Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Integrity registers #107

Merged
merged 1 commit into from
Feb 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions comid/cbor.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ func comidTags() cbor.TagSet {

func initCBOREncMode() (en cbor.EncMode, err error) {
encOpt := cbor.EncOptions{
Sort: cbor.SortCoreDeterministic,
IndefLength: cbor.IndefLengthForbidden,
TimeTag: cbor.EncTagRequired,
}
Expand Down
138 changes: 138 additions & 0 deletions comid/integrityregisters.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
// Copyright 2024 Contributors to the Veraison project.
// SPDX-License-Identifier: Apache-2.0
package comid

import (
"encoding/json"
"fmt"
"strconv"

"github.com/veraison/swid"
)

const TextType = "text"

// IRegisterIndex is the interface to hold register index
// Supported index types are uint and text
type IRegisterIndex interface{}

// IntegrityRegisters holds the Integrity Registers
type IntegrityRegisters struct {
m map[IRegisterIndex]Digests
}

func NewIntegrityRegisters() *IntegrityRegisters {
return &IntegrityRegisters{m: make(map[IRegisterIndex]Digests)}
}

// AddDigests allows inserting an array of digests at a specific index
// Supported index types are uint and text
func (i *IntegrityRegisters) AddDigests(index IRegisterIndex, digests Digests) error {
if len(digests) == 0 {
return fmt.Errorf("no digests to add")
}
for _, digest := range digests {
if err := i.AddDigest(index, digest); err != nil {
return fmt.Errorf("unable to add Digest: %w", err)
}
}
return nil
}

// AddDigest allows inserting a digest at a specific index
// Supported index types are uint and text
func (i *IntegrityRegisters) AddDigest(index IRegisterIndex, digest swid.HashEntry) error {
if i.m == nil {
return fmt.Errorf("no register to add digest")
}
switch t := index.(type) {
case string, uint, uint64:
i.m[t] = append(i.m[t], digest)
default:
return fmt.Errorf("unexpected type for index: %T", t)
}
return nil
}

func (i IntegrityRegisters) MarshalCBOR() ([]byte, error) {
return em.Marshal(i.m)
}

func (i *IntegrityRegisters) UnmarshalCBOR(data []byte) error {
return dm.Unmarshal(data, &i.m)
}

type keyTypeandVal struct {
KeyType string `json:"key_type"`
Value json.RawMessage
}

func (i IntegrityRegisters) MarshalJSON() ([]byte, error) {
jmap := make(map[string]json.RawMessage)
var newkey string
for key, val := range i.m {
var ktv keyTypeandVal
switch t := key.(type) {
case uint, uint64:
ktv.KeyType = UintType
newkey = fmt.Sprintf("%v", key)
case string:
ktv.KeyType = TextType
newkey = key.(string)
default:
return nil, fmt.Errorf("unknown type %T for index-type-choice", t)
}

newval, err := json.Marshal(val)
if err != nil {
return nil, err
}
ktv.Value = newval
Value, err := json.Marshal(ktv)
if err != nil {
return nil, err
}
jmap[newkey] = Value
}
return json.Marshal(jmap)
}

func (i *IntegrityRegisters) UnmarshalJSON(data []byte) error {
if i.m == nil {
i.m = make(map[IRegisterIndex]Digests)
}
jmap := make(map[string]json.RawMessage)
var index IRegisterIndex
if err := json.Unmarshal(data, &jmap); err != nil {
return fmt.Errorf("register map decoding failure: %w", err)
}
for key, val := range jmap {
var ktv keyTypeandVal
var d Digests

if err := json.Unmarshal(val, &ktv); err != nil {
return fmt.Errorf("unable to unmarshal keyTypeAndValue: %w", err)
}
if err := json.Unmarshal(ktv.Value, &d); err != nil {
return fmt.Errorf("unable to unmarshal Digests: %w", err)
}
switch ktv.KeyType {
case UintType:
u, err := strconv.Atoi(key)
if err != nil {
return fmt.Errorf("unable to convert key to uint: %w", err)
} else if u < 0 {
return fmt.Errorf("invalid negative integer key")
}
index = uint(u)
case TextType:
index = key
default:
return fmt.Errorf("unexpected key type for index: %s", ktv.KeyType)
}
if err := i.AddDigests(index, d); err != nil {
return fmt.Errorf("unable to add digests into register set: %w", err)
}
}
return nil
}
Loading
Loading