Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
setrofim committed Sep 4, 2023
1 parent df142c7 commit 682d065
Show file tree
Hide file tree
Showing 13 changed files with 288 additions and 114 deletions.
2 changes: 1 addition & 1 deletion comid/attestverifkey.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (
type AttestVerifKey struct {
_ struct{} `cbor:",toarray"`
Environment Environment `json:"environment"`
VerifKeys VerifKeys `json:"verification-keys"`
VerifKeys CryptoKeys `json:"verification-keys"`
}

func (o AttestVerifKey) Valid() error {
Expand Down
11 changes: 6 additions & 5 deletions comid/attestverifkey_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,26 +7,27 @@ import (
)

func TestAttestVerifKey_Valid_empty(t *testing.T) {
invalidKey := CryptoKey{TaggedPKIXBase64Key("")}

tvs := []struct {
env Environment
verifkey VerifKeys
verifkey CryptoKeys
testerr string
}{
{
env: Environment{},
verifkey: VerifKeys{},
verifkey: CryptoKeys{},
testerr: "environment validation failed: environment must not be empty",
},
{
env: Environment{Instance: NewInstanceUEID(TestUEID)},
verifkey: VerifKeys{},
verifkey: CryptoKeys{},
testerr: "verification keys validation failed: no verification key to validate",
},
{
env: Environment{Instance: NewInstanceUEID(TestUEID)},
verifkey: VerifKeys{{Key: ""}},
testerr: "verification keys validation failed: invalid verification key at index 0: verification key not set",
verifkey: CryptoKeys{&invalidKey},
testerr: "verification keys validation failed: invalid verification key at index 0: key value not set",
},
}
for _, tv := range tvs {
Expand Down
7 changes: 7 additions & 0 deletions comid/cbor.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,14 @@ func comidTags() cbor.TagSet {
//551: To Do see: https://github.com/veraison/corim/issues/32
552: TaggedSVN(0),
553: TaggedMinSVN(0),
554: TaggedPKIXBase64Key(""),
555: TaggedPKIXBase64Cert(""),
556: TaggedPKIXBase64CertPath(""),
557: TaggedThumbprint(""),
558: TaggedCOSEKey(""),
559: TaggedCertThumbprint(""),
560: TaggedRawValueBytes{},
561: TaggedCertPathThumbprint(""),
// PSA profile tags
600: TaggedImplID{},
601: TaggedPSARefValID{},
Expand Down
140 changes: 140 additions & 0 deletions comid/cryptokey.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
// Copyright 2023 Contributors to the Veraison project.
// SPDX-License-Identifier: Apache-2.0

package comid

import (
"crypto/x509"
"encoding/json"
"encoding/pem"
"errors"
"fmt"
)

const (
PKIXBase64KeyType = "PKIXBase64Key"
)

// CryptoKey is the struct implementing vCoRIM crypto-key-type-choice. See
// https://www.ietf.org/archive/id/draft-ietf-rats-corim-02.html#name-crypto-keys
type CryptoKey struct {
Value ICryptoKeyValue
}

func (o CryptoKey) String() string {
return o.Value.String()
}

func (o CryptoKey) Valid() error {
return o.Value.Valid()
}

func (o CryptoKey) MarshalJSON() ([]byte, error) {
value := struct {
Type string `json:"type"`
Value string `json:"value"`
}{
Value: o.Value.String(),
}

switch o.Value.(type) {
case TaggedPKIXBase64Key:
value.Type = PKIXBase64KeyType
default:
return nil, fmt.Errorf("unexpected ICryptoKeyValue type: %T", o.Value)
}

return json.Marshal(value)
}

func (o *CryptoKey) UnmarshalJSON(b []byte) error {
var value struct {
Type string `json:"type"`
Value string `json:"value"`
}

if err := json.Unmarshal(b, &value); err != nil {
return err
}

if value.Type == "" {
return errors.New("key type not set")
}

switch value.Type {
case PKIXBase64KeyType:
o.Value = TaggedPKIXBase64Key(value.Value)
default:
return fmt.Errorf("unexpected ICryptoKeyValue type: %q", value.Type)
}

return o.Valid()
}

func (o CryptoKey) MarshalCBOR() ([]byte, error) {
return em.Marshal(o.Value)
}

func (o *CryptoKey) UnmarshalCBOR(b []byte) error {
return dm.Unmarshal(b, &o.Value)
}

type ICryptoKeyValue interface {
String() string
Valid() error
}

type TaggedPKIXBase64Key string

func NewPKIXBase64Key(s string) (*CryptoKey, error) {
key := TaggedPKIXBase64Key(s)
if err := key.Valid(); err != nil {
return nil, err
}
return &CryptoKey{key}, nil
}

func MustNewPKIXBase64Key(s string) *CryptoKey {
key, err := NewPKIXBase64Key(s)
if err != nil {
panic(err)
}
return key
}

func (o TaggedPKIXBase64Key) String() string {
return string(o)
}

func (o TaggedPKIXBase64Key) Valid() error {
if string(o) == "" {
return errors.New("key value not set")
}

block, rest := pem.Decode([]byte(o))
if block == nil {
return errors.New("could not extract PKIX PEM block")
}

if len(rest) != 0 {
return errors.New("trailing data found after PEM block")
}

if block.Type != "PUBLIC KEY" {
return fmt.Errorf("unsupported PEM block type: %q", block.Type)
}

_, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
return fmt.Errorf("unable to parse public key: %w", err)
}

return nil
}

type TaggedPKIXBase64Cert string
type TaggedPKIXBase64CertPath string
type TaggedThumbprint string
type TaggedCOSEKey string
type TaggedCertThumbprint string
type TaggedCertPathThumbprint string
58 changes: 58 additions & 0 deletions comid/cryptokey_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// Copyright 2023 Contributors to the Veraison project.
// SPDX-License-Identifier: Apache-2.0

package comid

import (
"encoding/json"
"fmt"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func Test_CryptoKey_NewPKIXBase64Key(t *testing.T) {
key, err := NewPKIXBase64Key(TestECPubKey)
assert.NoError(t, err)
assert.Equal(t, TestECPubKey, key.String())

_, err = NewPKIXBase64Key("")
assert.EqualError(t, err, "key value not set")

noPem := "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEW1BvqF+/ry8BWa7ZEMU1xYYHEQ8BlLT4MFHOaO+ICTtIvrEeEpr/sfTAP66H2hCHdb5HEXKtRKod6QLcOLPA1Q=="
_, err = NewPKIXBase64Key(noPem)
assert.EqualError(t, err, "could not extract PKIX PEM block")

badKey := "-----BEGIN PUBLIC KEY-----\nDEADBEEF\n-----END PUBLIC KEY-----"
_, err = NewPKIXBase64Key(badKey)
assert.Contains(t, err.Error(), "unable to parse public key")
}

func Test_CryptoKey_JSON(t *testing.T) {
key := MustNewPKIXBase64Key(TestECPubKey)
data, err := json.Marshal(key)
require.NoError(t, err)

expected := fmt.Sprintf(`{"type": "PKIXBase64Key", "value": %q}`, TestECPubKey)
assert.JSONEq(t, expected, string(data))

var key2 CryptoKey
err = json.Unmarshal(data, &key2)
require.NoError(t, err)
assert.Equal(t, *key, key2)
}

func Test_CryptoKey_CBOR(t *testing.T) {
key := MustNewPKIXBase64Key(TestECPubKey)
data, err := em.Marshal(key)
require.NoError(t, err)

expected := MustHexDecode(t, "d9022a78b12d2d2d2d2d424547494e205055424c4943204b45592d2d2d2d2d0a4d466b77457759484b6f5a497a6a3043415159494b6f5a497a6a304441516344516741455731427671462b2f727938425761375a454d553178595948455138420a6c4c54344d46484f614f2b4943547449767245654570722f7366544150363648326843486462354845584b74524b6f6436514c634f4c504131513d3d0a2d2d2d2d2d454e44205055424c4943204b45592d2d2d2d2d")
assert.Equal(t, expected, data)

var key2 CryptoKey
err = dm.Unmarshal(data, &key2)
require.NoError(t, err)
assert.Equal(t, key.String(), key2.String())
}
18 changes: 9 additions & 9 deletions comid/verifkeys.go → comid/cryptokeys.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,23 @@ package comid

import "fmt"

// VerifKeys is an array of VerifKey
type VerifKeys []VerifKey
// CryptoKeys is an array of ICryptoKey
type CryptoKeys []*CryptoKey

// NewVerifKeys instantiates an empty VerifKeys array
func NewVerifKeys() *VerifKeys {
return new(VerifKeys)
// NewCryptoKeys instantiates an empty CryptoKeys array
func NewCryptoKeys() *CryptoKeys {
return new(CryptoKeys)
}

// AddVerifKey adds the supplied VerifKey to the target VerifKeys array
func (o *VerifKeys) AddVerifKey(v *VerifKey) *VerifKeys {
// AddCryptoKey adds the supplied ICryptoKey to the target CryptoKeys array
func (o *CryptoKeys) AddCryptoKey(v *CryptoKey) *CryptoKeys {
if o != nil && v != nil {
*o = append(*o, *v)
*o = append(*o, v)
}
return o
}

func (o VerifKeys) Valid() error {
func (o CryptoKeys) Valid() error {
if len(o) == 0 {
return fmt.Errorf("no verification key to validate")
}
Expand Down
2 changes: 1 addition & 1 deletion comid/devidentitykey.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import "fmt"
type DevIdentityKey struct {
_ struct{} `cbor:",toarray"`
Environment Environment `json:"environment"`
VerifKeys VerifKeys `json:"verification-keys"`
VerifKeys CryptoKeys `json:"verification-keys"`
}

func (o DevIdentityKey) Valid() error {
Expand Down
11 changes: 6 additions & 5 deletions comid/devidentitykey_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,27 @@ import (
)

func TestDevIdentityKey_Valid_empty(t *testing.T) {
invalidKey := CryptoKey{TaggedPKIXBase64Key("")}

tvs := []struct {
env Environment
verifkey VerifKeys
verifkey CryptoKeys
testerr string
}{
{
env: Environment{},
verifkey: VerifKeys{},
verifkey: CryptoKeys{},
testerr: "environment validation failed: environment must not be empty",
},
{
env: Environment{Instance: NewInstanceUEID(TestUEID)},
verifkey: VerifKeys{},
verifkey: CryptoKeys{},
testerr: "verification keys validation failed: no verification key to validate",
},
{
env: Environment{Instance: NewInstanceUEID(TestUEID)},
verifkey: VerifKeys{{Key: ""}},
testerr: "verification keys validation failed: invalid verification key at index 0: verification key not set",
verifkey: CryptoKeys{&invalidKey},
testerr: "verification keys validation failed: invalid verification key at index 0: key value not set",
},
}
for _, tv := range tvs {
Expand Down
6 changes: 3 additions & 3 deletions comid/example_psa_keys_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ func Example_psa_keys() {
// output:
// ImplementationID: 61636d652d696d706c656d656e746174696f6e2d69642d303030303030303031
// InstanceID: 01ceebae7b8927a3227e5303cf5e0f1f7b34bb542ad7250ac03fbcde36ec2f1508
// IAK public key: 4d466b77457759484b6f5a497a6a3043415159494b6f5a497a6a30444151634451674145466e3074616f41775233506d724b6b594c74417344396f30354b534d366d6267664e436770754c306736567054486b5a6c3733776b354244786f56376e2b4f656565306949716b5733484d5a54334554696e694a64673d3d
// IAK public key: 2d2d2d2d2d424547494e205055424c4943204b45592d2d2d2d2d0a4d466b77457759484b6f5a497a6a3043415159494b6f5a497a6a304441516344516741455731427671462b2f727938425761375a454d553178595948455138420a6c4c54344d46484f614f2b4943547449767245654570722f7366544150363648326843486462354845584b74524b6f6436514c634f4c504131513d3d0a2d2d2d2d2d454e44205055424c4943204b45592d2d2d2d2d
// ImplementationID: 61636d652d696d706c656d656e746174696f6e2d69642d303030303030303031
// InstanceID: 014ca3e4f50bf248c39787020d68ffd05c88767751bf2645ca923f57a98becd296
// IAK public key: 4d466b77457759484b6f5a497a6a3043415159494b6f5a497a6a304441516344516741453656777165376879334f385970612b425545544c556a424e5533724558565579743958485237484a574c473758544b51643969316b565258654250444c466e66597275312f657578526e4a4d374839556f46444c64413d3d
// IAK public key: 2d2d2d2d2d424547494e205055424c4943204b45592d2d2d2d2d0a4d466b77457759484b6f5a497a6a3043415159494b6f5a497a6a304441516344516741455731427671462b2f727938425761375a454d553178595948455138420a6c4c54344d46484f614f2b4943547449767245654570722f7366544150363648326843486462354845584b74524b6f6436514c634f4c504131513d3d0a2d2d2d2d2d454e44205055424c4943204b45592d2d2d2d2d
}

func extractKeys(c *Comid) error {
Expand Down Expand Up @@ -60,7 +60,7 @@ func extractPSAKey(k AttestVerifKey) error {
return fmt.Errorf("more than one key")
}

fmt.Printf("IAK public key: %x\n", k.VerifKeys[0].Key)
fmt.Printf("IAK public key: %x\n", k.VerifKeys[0])

return nil
}
Expand Down
Loading

0 comments on commit 682d065

Please sign in to comment.