diff --git a/comid/attestverifkey.go b/comid/attestverifkey.go index 2529952a..74ab469d 100644 --- a/comid/attestverifkey.go +++ b/comid/attestverifkey.go @@ -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 { diff --git a/comid/attestverifkey_test.go b/comid/attestverifkey_test.go index 3a7241f6..3acd0329 100644 --- a/comid/attestverifkey_test.go +++ b/comid/attestverifkey_test.go @@ -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 { diff --git a/comid/cbor.go b/comid/cbor.go index fec19025..b3d9b6ca 100644 --- a/comid/cbor.go +++ b/comid/cbor.go @@ -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{}, diff --git a/comid/cryptokey.go b/comid/cryptokey.go new file mode 100644 index 00000000..7cb8772d --- /dev/null +++ b/comid/cryptokey.go @@ -0,0 +1,469 @@ +// Copyright 2023 Contributors to the Veraison project. +// SPDX-License-Identifier: Apache-2.0 + +package comid + +import ( + "bytes" + "crypto" + "crypto/x509" + "encoding/base64" + "encoding/json" + "encoding/pem" + "errors" + "fmt" + + "github.com/fxamacker/cbor/v2" + "github.com/veraison/go-cose" +) + +const ( + PKIXBase64KeyType = "PKIXBase64Key" + PKIXBase64CertType = "PKIXBase64Cert" + PKIXBase64CertPathType = "PKIXBase64CertPath" + COSEKeyType = "COSEKey" +) + +// 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 NewCryptoKey(k []byte, typ string) (*CryptoKey, error) { + switch typ { + case PKIXBase64KeyType: + return NewPKIXBase64Key(string(k)) + case PKIXBase64CertType: + return NewPKIXBase64Cert(string(k)) + case PKIXBase64CertPathType: + return NewPKIXBase64CertPath(string(k)) + case COSEKeyType: + return NewCOSEKey(k) + default: + return nil, fmt.Errorf("unexpected CryptoKey type: %s", typ) + } +} + +func MustNewCryptoKey(k []byte, typ string) *CryptoKey { + key, err := NewCryptoKey(k, typ) + if err != nil { + panic(err) + } + + return key +} + +func (o CryptoKey) String() string { + return o.Value.String() +} + +func (o CryptoKey) Valid() error { + return o.Value.Valid() +} + +func (o CryptoKey) PublicKey() (crypto.PublicKey, error) { + return o.Value.PublicKey() +} + +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 + case TaggedPKIXBase64Cert: + value.Type = PKIXBase64CertType + case TaggedPKIXBase64CertPath: + value.Type = PKIXBase64CertPathType + case TaggedCOSEKey: + value.Type = COSEKeyType + 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) + case PKIXBase64CertType: + o.Value = TaggedPKIXBase64Cert(value.Value) + case PKIXBase64CertPathType: + o.Value = TaggedPKIXBase64CertPath(value.Value) + case COSEKeyType: + bytes, err := base64.StdEncoding.DecodeString(value.Value) + if err != nil { + return fmt.Errorf("base64 decode error: %w", err) + } + o.Value = TaggedCOSEKey(bytes) + 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 + PublicKey() (crypto.PublicKey, 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 { + _, err := o.PublicKey() + return err +} + +func (o TaggedPKIXBase64Key) PublicKey() (crypto.PublicKey, error) { + if string(o) == "" { + return nil, errors.New("key value not set") + } + + block, rest := pem.Decode([]byte(o)) + if block == nil { + return nil, errors.New("could not decode PEM block") + } + + if len(rest) != 0 { + return nil, errors.New("trailing data found after PEM block") + } + + if block.Type != "PUBLIC KEY" { + return nil, fmt.Errorf( + "unexpected PEM block type: %q, expected \"PUBLIC KEY\"", + block.Type, + ) + } + + key, err := x509.ParsePKIXPublicKey(block.Bytes) + if err != nil { + return nil, fmt.Errorf("unable to parse public key: %w", err) + } + + return key, nil +} + +type TaggedPKIXBase64Cert string + +func NewPKIXBase64Cert(s string) (*CryptoKey, error) { + cert := TaggedPKIXBase64Cert(s) + if err := cert.Valid(); err != nil { + return nil, err + } + return &CryptoKey{cert}, nil +} + +func MustNewPKIXBase64Cert(s string) *CryptoKey { + cert, err := NewPKIXBase64Cert(s) + if err != nil { + panic(err) + } + return cert +} + +func (o TaggedPKIXBase64Cert) String() string { + return string(o) +} + +func (o TaggedPKIXBase64Cert) Valid() error { + _, err := o.cert() + return err +} + +func (o TaggedPKIXBase64Cert) PublicKey() (crypto.PublicKey, error) { + cert, err := o.cert() + if err != nil { + return nil, err + } + + if cert.PublicKey == nil { + return nil, errors.New("cert does not contain a crypto.PublicKey") + } + + return cert.PublicKey, nil +} + +func (o TaggedPKIXBase64Cert) cert() (*x509.Certificate, error) { + if string(o) == "" { + return nil, errors.New("cert value not set") + } + + block, rest := pem.Decode([]byte(o)) + if block == nil { + return nil, errors.New("could not decode PEM block") + } + + if len(rest) != 0 { + return nil, errors.New("trailing data found after PEM block") + } + + if block.Type != "CERTIFICATE" { + return nil, fmt.Errorf( + "unexpected PEM block type: %q, expected \"CERTIFICATE\"", + block.Type, + ) + } + + cert, err := x509.ParseCertificate(block.Bytes) + if err != nil { + return nil, fmt.Errorf("could not parse x509 cert: %w", err) + } + + return cert, nil +} + +type TaggedPKIXBase64CertPath string + +func NewPKIXBase64CertPath(s string) (*CryptoKey, error) { + cert := TaggedPKIXBase64CertPath(s) + if err := cert.Valid(); err != nil { + return nil, err + } + return &CryptoKey{cert}, nil +} + +func MustNewPKIXBase64CertPath(s string) *CryptoKey { + cert, err := NewPKIXBase64CertPath(s) + if err != nil { + panic(err) + } + return cert +} + +func (o TaggedPKIXBase64CertPath) String() string { + return string(o) +} + +func (o TaggedPKIXBase64CertPath) Valid() error { + _, err := o.certPath() + return err +} + +func (o TaggedPKIXBase64CertPath) PublicKey() (crypto.PublicKey, error) { + certs, err := o.certPath() + if err != nil { + return nil, err + } + + if len(certs) == 0 { + return nil, errors.New("empty cert path") + } + + if certs[0].PublicKey == nil { + return nil, errors.New("leaf cert does not contain a crypto.PublicKey") + } + + return certs[0].PublicKey, nil +} + +func (o TaggedPKIXBase64CertPath) certPath() ([]*x509.Certificate, error) { + if string(o) == "" { + return nil, errors.New("cert value not set") + } + + var certs []*x509.Certificate + var block *pem.Block + var rest []byte + rest = []byte(o) + i := 0 + for { + if len(rest) == 0 { + break + } + + block, rest = pem.Decode(rest) + if block == nil { + return nil, fmt.Errorf("could not decode PEM block %d", i) + } + + if block.Type != "CERTIFICATE" { + return nil, fmt.Errorf( + "unexpected type for PEM block %d: %q, expected \"CERTIFICATE\"", + i, block.Type, + ) + } + + cert, err := x509.ParseCertificate(block.Bytes) + if err != nil { + return nil, fmt.Errorf( + "could not parse x509 cert in PEM block %d: %w", + i, err, + ) + } + + certs = append(certs, cert) + + i++ + } + + return certs, nil +} + +type TaggedCOSEKey []byte + +func NewCOSEKey(b []byte) (*CryptoKey, error) { + key := TaggedCOSEKey(b) + if err := key.Valid(); err != nil { + return nil, err + } + return &CryptoKey{key}, nil +} + +func MustNewCOSEKey(b []byte) *CryptoKey { + key, err := NewCOSEKey(b) + if err != nil { + panic(err) + } + + return key +} + +func (o TaggedCOSEKey) String() string { + return base64.StdEncoding.EncodeToString(o) +} + +func (o TaggedCOSEKey) Valid() error { + if len(o) == 0 { + return errors.New("empty COSE_Key bytes") + } + + var err error + + // CBOR Major type 4 == array == COSE_KeySet. Key sets are currently + // not supported by go-cose library. + if ((o[0] & 0xe0) >> 5) == 4 { + _, err = o.coseKeySet() + } else { + _, err = o.coseKey() + } + return err +} + +func (o TaggedCOSEKey) PublicKey() (crypto.PublicKey, error) { + if len(o) == 0 { + return nil, errors.New("empty COSE_Key value") + } + + // CBOR Major type 4 == array == COSE_KeySet. Key sets are currently + // not supported by go-cose library. + if ((o[0] & 0xe0) >> 5) == 4 { + keySet, err := o.coseKeySet() + if err != nil { + return nil, err + } + + if len(keySet) == 0 { + return nil, errors.New("empty COSE_KeySet") + } else if len(keySet) > 1 { + return nil, errors.New("COSE_KeySet contains more than one key") + } + + return keySet[0].PublicKey() + } + + coseKey, err := o.coseKey() + if err != nil { + return nil, err + } + + return coseKey.PublicKey() +} + +func (o TaggedCOSEKey) MarshalCBOR() ([]byte, error) { + var buf bytes.Buffer + + // encodeMarshalerType in github.com/fxamacker/cbor/v2 does not look up + // assocated Tags, so we have to write them ourselves. + if _, err := buf.Write([]byte{0xd9, 0x02, 0x2e}); err != nil { // tag 558 + return nil, err + } + + if _, err := buf.Write(o); err != nil { + return nil, err + } + + return buf.Bytes(), nil +} + +func (o *TaggedCOSEKey) UnmarshalCBOR(b []byte) error { + // the first 3 bytes are the tag + if !bytes.Equal([]byte{0xd9, 0x02, 0x2e}, b[:3]) { + return errors.New("did not see CBOR tag 588 at the beginning of COSE_Key structure") + } + + *o = b[3:] + return nil +} + +func (o TaggedCOSEKey) coseKey() (*cose.Key, error) { + coseKey := new(cose.Key) + if err := coseKey.UnmarshalCBOR(o); err != nil { + return nil, err + } + + return coseKey, nil +} + +func (o TaggedCOSEKey) coseKeySet() ([]*cose.Key, error) { + var keySet []*cose.Key + if err := cbor.Unmarshal(o, &keySet); err != nil { + return nil, err + } + + return keySet, nil +} + +type TaggedThumbprint string +type TaggedCertThumbprint string +type TaggedCertPathThumbprint string diff --git a/comid/cryptokey_test.go b/comid/cryptokey_test.go new file mode 100644 index 00000000..b8a14406 --- /dev/null +++ b/comid/cryptokey_test.go @@ -0,0 +1,202 @@ +// Copyright 2023 Contributors to the Veraison project. +// SPDX-License-Identifier: Apache-2.0 + +package comid + +import ( + "encoding/base64" + "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) + require.NoError(t, err) + assert.Equal(t, TestECPubKey, key.String()) + pub, err := key.PublicKey() + assert.NoError(t, err) + assert.NotNil(t, pub) + + _, err = NewPKIXBase64Key("") + assert.EqualError(t, err, "key value not set") + + noPem := "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEW1BvqF+/ry8BWa7ZEMU1xYYHEQ8BlLT4MFHOaO+ICTtIvrEeEpr/sfTAP66H2hCHdb5HEXKtRKod6QLcOLPA1Q==" + _, err = NewPKIXBase64Key(noPem) + assert.EqualError(t, err, "could not decode PEM block") + + badBlock := "-----BEGIN CERTIFICATE-----\nDEADBEEF\n-----END CERTIFICATE-----" + _, err = NewPKIXBase64Key(badBlock) + assert.Contains(t, err.Error(), "unexpected PEM block type") + + 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_NewPKIXBase64Cert(t *testing.T) { + cert, err := NewPKIXBase64Cert(TestCert) + require.NoError(t, err) + assert.Equal(t, TestCert, cert.String()) + pub, err := cert.PublicKey() + assert.NoError(t, err) + assert.NotNil(t, pub) + + _, err = NewPKIXBase64Cert("") + assert.EqualError(t, err, "cert value not set") + + noPem := "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEW1BvqF+/ry8BWa7ZEMU1xYYHEQ8BlLT4MFHOaO+ICTtIvrEeEpr/sfTAP66H2hCHdb5HEXKtRKod6QLcOLPA1Q==" + _, err = NewPKIXBase64Cert(noPem) + assert.EqualError(t, err, "could not decode PEM block") + + badBlock := "-----BEGIN PUBLIC KEY-----\nDEADBEEF\n-----END PUBLIC KEY-----" + _, err = NewPKIXBase64Cert(badBlock) + assert.Contains(t, err.Error(), "unexpected PEM block type") + + badCert := "-----BEGIN CERTIFICATE-----\nDEADBEEF\n-----END CERTIFICATE-----" + _, err = NewPKIXBase64Cert(badCert) + assert.Contains(t, err.Error(), "could not parse x509 cert") +} + +func Test_CryptoKey_NewPKIXBase64CertPath(t *testing.T) { + certs, err := NewPKIXBase64CertPath(TestCertPath) + assert.NoError(t, err) + assert.Equal(t, TestCertPath, certs.String()) + pub, err := certs.PublicKey() + assert.NoError(t, err) + assert.NotNil(t, pub) + + _, err = NewPKIXBase64CertPath("") + assert.EqualError(t, err, "cert value not set") + + noPem := "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEW1BvqF+/ry8BWa7ZEMU1xYYHEQ8BlLT4MFHOaO+ICTtIvrEeEpr/sfTAP66H2hCHdb5HEXKtRKod6QLcOLPA1Q==" + _, err = NewPKIXBase64CertPath(noPem) + assert.EqualError(t, err, "could not decode PEM block 0") + + badBlock := "-----BEGIN PUBLIC KEY-----\nDEADBEEF\n-----END PUBLIC KEY-----" + _, err = NewPKIXBase64CertPath(badBlock) + assert.Contains(t, err.Error(), "unexpected type for PEM block 0") + + badCert := "-----BEGIN CERTIFICATE-----\nDEADBEEF\n-----END CERTIFICATE-----" + _, err = NewPKIXBase64CertPath(badCert) + assert.Contains(t, err.Error(), "could not parse x509 cert in PEM block 0") +} + +func Test_CryptoKey_NewCOSEKey(t *testing.T) { + key, err := NewCOSEKey(TestCOSEKey) + require.NoError(t, err) + assert.Equal(t, base64.StdEncoding.EncodeToString(TestCOSEKey), key.String()) + pub, err := key.PublicKey() + assert.NoError(t, err) + assert.NotNil(t, pub) + + _, err = NewCOSEKey([]byte{}) + assert.EqualError(t, err, "empty COSE_Key bytes") + + _, err = NewCOSEKey([]byte("DEADBEEF")) + assert.Contains(t, err.Error(), "cbor: cannot unmarshal") + + badKey := []byte{ // taken from go-cose unit tests + 0xa2, // map(2) + 0x01, 0x01, // kty: OKP + 0x03, 0x41, 0x01, // alg: bstr(1) + } + _, err = NewCOSEKey(badKey) + assert.Contains(t, err.Error(), "alg: invalid type") + + keySet, err := NewCOSEKey(TestCOSEKeySetOne) + require.NoError(t, err) + pub, err = keySet.PublicKey() + assert.NoError(t, err) + assert.NotNil(t, pub) + + keySet, err = NewCOSEKey(TestCOSEKeySetMulti) + require.NoError(t, err) + _, err = keySet.PublicKey() + assert.Contains(t, err.Error(), "COSE_KeySet contains more than one key") +} + +func Test_CryptoKey_JSON(t *testing.T) { + for _, tv := range []struct { + Type string + In []byte + Out string + }{ + { + Type: PKIXBase64KeyType, + In: []byte(TestECPubKey), + Out: TestECPubKey, + }, + { + Type: PKIXBase64CertType, + In: []byte(TestCert), + Out: TestCert, + }, + { + Type: PKIXBase64CertPathType, + In: []byte(TestCertPath), + Out: TestCertPath, + }, + { + Type: COSEKeyType, + In: TestCOSEKey, + Out: base64.StdEncoding.EncodeToString(TestCOSEKey), + }, + } { + key := MustNewCryptoKey(tv.In, tv.Type) + data, err := json.Marshal(key) + require.NoError(t, err) + + expected := fmt.Sprintf(`{"type": %q, "value": %q}`, tv.Type, tv.Out) + 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) { + for _, tv := range []struct { + Type string + In []byte + Out string + }{ + { + Type: PKIXBase64KeyType, + In: []byte(TestECPubKey), + Out: "d9022a78b12d2d2d2d2d424547494e205055424c4943204b45592d2d2d2d2d0a4d466b77457759484b6f5a497a6a3043415159494b6f5a497a6a304441516344516741455731427671462b2f727938425761375a454d553178595948455138420a6c4c54344d46484f614f2b4943547449767245654570722f7366544150363648326843486462354845584b74524b6f6436514c634f4c504131513d3d0a2d2d2d2d2d454e44205055424c4943204b45592d2d2d2d2d", + }, + { + Type: PKIXBase64CertType, + In: []byte(TestCert), + Out: "d9022b7902c82d2d2d2d2d424547494e2043455254494649434154452d2d2d2d2d0a4d4949423454434341596567417749424167495547687241394d337951494671636b413276366e5165776d4633304977436759494b6f5a497a6a3045417749770a5254454c4d416b474131554542684d4351565578457a415242674e564241674d436c4e766257557455335268644755784954416642674e5642416f4d47456c750a64475679626d5630494664705a47647064484d6755485235494578305a444167467730794d7a41354d4451784d5441784e446861474138794d4455784d4445780a4f5445784d4445304f466f775254454c4d416b474131554542684d4351565578457a415242674e564241674d436c4e76625755745533526864475578495441660a42674e5642416f4d47456c7564475679626d5630494664705a47647064484d6755485235494578305a44425a4d424d4742797147534d343941674547434371470a534d3439417745484130494142467451623668667636387641566d75325244464e63574742784550415a53302b4442527a6d6a7669416b37534c367848684b610a2f37483077442b7568396f516833572b527846797255537148656b433344697a774e576a557a42524d423047413155644467515742425157704e5062366557440a534d2f2b6a7770627a6f4f33694867344c54416642674e5648534d454744415767425157704e506236655744534d2f2b6a7770627a6f4f33694867344c5441500a42674e5648524d4241663845425441444151482f4d416f4743437147534d343942414d43413067414d455543494161794e49463065434a445a6d637271526a480a663968384778654944556e4c716c646549764e66612b39534169454139554c4254506a6e545568596c653232364f416a67327364686b587462334d75304530460a6e75556d7349513d0a2d2d2d2d2d454e442043455254494649434154452d2d2d2d2d", + }, + { + Type: PKIXBase64CertPathType, + In: []byte(TestCertPath), + Out: "d9022c7919272d2d2d2d2d424547494e2043455254494649434154452d2d2d2d2d0a4d494943656a4343416979674177494241674955497065567756684e2f71594c67744e4a6c775a484a6a2b49542f7777425159444b3256774d444d784d5441760a42674e56424155544b4464684d445a6c5a5755304d5749334f446c6d4e4467324d3251344e6d49344e7a6334596a46684d6a417859545a6d5a57526b4e5459770a4942634e4d5467774d7a49794d6a4d314f545535576867504f546b354f5445794d7a45794d7a55354e546c614d444d784d54417642674e56424155544b4449790a4f5463354e574d784e5467305a475a6c59545977596a67795a444d304f546b334d4459304e7a49324d3259344f44526d5a6d4d774b6a414642674d725a5841440a495141565569377856796e4d3835554a366c77566f6d767053654f494236584362766b6f4649667653755a3752714f43415534776767464b4d423847413155640a497751594d42614146486f4737755162654a394959396872683369786f67476d2f7431574d4230474131556444675157424251696c3558425745332b706775430a30306d58426b636d503468502f44414f42674e56485138424166384542414d434167517744775944565230544151482f42415577417745422f7a43423567594b0a4b7759424241485765514942474145422f77534231444342306142434245414d7476656f414a783476335175394b386749304a326b70376967427634566439420a48454d746c665a4f5164793679444f6c6350725147596a537a7776416a4668384441343662712b78476a33314e46557936706b686f304945514e436b6c2f4b660a6245534c5a364f684563644f6e417a69533567783554714a6d463232794b436a49764c524956784e49685a4e32456e4d41746d3464703145477550424c5572410a747a58686c7a755a754b31785636536b516752415365536f486d6e4e674c686e6e454b54574b7a634c326a7a506a4f41465551544e52792b694f67686c7549330a66696347364e4237634d624c415a6b665631326c696853562b2f37694b33544a3062554e6a51675770615944436745424d4155474179746c63414e42414875360a447475504e4f7572634158632b3431515932336859384b526b42434b434537706873694977526662784b4d4c6c6446474e354f79745166524f5161576f4163760a4957547156394a527a47516147596e6c4c77453d0a2d2d2d2d2d454e442043455254494649434154452d2d2d2d2d0a2d2d2d2d2d424547494e2043455254494649434154452d2d2d2d2d0a4d494943656a434341697967417749424167495545626165377531635037732b472f434462324e75366e505264596b77425159444b3256774d444d784d5441760a42674e56424155544b4449794f5463354e574d784e5467305a475a6c59545977596a67795a444d304f546b334d4459304e7a49324d3259344f44526d5a6d4d770a4942634e4d5467774d7a49794d6a4d314f545535576867504f546b354f5445794d7a45794d7a55354e546c614d444d784d54417642674e56424155544b4445780a596a59355a57566c5a575131597a4e6d596d497a5a5446695a6a41344d7a5a6d4e6a4d325a5756684e7a4e6b4d5463314f446b774b6a414642674d725a5841440a4951447a676b54523775766f50394e427a5345423967752f6c70642b4e4c33384f5659516c30666569574b582b614f43415534776767464b4d423847413155640a497751594d42614146434b586c6346595466366d43344c54535a63475279592f69452f384d423047413155644467515742425152747037753756772f757a34620a38494e7659323771633946316954414f42674e56485138424166384542414d434167517744775944565230544151482f42415577417745422f7a43423567594b0a4b7759424241485765514942474145422f775342314443423061424342454262734b67636176452b75793141786b49646c376c4e39696648793348452b4c69750a386c4d453237434d59396b557479772f6c657331483876706d537978684f3461545767777577516137596e39486f4777654548736f304945514862383730484e0a3162556e396e46696831315342416a396c6f6270754a354772492f6d2b673648776d6f517a35556c79306f584d4e6e78454d4137664c327a613031796e4770490a2f757a383272554932764c57536c476b5167524133584667496f56496d6f736441677675504856616f6276334a476a476c332b41444f543163366454366451450a646e4f62524e7564593871687a547666455752346553364f4a746679724f65527958656b324f564a68365944436745424d4155474179746c63414e42414a496a0a7946717764725a435375596d43342b5a555563414e4b514b41314b63524669496c4b63672f7070774b56796b5058624168736e365343567157474137763743650a4c6935684f72482f566c6a41514163645967633d0a2d2d2d2d2d454e442043455254494649434154452d2d2d2d2d0a2d2d2d2d2d424547494e2043455254494649434154452d2d2d2d2d0a4d494943656a43434169796741774942416749555955584d636656334d756370756e6c313933777558784242722f6777425159444b3256774d444d784d5441760a42674e56424155544b444578596a59355a57566c5a575131597a4e6d596d497a5a5446695a6a41344d7a5a6d4e6a4d325a5756684e7a4e6b4d5463314f446b770a4942634e4d5467774d7a49794d6a4d314f545535576867504f546b354f5445794d7a45794d7a55354e546c614d444d784d54417642674e56424155544b4459780a4e44566a597a63785a6a55334e7a4d795a5463794f574a684e7a6b334e5759334e324d795a54566d4d5441304d57466d5a6a67774b6a414642674d725a5841440a4951424a6f3950677665486a30616876384d6b574851554753785a2f77535464614e4e5a6264425a4e61314c30614f43415534776767464b4d423847413155640a497751594d426141464247326e75377458442b37506876776732396a6275707a3058574a4d423047413155644467515742425268526378783958637935796d360a6558583366433566454547762b44414f42674e56485138424166384542414d434167517744775944565230544151482f42415577417745422f7a43423567594b0a4b7759424241485765514942474145422f775342314443423061424342454132616e736566305362524e386a37367735687a57352f54435846497351634552730a62534b51594e6e71756731726a4543506e686533412f385a3657477861444b316568452b6e72637643394252677257705536374a6f30494551495a795243484b0a394855692f387936563950305a754e45766d64704564496d51303952552f6c4e507358587879763056456d693657447334654679706d4252394c5658425875640a7243647575767953367442577353366b516752416257525443625872642f716c4c504949383549504238705a3975582b586749484934735348662b33463673650a68412f38307a55427a5369364f7a6330442b496259594259786472585a456b6e386955575364516f6b4b5944436745424d4155474179746c63414e42414b6c4a0a2f335659616c5a6d3958624547544b725652616f43566f55785156483375644d726b39796f716a466f77433465336b6453426c474766386d59454937787673410a6172316b6632624758542f634565464749774d3d0a2d2d2d2d2d454e442043455254494649434154452d2d2d2d2d0a2d2d2d2d2d424547494e2043455254494649434154452d2d2d2d2d0a4d494943656a4343416979674177494241674955582b69765048544f6d76566b744d6e514759516a754e6c6b2f445577425159444b3256774d444d784d5441760a42674e56424155544b4459784e44566a597a63785a6a55334e7a4d795a5463794f574a684e7a6b334e5759334e324d795a54566d4d5441304d57466d5a6a67770a4942634e4d5467774d7a49794d6a4d314f545535576867504f546b354f5445794d7a45794d7a55354e546c614d444d784d54417642674e56424155544b44566d0a5a5468685a6a4e6a4e7a526a5a546c685a6a55324e474930597a6c6b4d4445354f4451794d3249345a446b324e475a6a4d7a55774b6a414642674d725a5841440a495143367533626c77453442317864504d65554a50363537502f6d376953742b486572677647626b6b53784d72714f43415534776767464b4d423847413155640a497751594d426141464746467a484831647a4c6e4b627035646664384c6c385151612f344d423047413155644467515742425266364b3838644d3661395753300a7964415a68434f34325754384e54414f42674e56485138424166384542414d434167517744775944565230544151482f42415577417745422f7a43423567594b0a4b7759424241485765514942474145422f7753423144434230614243424543347a326a754a4978356a4437783649754d4e55693754556f6d577843516639516e0a434a39316f7a586b30764a396e4a4f33526476654a7662765a686f5066445149593854695a7038554b447834652b7a573063486b6f304945514f68704d4a36470a45584c5a67487452416d38316f5858414345462b6e6576324d437636434f6875527446797047394233666f526d32726e46556261565a7330704c66424d4738730a7353524a526361775843696d57344f6b5167524132374667783741343231327170714c61786150643974492b7a70664b57724c59634c7832302b444c6663716e0a4249497055434e3330537541753731736534782f696c634b7561574f4f307144673334534a45774679715944436745424d4155474179746c63414e42414374540a3558727836353971476e79776d6c4b48646c484f364264376650626f797a794951686f4574464e75694433576a44672f56777a38634e43556b552b74684737660a432b575a68637041636b446c6461692b5041633d0a2d2d2d2d2d454e442043455254494649434154452d2d2d2d2d0a2d2d2d2d2d424547494e2043455254494649434154452d2d2d2d2d0a4d494943656a434341697967417749424167495558583044564f796c6745697037727a7679614e4665676344545a4977425159444b3256774d444d784d5441760a42674e56424155544b44566d5a5468685a6a4e6a4e7a526a5a546c685a6a55324e474930597a6c6b4d4445354f4451794d3249345a446b324e475a6a4d7a55770a4942634e4d5467774d7a49794d6a4d314f545535576867504f546b354f5445794d7a45794d7a55354e546c614d444d784d54417642674e56424155544b44566b0a4e3251774d7a55305a574e684e5467774e4468684f57566c596d4e6c5a6d4d3559544d304e5464684d4463774d7a526b4f5449774b6a414642674d725a5841440a495143696143326748684d4f31706265516255674c48685367464250442f7a584e414777414873573237322b63364f43415534776767464b4d423847413155640a497751594d42614146462f6f727a78307a7072315a4c544a30426d4549376a5a5a5077314d42304741315564446751574242526466514e55374b5741534b6e750a764f2f4a6f30563642774e4e6b6a414f42674e56485138424166384542414d434167517744775944565230544151482f42415577417745422f7a43423567594b0a4b7759424241485765514942474145422f7753423144434230614243424542595877532f6d7272582b44344d717a4d384a546d49484339584871734a664f47630a623266714259505830555172694c44526c316170484e32327131452b4665614c4857424532755864613151366c596b51416148696f30494551474b483845414e0a4d7631504d4d62577364645a657732472f44522b4139746253693748363830794253653943652b6774616242617251444870673942384c65626d6f50706458740a4154762b6f537a7a6b2b5a7565564b6b516752417a74625532517a614a62634735747745596a59416746757443626e67706732742f32657a3751544e6e344e6d0a723934704f4178384c4970753643662f577a6376642f346b4c4f76577853622f62754d716247767273715944436745424d4155474179746c63414e42414d64780a66466e6b35327275346656354a3167734642746c6879356d4662516e49526947484c78424661544a6b39692b69784f35714662526a71763748512f6a475573490a7372554a513465324a456e534e616b4e6367453d0a2d2d2d2d2d454e442043455254494649434154452d2d2d2d2d0a2d2d2d2d2d424547494e2043455254494649434154452d2d2d2d2d0a4d494943656a434341697967417749424167495541316f576f57507756644335474f3362516f4433726f446531536f77425159444b3256774d444d784d5441760a42674e56424155544b44566b4e3251774d7a55305a574e684e5467774e4468684f57566c596d4e6c5a6d4d3559544d304e5464684d4463774d7a526b4f5449770a4942634e4d5467774d7a49794d6a4d314f545535576867504f546b354f5445794d7a45794d7a55354e546c614d444d784d54417642674e56424155544b44417a0a4e5745784e6d45784e6a4e6d4d4455315a4442694f5445345a57526b596a51794f44426d4e32466c4f44426b5a5751314d6d45774b6a414642674d725a5841440a495144534e45593167624c4d4e414f432b33656f6b2b5279513666684e384632336f32647836315162734d3054714f43415534776767464b4d423847413155640a497751594d4261414646313941315473705942497165363837386d6a52586f48413032534d42304741315564446751574242514457686168592f4256304c6b590a3764744367506575674e37564b6a414f42674e56485138424166384542414d434167517744775944565230544151482f42415577417745422f7a43423567594b0a4b7759424241485765514942474145422f7753423144434230614243424541396d5070416d572b49454f58584f4267537933727935334935363244394f5a485a0a2b4447312f4d396d577869556b524131556369714d704767366e6779717033384a354f7055497546736f53564471465650796a786f3049455149472f376831370a416d3737474c6d51316e534d425a6a74724a2b46726d5754635a6a784a3963583043504a7175377775674c3554636a31493863396e424e71736f6b46783870450a74526f71697a377274365a353244326b516752415a7276714664796a347256636a74566b4a624d6c702f386a6d664765614b682f5247363457724b32754e6b390a79684b4f706b695152307035557354616d2b586445767172786a4c61343373723064692f704b45625a715944436745424d4155474179746c63414e42414f75510a71585a553532314c7a4454585878324559715675574379555a494a5a67526c2f4a477332526d5950594a435a756e304b6a3159497658356d425a3370433835770a30664a466d4d3142322b414373702b703651673d0a2d2d2d2d2d454e442043455254494649434154452d2d2d2d2d0a2d2d2d2d2d424547494e2043455254494649434154452d2d2d2d2d0a4d494943656a4343416979674177494241674955533356553735327371445566593630452f684571536e313432415577425159444b3256774d444d784d5441760a42674e56424155544b44417a4e5745784e6d45784e6a4e6d4d4455315a4442694f5445345a57526b596a51794f44426d4e32466c4f44426b5a5751314d6d45770a4942634e4d5467774d7a49794d6a4d314f545535576867504f546b354f5445794d7a45794d7a55354e546c614d444d784d54417642674e56424155544b4452690a4e7a55314e47566d4f575268593245344d7a55785a6a597a595751774e475a6c4d544579595452684e3251334f4751344d4455774b6a414642674d725a5841440a4951422f6f475854363775635978396c7078465a4652597674676d437942483232692f4c6e554e304b46364c73614f43415534776767464b4d423847413155640a497751594d42614146414e614671466a3846585175526a7432304b4139363641337455714d42304741315564446751574242524c645654766e61796f4e52396a0a7251542b4553704b66586a594254414f42674e56485138424166384542414d434167517744775944565230544151482f42415577417745422f7a43423567594b0a4b7759424241485765514942474145422f77534231444342306142434245444a3657313561697079433255764d6971364943322f77466b7673466339504f72540a314e6e675a47666b65384a6c6e4f37385652555a6373463775687471797265796a697135695a485339684d304a3576494f78756a6f304945514a635a3738616c0a6e43744a69577143486a5467475a6a6f572b6c514a6a4a3955783530545478526545703365454f44394f3374347967645348347254467569754c3674646c5a380a72432f304b544334473576456f77476b51675241675150494251656d5a316973516f4635724b70506f747048584e38595978475935574651497a6b39647a37500a7a78496e5131716e4741736a51505353392b4a4d79774444416937584b754677526630576b32543954615944436745424d4155474179746c63414e424146556c0a5572545135717043634266504765546163584e776c35793357544667706a464b722b4d77367175736a2b62645a366c2b4e334378764f784a396d2b6939364d780a727054366b69536e417a6b2b327a67536941343d0a2d2d2d2d2d454e442043455254494649434154452d2d2d2d2d", + }, + { + Type: COSEKeyType, + In: TestCOSEKey, + Out: "d9022ea501020258246d65726961646f632e6272616e64796275636b406275636b6c616e642e6578616d706c65200121582065eda5a12577c2bae829437fe338701a10aaa375e1bb5b5de108de439c08551d2258201e52ed75701163f7f9e40ddf9f341b3dc9ba860af7e0ca7ca7e9eecd0084d19c", + }, + } { + key := MustNewCryptoKey(tv.In, tv.Type) + data, err := em.Marshal(key) + require.NoError(t, err) + + expected := MustHexDecode(t, tv.Out) + assert.Equal(t, expected, data) + + var key2 CryptoKey + err = dm.Unmarshal(data, &key2) + require.NoError(t, err) + assert.Equal(t, key.String(), key2.String()) + } +} diff --git a/comid/verifkeys.go b/comid/cryptokeys.go similarity index 51% rename from comid/verifkeys.go rename to comid/cryptokeys.go index 37098a6c..0675d7b7 100644 --- a/comid/verifkeys.go +++ b/comid/cryptokeys.go @@ -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") } diff --git a/comid/devidentitykey.go b/comid/devidentitykey.go index 61a8317c..156fa699 100644 --- a/comid/devidentitykey.go +++ b/comid/devidentitykey.go @@ -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 { diff --git a/comid/devidentitykey_test.go b/comid/devidentitykey_test.go index 94a8a2cc..3aa9ad21 100644 --- a/comid/devidentitykey_test.go +++ b/comid/devidentitykey_test.go @@ -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 { diff --git a/comid/example_psa_keys_test.go b/comid/example_psa_keys_test.go index 2e2909e4..edf95989 100644 --- a/comid/example_psa_keys_test.go +++ b/comid/example_psa_keys_test.go @@ -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 { @@ -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 } diff --git a/comid/example_test.go b/comid/example_test.go index 50aa19b9..eae628ef 100644 --- a/comid/example_test.go +++ b/comid/example_test.go @@ -79,12 +79,9 @@ func Example_encode() { Environment: Environment{ Instance: NewInstanceUUID(uuid.UUID(TestUUID)), }, - VerifKeys: *NewVerifKeys(). - AddVerifKey( - NewVerifKey(). - SetKey("FGHIjkisldnASDxvWY..."). - AddCert("MENGsdhfugjQWEtyX..."). - AddCert("MIIEnjCCA4agAwIBA..."), + VerifKeys: *NewCryptoKeys(). + AddCryptoKey( + MustNewPKIXBase64Key(TestECPubKey), ), }, ).AddDevIdentityKey( @@ -92,12 +89,9 @@ func Example_encode() { Environment: Environment{ Instance: NewInstanceUEID(TestUEID), }, - VerifKeys: *NewVerifKeys(). - AddVerifKey( - NewVerifKey(). - SetKey("MIGkAgEBBDCk5QboB..."). - AddCert("MIIDkjCCAxigAwIBA..."). - AddCert("MIIEnjCCA4agAwIBA..."), + VerifKeys: *NewCryptoKeys(). + AddCryptoKey( + MustNewPKIXBase64Key(TestECPubKey), ), }, ) @@ -113,8 +107,8 @@ func Example_encode() { } // Output: - // a50065656e2d474201a10078206d792d6e733a61636d652d726f616472756e6e65722d737570706c656d656e740282a3006941434d45204c74642e01d8207468747470733a2f2f61636d652e6578616d706c6502820100a20069454d4341204c74642e0281020382a200781a6d792d6e733a61636d652d726f616472756e6e65722d626173650100a20078196d792d6e733a61636d652d726f616472756e6e65722d6f6c64010104a4008182a300a500d86f445502c000016941434d45204c74642e026a526f616452756e6e65720300040101d902264702deadbeefdead02d8255031fb5abf023e4992aa4e95f9c1503bfa81a200d8255031fb5abf023e4992aa4e95f9c1503bfa01aa01d90228020282820644abcdef00820644ffffffff030a04d9023044010203040544ffffffff064802005e1000000001075020010db8000000000000000000000068086c43303258373056484a484435094702deadbeefdead0a5031fb5abf023e4992aa4e95f9c1503bfa018182a300a500d8255031fb5abf023e4992aa4e95f9c1503bfa016941434d45204c74642e026a526f616452756e6e65720300040101d902264702deadbeefdead02d8255031fb5abf023e4992aa4e95f9c1503bfa81a200d8255031fb5abf023e4992aa4e95f9c1503bfa01aa01d90229020282820644abcdef00820644ffffffff030b04d9023044010203040544ffffffff064802005e1000000001075020010db8000000000000000000000068086c43303258373056484a484435094702deadbeefdead0a5031fb5abf023e4992aa4e95f9c1503bfa028182a101d8255031fb5abf023e4992aa4e95f9c1503bfa81a20075464748496a6b69736c646e415344787657592e2e2e0182744d454e477364686675676a5157457479582e2e2e744d4949456e6a43434134616741774942412e2e2e038182a101d902264702deadbeefdead81a200744d49476b416745424244436b3551626f422e2e2e0182744d4949446b6a43434178696741774942412e2e2e744d4949456e6a43434134616741774942412e2e2e - // {"lang":"en-GB","tag-identity":{"id":"my-ns:acme-roadrunner-supplement"},"entities":[{"name":"ACME Ltd.","regid":"https://acme.example","roles":["creator","tagCreator"]},{"name":"EMCA Ltd.","roles":["maintainer"]}],"linked-tags":[{"target":"my-ns:acme-roadrunner-base","rel":"supplements"},{"target":"my-ns:acme-roadrunner-old","rel":"replaces"}],"triples":{"reference-values":[{"environment":{"class":{"id":{"type":"oid","value":"2.5.2.8192"},"vendor":"ACME Ltd.","model":"RoadRunner","layer":0,"index":1},"instance":{"type":"ueid","value":"At6tvu/erQ=="},"group":{"type":"ueid","value":"31fb5abf-023e-4992-aa4e-95f9c1503bfa"}},"measurements":[{"key":{"type":"uuid","value":"31fb5abf-023e-4992-aa4e-95f9c1503bfa"},"value":{"svn":{"type":"exact-value","value":2},"digests":["sha-256-32:q83vAA==","sha-256-32://///w=="],"op-flags":["notSecure","debug"],"raw-value":{"type":"bytes","value":"AQIDBA=="},"raw-value-mask":"/////w==","mac-addr":"02:00:5e:10:00:00:00:01","ip-addr":"2001:db8::68","serial-number":"C02X70VHJHD5","ueid":"At6tvu/erQ==","uuid":"31fb5abf-023e-4992-aa4e-95f9c1503bfa"}}]}],"endorsed-values":[{"environment":{"class":{"id":{"type":"uuid","value":"31fb5abf-023e-4992-aa4e-95f9c1503bfa"},"vendor":"ACME Ltd.","model":"RoadRunner","layer":0,"index":1},"instance":{"type":"ueid","value":"At6tvu/erQ=="},"group":{"type":"ueid","value":"31fb5abf-023e-4992-aa4e-95f9c1503bfa"}},"measurements":[{"key":{"type":"uuid","value":"31fb5abf-023e-4992-aa4e-95f9c1503bfa"},"value":{"svn":{"type":"min-value","value":2},"digests":["sha-256-32:q83vAA==","sha-256-32://///w=="],"op-flags":["notConfigured","notSecure","debug"],"raw-value":{"type":"bytes","value":"AQIDBA=="},"raw-value-mask":"/////w==","mac-addr":"02:00:5e:10:00:00:00:01","ip-addr":"2001:db8::68","serial-number":"C02X70VHJHD5","ueid":"At6tvu/erQ==","uuid":"31fb5abf-023e-4992-aa4e-95f9c1503bfa"}}]}],"attester-verification-keys":[{"environment":{"instance":{"type":"uuid","value":"31fb5abf-023e-4992-aa4e-95f9c1503bfa"}},"verification-keys":[{"key":"FGHIjkisldnASDxvWY...","chain":["MENGsdhfugjQWEtyX...","MIIEnjCCA4agAwIBA..."]}]}],"dev-identity-keys":[{"environment":{"instance":{"type":"ueid","value":"At6tvu/erQ=="}},"verification-keys":[{"key":"MIGkAgEBBDCk5QboB...","chain":["MIIDkjCCAxigAwIBA...","MIIEnjCCA4agAwIBA..."]}]}]}} + // a50065656e2d474201a10078206d792d6e733a61636d652d726f616472756e6e65722d737570706c656d656e740282a3006941434d45204c74642e01d8207468747470733a2f2f61636d652e6578616d706c6502820100a20069454d4341204c74642e0281020382a200781a6d792d6e733a61636d652d726f616472756e6e65722d626173650100a20078196d792d6e733a61636d652d726f616472756e6e65722d6f6c64010104a4008182a300a500d86f445502c000016941434d45204c74642e026a526f616452756e6e65720300040101d902264702deadbeefdead02d8255031fb5abf023e4992aa4e95f9c1503bfa81a200d8255031fb5abf023e4992aa4e95f9c1503bfa01aa01d90228020282820644abcdef00820644ffffffff030a04d9023044010203040544ffffffff064802005e1000000001075020010db8000000000000000000000068086c43303258373056484a484435094702deadbeefdead0a5031fb5abf023e4992aa4e95f9c1503bfa018182a300a500d8255031fb5abf023e4992aa4e95f9c1503bfa016941434d45204c74642e026a526f616452756e6e65720300040101d902264702deadbeefdead02d8255031fb5abf023e4992aa4e95f9c1503bfa81a200d8255031fb5abf023e4992aa4e95f9c1503bfa01aa01d90229020282820644abcdef00820644ffffffff030b04d9023044010203040544ffffffff064802005e1000000001075020010db8000000000000000000000068086c43303258373056484a484435094702deadbeefdead0a5031fb5abf023e4992aa4e95f9c1503bfa028182a101d8255031fb5abf023e4992aa4e95f9c1503bfa81d9022a78b12d2d2d2d2d424547494e205055424c4943204b45592d2d2d2d2d0a4d466b77457759484b6f5a497a6a3043415159494b6f5a497a6a304441516344516741455731427671462b2f727938425761375a454d553178595948455138420a6c4c54344d46484f614f2b4943547449767245654570722f7366544150363648326843486462354845584b74524b6f6436514c634f4c504131513d3d0a2d2d2d2d2d454e44205055424c4943204b45592d2d2d2d2d038182a101d902264702deadbeefdead81d9022a78b12d2d2d2d2d424547494e205055424c4943204b45592d2d2d2d2d0a4d466b77457759484b6f5a497a6a3043415159494b6f5a497a6a304441516344516741455731427671462b2f727938425761375a454d553178595948455138420a6c4c54344d46484f614f2b4943547449767245654570722f7366544150363648326843486462354845584b74524b6f6436514c634f4c504131513d3d0a2d2d2d2d2d454e44205055424c4943204b45592d2d2d2d2d + // {"lang":"en-GB","tag-identity":{"id":"my-ns:acme-roadrunner-supplement"},"entities":[{"name":"ACME Ltd.","regid":"https://acme.example","roles":["creator","tagCreator"]},{"name":"EMCA Ltd.","roles":["maintainer"]}],"linked-tags":[{"target":"my-ns:acme-roadrunner-base","rel":"supplements"},{"target":"my-ns:acme-roadrunner-old","rel":"replaces"}],"triples":{"reference-values":[{"environment":{"class":{"id":{"type":"oid","value":"2.5.2.8192"},"vendor":"ACME Ltd.","model":"RoadRunner","layer":0,"index":1},"instance":{"type":"ueid","value":"At6tvu/erQ=="},"group":{"type":"ueid","value":"31fb5abf-023e-4992-aa4e-95f9c1503bfa"}},"measurements":[{"key":{"type":"uuid","value":"31fb5abf-023e-4992-aa4e-95f9c1503bfa"},"value":{"svn":{"type":"exact-value","value":2},"digests":["sha-256-32:q83vAA==","sha-256-32://///w=="],"op-flags":["notSecure","debug"],"raw-value":{"type":"bytes","value":"AQIDBA=="},"raw-value-mask":"/////w==","mac-addr":"02:00:5e:10:00:00:00:01","ip-addr":"2001:db8::68","serial-number":"C02X70VHJHD5","ueid":"At6tvu/erQ==","uuid":"31fb5abf-023e-4992-aa4e-95f9c1503bfa"}}]}],"endorsed-values":[{"environment":{"class":{"id":{"type":"uuid","value":"31fb5abf-023e-4992-aa4e-95f9c1503bfa"},"vendor":"ACME Ltd.","model":"RoadRunner","layer":0,"index":1},"instance":{"type":"ueid","value":"At6tvu/erQ=="},"group":{"type":"ueid","value":"31fb5abf-023e-4992-aa4e-95f9c1503bfa"}},"measurements":[{"key":{"type":"uuid","value":"31fb5abf-023e-4992-aa4e-95f9c1503bfa"},"value":{"svn":{"type":"min-value","value":2},"digests":["sha-256-32:q83vAA==","sha-256-32://///w=="],"op-flags":["notConfigured","notSecure","debug"],"raw-value":{"type":"bytes","value":"AQIDBA=="},"raw-value-mask":"/////w==","mac-addr":"02:00:5e:10:00:00:00:01","ip-addr":"2001:db8::68","serial-number":"C02X70VHJHD5","ueid":"At6tvu/erQ==","uuid":"31fb5abf-023e-4992-aa4e-95f9c1503bfa"}}]}],"attester-verification-keys":[{"environment":{"instance":{"type":"uuid","value":"31fb5abf-023e-4992-aa4e-95f9c1503bfa"}},"verification-keys":[{"type":"PKIXBase64Key","value":"-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEW1BvqF+/ry8BWa7ZEMU1xYYHEQ8B\nlLT4MFHOaO+ICTtIvrEeEpr/sfTAP66H2hCHdb5HEXKtRKod6QLcOLPA1Q==\n-----END PUBLIC KEY-----"}]}],"dev-identity-keys":[{"environment":{"instance":{"type":"ueid","value":"At6tvu/erQ=="}},"verification-keys":[{"type":"PKIXBase64Key","value":"-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEW1BvqF+/ry8BWa7ZEMU1xYYHEQ8B\nlLT4MFHOaO+ICTtIvrEeEpr/sfTAP66H2hCHdb5HEXKtRKod6QLcOLPA1Q==\n-----END PUBLIC KEY-----"}]}]}} } func Example_encode_PSA() { @@ -150,10 +144,9 @@ func Example_encode_PSA() { Environment: Environment{ Instance: NewInstanceUEID(TestUEID), }, - VerifKeys: *NewVerifKeys(). - AddVerifKey( - NewVerifKey(). - SetKey("MIGkAgEBBDCk5QboB..."), + VerifKeys: *NewCryptoKeys(). + AddCryptoKey( + MustNewPKIXBase64Key(TestECPubKey), ), }, ) @@ -169,8 +162,8 @@ func Example_encode_PSA() { } // Output: - // a301a10078206d792d6e733a61636d652d726f616472756e6e65722d737570706c656d656e740281a3006941434d45204c74642e01d8207468747470733a2f2f61636d652e6578616d706c65028301000204a2008182a100a300d90258582061636d652d696d706c656d656e746174696f6e2d69642d303030303030303031016941434d45204c74642e026e526f616452756e6e657220322e3082a200d90259a30162424c0465352e302e35055820acbb11c7e4da217205523ce4ce1a245ae1a239ae3c6bfd9e7871f7e5d8bae86b01a10281820644abcdef00a200d90259a3016450526f540465312e332e35055820acbb11c7e4da217205523ce4ce1a245ae1a239ae3c6bfd9e7871f7e5d8bae86b01a10281820644abcdef00028182a101d902264702deadbeefdead81a100744d49476b416745424244436b3551626f422e2e2e - // {"tag-identity":{"id":"my-ns:acme-roadrunner-supplement"},"entities":[{"name":"ACME Ltd.","regid":"https://acme.example","roles":["creator","tagCreator","maintainer"]}],"triples":{"reference-values":[{"environment":{"class":{"id":{"type":"psa.impl-id","value":"YWNtZS1pbXBsZW1lbnRhdGlvbi1pZC0wMDAwMDAwMDE="},"vendor":"ACME Ltd.","model":"RoadRunner 2.0"}},"measurements":[{"key":{"type":"psa.refval-id","value":{"label":"BL","version":"5.0.5","signer-id":"rLsRx+TaIXIFUjzkzhokWuGiOa48a/2eeHH35di66Gs="}},"value":{"digests":["sha-256-32:q83vAA=="]}},{"key":{"type":"psa.refval-id","value":{"label":"PRoT","version":"1.3.5","signer-id":"rLsRx+TaIXIFUjzkzhokWuGiOa48a/2eeHH35di66Gs="}},"value":{"digests":["sha-256-32:q83vAA=="]}}]}],"attester-verification-keys":[{"environment":{"instance":{"type":"ueid","value":"At6tvu/erQ=="}},"verification-keys":[{"key":"MIGkAgEBBDCk5QboB..."}]}]}} + // a301a10078206d792d6e733a61636d652d726f616472756e6e65722d737570706c656d656e740281a3006941434d45204c74642e01d8207468747470733a2f2f61636d652e6578616d706c65028301000204a2008182a100a300d90258582061636d652d696d706c656d656e746174696f6e2d69642d303030303030303031016941434d45204c74642e026e526f616452756e6e657220322e3082a200d90259a30162424c0465352e302e35055820acbb11c7e4da217205523ce4ce1a245ae1a239ae3c6bfd9e7871f7e5d8bae86b01a10281820644abcdef00a200d90259a3016450526f540465312e332e35055820acbb11c7e4da217205523ce4ce1a245ae1a239ae3c6bfd9e7871f7e5d8bae86b01a10281820644abcdef00028182a101d902264702deadbeefdead81d9022a78b12d2d2d2d2d424547494e205055424c4943204b45592d2d2d2d2d0a4d466b77457759484b6f5a497a6a3043415159494b6f5a497a6a304441516344516741455731427671462b2f727938425761375a454d553178595948455138420a6c4c54344d46484f614f2b4943547449767245654570722f7366544150363648326843486462354845584b74524b6f6436514c634f4c504131513d3d0a2d2d2d2d2d454e44205055424c4943204b45592d2d2d2d2d + // {"tag-identity":{"id":"my-ns:acme-roadrunner-supplement"},"entities":[{"name":"ACME Ltd.","regid":"https://acme.example","roles":["creator","tagCreator","maintainer"]}],"triples":{"reference-values":[{"environment":{"class":{"id":{"type":"psa.impl-id","value":"YWNtZS1pbXBsZW1lbnRhdGlvbi1pZC0wMDAwMDAwMDE="},"vendor":"ACME Ltd.","model":"RoadRunner 2.0"}},"measurements":[{"key":{"type":"psa.refval-id","value":{"label":"BL","version":"5.0.5","signer-id":"rLsRx+TaIXIFUjzkzhokWuGiOa48a/2eeHH35di66Gs="}},"value":{"digests":["sha-256-32:q83vAA=="]}},{"key":{"type":"psa.refval-id","value":{"label":"PRoT","version":"1.3.5","signer-id":"rLsRx+TaIXIFUjzkzhokWuGiOa48a/2eeHH35di66Gs="}},"value":{"digests":["sha-256-32:q83vAA=="]}}]}],"attester-verification-keys":[{"environment":{"instance":{"type":"ueid","value":"At6tvu/erQ=="}},"verification-keys":[{"type":"PKIXBase64Key","value":"-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEW1BvqF+/ry8BWa7ZEMU1xYYHEQ8B\nlLT4MFHOaO+ICTtIvrEeEpr/sfTAP66H2hCHdb5HEXKtRKod6QLcOLPA1Q==\n-----END PUBLIC KEY-----"}]}]}} } func Example_encode_PSA_attestation_verification() { @@ -182,10 +175,9 @@ func Example_encode_PSA_attestation_verification() { Environment: Environment{ Instance: NewInstanceUEID(TestUEID), }, - VerifKeys: *NewVerifKeys(). - AddVerifKey( - NewVerifKey(). - SetKey("MFkwEwYHKoZI..."), + VerifKeys: *NewCryptoKeys(). + AddCryptoKey( + MustNewPKIXBase64Key(TestECPubKey), ), }, ) @@ -201,8 +193,8 @@ func Example_encode_PSA_attestation_verification() { } // Output: - // a301a10078206d792d6e733a61636d652d726f616472756e6e65722d737570706c656d656e740281a3006941434d45204c74642e01d8207468747470733a2f2f61636d652e6578616d706c65028301000204a1028182a101d902264702deadbeefdead81a1006f4d466b77457759484b6f5a492e2e2e - // {"tag-identity":{"id":"my-ns:acme-roadrunner-supplement"},"entities":[{"name":"ACME Ltd.","regid":"https://acme.example","roles":["creator","tagCreator","maintainer"]}],"triples":{"attester-verification-keys":[{"environment":{"instance":{"type":"ueid","value":"At6tvu/erQ=="}},"verification-keys":[{"key":"MFkwEwYHKoZI..."}]}]}} + // a301a10078206d792d6e733a61636d652d726f616472756e6e65722d737570706c656d656e740281a3006941434d45204c74642e01d8207468747470733a2f2f61636d652e6578616d706c65028301000204a1028182a101d902264702deadbeefdead81d9022a78b12d2d2d2d2d424547494e205055424c4943204b45592d2d2d2d2d0a4d466b77457759484b6f5a497a6a3043415159494b6f5a497a6a304441516344516741455731427671462b2f727938425761375a454d553178595948455138420a6c4c54344d46484f614f2b4943547449767245654570722f7366544150363648326843486462354845584b74524b6f6436514c634f4c504131513d3d0a2d2d2d2d2d454e44205055424c4943204b45592d2d2d2d2d + // {"tag-identity":{"id":"my-ns:acme-roadrunner-supplement"},"entities":[{"name":"ACME Ltd.","regid":"https://acme.example","roles":["creator","tagCreator","maintainer"]}],"triples":{"attester-verification-keys":[{"environment":{"instance":{"type":"ueid","value":"At6tvu/erQ=="}},"verification-keys":[{"type":"PKIXBase64Key","value":"-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEW1BvqF+/ry8BWa7ZEMU1xYYHEQ8B\nlLT4MFHOaO+ICTtIvrEeEpr/sfTAP66H2hCHdb5HEXKtRKod6QLcOLPA1Q==\n-----END PUBLIC KEY-----"}]}]}} } func Example_decode_JSON() { @@ -350,11 +342,8 @@ func Example_decode_JSON() { }, "verification-keys": [ { - "key": "MFkwEwYHKoZI...", - "chain": [ - "MIIDkjCCAxigAwIBA...", - "MIIEnjCCA4agAwIBA..." - ] + "type": "PKIXBase64Key", + "value": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEW1BvqF+/ry8BWa7ZEMU1xYYHEQ8B\nlLT4MFHOaO+ICTtIvrEeEpr/sfTAP66H2hCHdb5HEXKtRKod6QLcOLPA1Q==\n-----END PUBLIC KEY-----" } ] } @@ -369,10 +358,12 @@ func Example_decode_JSON() { }, "verification-keys": [ { - "key": "MIIDUDCCAvWgAw..." + "type": "PKIXBase64Key", + "value": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEW1BvqF+/ry8BWa7ZEMU1xYYHEQ8B\nlLT4MFHOaO+ICTtIvrEeEpr/sfTAP66H2hCHdb5HEXKtRKod6QLcOLPA1Q==\n-----END PUBLIC KEY-----" }, { - "key": "MIIEnjCCA4agAw..." + "type": "PKIXBase64Key", + "value": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEW1BvqF+/ry8BWa7ZEMU1xYYHEQ8B\nlLT4MFHOaO+ICTtIvrEeEpr/sfTAP66H2hCHdb5HEXKtRKod6QLcOLPA1Q==\n-----END PUBLIC KEY-----" } ] } diff --git a/comid/test_vars.go b/comid/test_vars.go index 5d923cd6..0a06b271 100644 --- a/comid/test_vars.go +++ b/comid/test_vars.go @@ -1,4 +1,4 @@ -// Copyright 2021 Contributors to the Veraison project. +// Copyright 2021-2023 Contributors to the Veraison project. // SPDX-License-Identifier: Apache-2.0 package comid @@ -33,6 +33,150 @@ var ( TestTagID = "urn:example:veraison" TestMKey uint64 = 700 TestCCALabel = "cca-platform-config" + + TestECPrivKey = `-----BEGIN EC PRIVATE KEY----- +MHcCAQEEICAm3+mCCDTMuzKqfZso9NT8ur9U9GjuUQ/lNEJvwRFMoAoGCCqGSM49 +AwEHoUQDQgAEW1BvqF+/ry8BWa7ZEMU1xYYHEQ8BlLT4MFHOaO+ICTtIvrEeEpr/ +sfTAP66H2hCHdb5HEXKtRKod6QLcOLPA1Q== +-----END EC PRIVATE KEY-----` + + TestECPubKey = `-----BEGIN PUBLIC KEY----- +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEW1BvqF+/ry8BWa7ZEMU1xYYHEQ8B +lLT4MFHOaO+ICTtIvrEeEpr/sfTAP66H2hCHdb5HEXKtRKod6QLcOLPA1Q== +-----END PUBLIC KEY-----` + + TestCert = `-----BEGIN CERTIFICATE----- +MIIB4TCCAYegAwIBAgIUGhrA9M3yQIFqckA2v6nQewmF30IwCgYIKoZIzj0EAwIw +RTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGElu +dGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAgFw0yMzA5MDQxMTAxNDhaGA8yMDUxMDEx +OTExMDE0OFowRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAf +BgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDBZMBMGByqGSM49AgEGCCqG +SM49AwEHA0IABFtQb6hfv68vAVmu2RDFNcWGBxEPAZS0+DBRzmjviAk7SL6xHhKa +/7H0wD+uh9oQh3W+RxFyrUSqHekC3DizwNWjUzBRMB0GA1UdDgQWBBQWpNPb6eWD +SM/+jwpbzoO3iHg4LTAfBgNVHSMEGDAWgBQWpNPb6eWDSM/+jwpbzoO3iHg4LTAP +BgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMCA0gAMEUCIAayNIF0eCJDZmcrqRjH +f9h8GxeIDUnLqldeIvNfa+9SAiEA9ULBTPjnTUhYle226OAjg2sdhkXtb3Mu0E0F +nuUmsIQ= +-----END CERTIFICATE-----` + + TestCertPath = `-----BEGIN CERTIFICATE----- +MIICejCCAiygAwIBAgIUIpeVwVhN/qYLgtNJlwZHJj+IT/wwBQYDK2VwMDMxMTAv +BgNVBAUTKDdhMDZlZWU0MWI3ODlmNDg2M2Q4NmI4Nzc4YjFhMjAxYTZmZWRkNTYw +IBcNMTgwMzIyMjM1OTU5WhgPOTk5OTEyMzEyMzU5NTlaMDMxMTAvBgNVBAUTKDIy +OTc5NWMxNTg0ZGZlYTYwYjgyZDM0OTk3MDY0NzI2M2Y4ODRmZmMwKjAFBgMrZXAD +IQAVUi7xVynM85UJ6lwVomvpSeOIB6XCbvkoFIfvSuZ7RqOCAU4wggFKMB8GA1Ud +IwQYMBaAFHoG7uQbeJ9IY9hrh3ixogGm/t1WMB0GA1UdDgQWBBQil5XBWE3+pguC +00mXBkcmP4hP/DAOBgNVHQ8BAf8EBAMCAgQwDwYDVR0TAQH/BAUwAwEB/zCB5gYK +KwYBBAHWeQIBGAEB/wSB1DCB0aBCBEAMtveoAJx4v3Qu9K8gI0J2kp7igBv4Vd9B +HEMtlfZOQdy6yDOlcPrQGYjSzwvAjFh8DA46bq+xGj31NFUy6pkho0IEQNCkl/Kf +bESLZ6OhEcdOnAziS5gx5TqJmF22yKCjIvLRIVxNIhZN2EnMAtm4dp1EGuPBLUrA +tzXhlzuZuK1xV6SkQgRASeSoHmnNgLhnnEKTWKzcL2jzPjOAFUQTNRy+iOghluI3 +ficG6NB7cMbLAZkfV12lihSV+/7iK3TJ0bUNjQgWpaYDCgEBMAUGAytlcANBAHu6 +DtuPNOurcAXc+41QY23hY8KRkBCKCE7phsiIwRfbxKMLldFGN5OytQfROQaWoAcv +IWTqV9JRzGQaGYnlLwE= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICejCCAiygAwIBAgIUEbae7u1cP7s+G/CDb2Nu6nPRdYkwBQYDK2VwMDMxMTAv +BgNVBAUTKDIyOTc5NWMxNTg0ZGZlYTYwYjgyZDM0OTk3MDY0NzI2M2Y4ODRmZmMw +IBcNMTgwMzIyMjM1OTU5WhgPOTk5OTEyMzEyMzU5NTlaMDMxMTAvBgNVBAUTKDEx +YjY5ZWVlZWQ1YzNmYmIzZTFiZjA4MzZmNjM2ZWVhNzNkMTc1ODkwKjAFBgMrZXAD +IQDzgkTR7uvoP9NBzSEB9gu/lpd+NL38OVYQl0feiWKX+aOCAU4wggFKMB8GA1Ud +IwQYMBaAFCKXlcFYTf6mC4LTSZcGRyY/iE/8MB0GA1UdDgQWBBQRtp7u7Vw/uz4b +8INvY27qc9F1iTAOBgNVHQ8BAf8EBAMCAgQwDwYDVR0TAQH/BAUwAwEB/zCB5gYK +KwYBBAHWeQIBGAEB/wSB1DCB0aBCBEBbsKgcavE+uy1AxkIdl7lN9ifHy3HE+Liu +8lME27CMY9kUtyw/les1H8vpmSyxhO4aTWgwuwQa7Yn9HoGweEHso0IEQHb870HN +1bUn9nFih11SBAj9lobpuJ5GrI/m+g6HwmoQz5Uly0oXMNnxEMA7fL2za01ynGpI +/uz82rUI2vLWSlGkQgRA3XFgIoVImosdAgvuPHVaobv3JGjGl3+ADOT1c6dT6dQE +dnObRNudY8qhzTvfEWR4eS6OJtfyrOeRyXek2OVJh6YDCgEBMAUGAytlcANBAJIj +yFqwdrZCSuYmC4+ZUUcANKQKA1KcRFiIlKcg/ppwKVykPXbAhsn6SCVqWGA7v7Ce +Li5hOrH/VljAQAcdYgc= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICejCCAiygAwIBAgIUYUXMcfV3Mucpunl193wuXxBBr/gwBQYDK2VwMDMxMTAv +BgNVBAUTKDExYjY5ZWVlZWQ1YzNmYmIzZTFiZjA4MzZmNjM2ZWVhNzNkMTc1ODkw +IBcNMTgwMzIyMjM1OTU5WhgPOTk5OTEyMzEyMzU5NTlaMDMxMTAvBgNVBAUTKDYx +NDVjYzcxZjU3NzMyZTcyOWJhNzk3NWY3N2MyZTVmMTA0MWFmZjgwKjAFBgMrZXAD +IQBJo9PgveHj0ahv8MkWHQUGSxZ/wSTdaNNZbdBZNa1L0aOCAU4wggFKMB8GA1Ud +IwQYMBaAFBG2nu7tXD+7Phvwg29jbupz0XWJMB0GA1UdDgQWBBRhRcxx9Xcy5ym6 +eXX3fC5fEEGv+DAOBgNVHQ8BAf8EBAMCAgQwDwYDVR0TAQH/BAUwAwEB/zCB5gYK +KwYBBAHWeQIBGAEB/wSB1DCB0aBCBEA2ansef0SbRN8j76w5hzW5/TCXFIsQcERs +bSKQYNnqug1rjECPnhe3A/8Z6WGxaDK1ehE+nrcvC9BRgrWpU67Jo0IEQIZyRCHK +9HUi/8y6V9P0ZuNEvmdpEdImQ09RU/lNPsXXxyv0VEmi6WDs4eFypmBR9LVXBXud +rCduuvyS6tBWsS6kQgRAbWRTCbXrd/qlLPII85IPB8pZ9uX+XgIHI4sSHf+3F6se +hA/80zUBzSi6Ozc0D+IbYYBYxdrXZEkn8iUWSdQokKYDCgEBMAUGAytlcANBAKlJ +/3VYalZm9XbEGTKrVRaoCVoUxQVH3udMrk9yoqjFowC4e3kdSBlGGf8mYEI7xvsA +ar1kf2bGXT/cEeFGIwM= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICejCCAiygAwIBAgIUX+ivPHTOmvVktMnQGYQjuNlk/DUwBQYDK2VwMDMxMTAv +BgNVBAUTKDYxNDVjYzcxZjU3NzMyZTcyOWJhNzk3NWY3N2MyZTVmMTA0MWFmZjgw +IBcNMTgwMzIyMjM1OTU5WhgPOTk5OTEyMzEyMzU5NTlaMDMxMTAvBgNVBAUTKDVm +ZThhZjNjNzRjZTlhZjU2NGI0YzlkMDE5ODQyM2I4ZDk2NGZjMzUwKjAFBgMrZXAD +IQC6u3blwE4B1xdPMeUJP657P/m7iSt+HergvGbkkSxMrqOCAU4wggFKMB8GA1Ud +IwQYMBaAFGFFzHH1dzLnKbp5dfd8Ll8QQa/4MB0GA1UdDgQWBBRf6K88dM6a9WS0 +ydAZhCO42WT8NTAOBgNVHQ8BAf8EBAMCAgQwDwYDVR0TAQH/BAUwAwEB/zCB5gYK +KwYBBAHWeQIBGAEB/wSB1DCB0aBCBEC4z2juJIx5jD7x6IuMNUi7TUomWxCQf9Qn +CJ91ozXk0vJ9nJO3RdveJvbvZhoPfDQIY8TiZp8UKDx4e+zW0cHko0IEQOhpMJ6G +EXLZgHtRAm81oXXACEF+nev2MCv6COhuRtFypG9B3foRm2rnFUbaVZs0pLfBMG8s +sSRJRcawXCimW4OkQgRA27Fgx7A4212qpqLaxaPd9tI+zpfKWrLYcLx20+DLfcqn +BIIpUCN30SuAu71se4x/ilcKuaWOO0qDg34SJEwFyqYDCgEBMAUGAytlcANBACtT +5Xrx659qGnywmlKHdlHO6Bd7fPboyzyIQhoEtFNuiD3WjDg/Vwz8cNCUkU+thG7f +C+WZhcpAckDldai+PAc= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICejCCAiygAwIBAgIUXX0DVOylgEip7rzvyaNFegcDTZIwBQYDK2VwMDMxMTAv +BgNVBAUTKDVmZThhZjNjNzRjZTlhZjU2NGI0YzlkMDE5ODQyM2I4ZDk2NGZjMzUw +IBcNMTgwMzIyMjM1OTU5WhgPOTk5OTEyMzEyMzU5NTlaMDMxMTAvBgNVBAUTKDVk +N2QwMzU0ZWNhNTgwNDhhOWVlYmNlZmM5YTM0NTdhMDcwMzRkOTIwKjAFBgMrZXAD +IQCiaC2gHhMO1pbeQbUgLHhSgFBPD/zXNAGwAHsW272+c6OCAU4wggFKMB8GA1Ud +IwQYMBaAFF/orzx0zpr1ZLTJ0BmEI7jZZPw1MB0GA1UdDgQWBBRdfQNU7KWASKnu +vO/Jo0V6BwNNkjAOBgNVHQ8BAf8EBAMCAgQwDwYDVR0TAQH/BAUwAwEB/zCB5gYK +KwYBBAHWeQIBGAEB/wSB1DCB0aBCBEBYXwS/mrrX+D4MqzM8JTmIHC9XHqsJfOGc +b2fqBYPX0UQriLDRl1apHN22q1E+FeaLHWBE2uXda1Q6lYkQAaHio0IEQGKH8EAN +Mv1PMMbWsddZew2G/DR+A9tbSi7H680yBSe9Ce+gtabBarQDHpg9B8LebmoPpdXt +ATv+oSzzk+ZueVKkQgRAztbU2QzaJbcG5twEYjYAgFutCbngpg2t/2ez7QTNn4Nm +r94pOAx8LIpu6Cf/Wzcvd/4kLOvWxSb/buMqbGvrsqYDCgEBMAUGAytlcANBAMdx +fFnk52ru4fV5J1gsFBtlhy5mFbQnIRiGHLxBFaTJk9i+ixO5qFbRjqv7HQ/jGUsI +srUJQ4e2JEnSNakNcgE= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICejCCAiygAwIBAgIUA1oWoWPwVdC5GO3bQoD3roDe1SowBQYDK2VwMDMxMTAv +BgNVBAUTKDVkN2QwMzU0ZWNhNTgwNDhhOWVlYmNlZmM5YTM0NTdhMDcwMzRkOTIw +IBcNMTgwMzIyMjM1OTU5WhgPOTk5OTEyMzEyMzU5NTlaMDMxMTAvBgNVBAUTKDAz +NWExNmExNjNmMDU1ZDBiOTE4ZWRkYjQyODBmN2FlODBkZWQ1MmEwKjAFBgMrZXAD +IQDSNEY1gbLMNAOC+3eok+RyQ6fhN8F23o2dx61QbsM0TqOCAU4wggFKMB8GA1Ud +IwQYMBaAFF19A1TspYBIqe6878mjRXoHA02SMB0GA1UdDgQWBBQDWhahY/BV0LkY +7dtCgPeugN7VKjAOBgNVHQ8BAf8EBAMCAgQwDwYDVR0TAQH/BAUwAwEB/zCB5gYK +KwYBBAHWeQIBGAEB/wSB1DCB0aBCBEA9mPpAmW+IEOXXOBgSy3ry53I562D9OZHZ ++DG1/M9mWxiUkRA1UciqMpGg6ngyqp38J5OpUIuFsoSVDqFVPyjxo0IEQIG/7h17 +Am77GLmQ1nSMBZjtrJ+FrmWTcZjxJ9cX0CPJqu7wugL5Tcj1I8c9nBNqsokFx8pE +tRoqiz7rt6Z52D2kQgRAZrvqFdyj4rVcjtVkJbMlp/8jmfGeaKh/RG64WrK2uNk9 +yhKOpkiQR0p5UsTam+XdEvqrxjLa43sr0di/pKEbZqYDCgEBMAUGAytlcANBAOuQ +qXZU521LzDTXXx2EYqVuWCyUZIJZgRl/JGs2RmYPYJCZun0Kj1YIvX5mBZ3pC85w +0fJFmM1B2+ACsp+p6Qg= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICejCCAiygAwIBAgIUS3VU752sqDUfY60E/hEqSn142AUwBQYDK2VwMDMxMTAv +BgNVBAUTKDAzNWExNmExNjNmMDU1ZDBiOTE4ZWRkYjQyODBmN2FlODBkZWQ1MmEw +IBcNMTgwMzIyMjM1OTU5WhgPOTk5OTEyMzEyMzU5NTlaMDMxMTAvBgNVBAUTKDRi +NzU1NGVmOWRhY2E4MzUxZjYzYWQwNGZlMTEyYTRhN2Q3OGQ4MDUwKjAFBgMrZXAD +IQB/oGXT67ucYx9lpxFZFRYvtgmCyBH22i/LnUN0KF6LsaOCAU4wggFKMB8GA1Ud +IwQYMBaAFANaFqFj8FXQuRjt20KA966A3tUqMB0GA1UdDgQWBBRLdVTvnayoNR9j +rQT+ESpKfXjYBTAOBgNVHQ8BAf8EBAMCAgQwDwYDVR0TAQH/BAUwAwEB/zCB5gYK +KwYBBAHWeQIBGAEB/wSB1DCB0aBCBEDJ6W15aipyC2UvMiq6IC2/wFkvsFc9POrT +1NngZGfke8JlnO78VRUZcsF7uhtqyreyjiq5iZHS9hM0J5vIOxujo0IEQJcZ78al +nCtJiWqCHjTgGZjoW+lQJjJ9Ux50TTxReEp3eEOD9O3t4ygdSH4rTFuiuL6tdlZ8 +rC/0KTC4G5vEowGkQgRAgQPIBQemZ1isQoF5rKpPotpHXN8YYxGY5WFQIzk9dz7P +zxInQ1qnGAsjQPSS9+JMywDDAi7XKuFwRf0Wk2T9TaYDCgEBMAUGAytlcANBAFUl +UrTQ5qpCcBfPGeTacXNwl5y3WTFgpjFKr+Mw6qusj+bdZ6l+N3CxvOxJ9m+i96Mx +rpT6kiSnAzk+2zgSiA4= +-----END CERTIFICATE-----` + + TestCOSEKey = MustHexDecode(nil, `a501020258246d65726961646f632e6272616e64796275636b406275636b6c616e642e6578616d706c65200121582065eda5a12577c2bae829437fe338701a10aaa375e1bb5b5de108de439c08551d2258201e52ed75701163f7f9e40ddf9f341b3dc9ba860af7e0ca7ca7e9eecd0084d19c`) + + TestCOSEKeySetOne = MustHexDecode(nil, `81a501020258246d65726961646f632e6272616e64796275636b406275636b6c616e642e6578616d706c65200121582065eda5a12577c2bae829437fe338701a10aaa375e1bb5b5de108de439c08551d2258201e52ed75701163f7f9e40ddf9f341b3dc9ba860af7e0ca7ca7e9eecd0084d19c`) + + TestCOSEKeySetMulti = MustHexDecode(nil, `82a501020258246d65726961646f632e6272616e64796275636b406275636b6c616e642e6578616d706c65200121582065eda5a12577c2bae829437fe338701a10aaa375e1bb5b5de108de439c08551d2258201e52ed75701163f7f9e40ddf9f341b3dc9ba860af7e0ca7ca7e9eecd0084d19ca601010327048202647369676e0543030201200621582015522ef15729ccf39509ea5c15a26be949e38807a5c26ef9281487ef4ae67b46`) ) func MustHexDecode(t *testing.T, s string) []byte { @@ -167,7 +311,8 @@ var ( }, "verification-keys": [ { - "key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEFn0taoAwR3PmrKkYLtAsD9o05KSM6mbgfNCgpuL0g6VpTHkZl73wk5BDxoV7n+Oeee0iIqkW3HMZT3ETiniJdg==" + "type": "PKIXBase64Key", + "value": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEW1BvqF+/ry8BWa7ZEMU1xYYHEQ8B\nlLT4MFHOaO+ICTtIvrEeEpr/sfTAP66H2hCHdb5HEXKtRKod6QLcOLPA1Q==\n-----END PUBLIC KEY-----" } ] }, @@ -188,7 +333,8 @@ var ( }, "verification-keys": [ { - "key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE6Vwqe7hy3O8Ypa+BUETLUjBNU3rEXVUyt9XHR7HJWLG7XTKQd9i1kVRXeBPDLFnfYru1/euxRnJM7H9UoFDLdA==" + "type": "PKIXBase64Key", + "value": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEW1BvqF+/ry8BWa7ZEMU1xYYHEQ8B\nlLT4MFHOaO+ICTtIvrEeEpr/sfTAP66H2hCHdb5HEXKtRKod6QLcOLPA1Q==\n-----END PUBLIC KEY-----" } ] } diff --git a/comid/verifkey.go b/comid/verifkey.go deleted file mode 100644 index e70c4429..00000000 --- a/comid/verifkey.go +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2021 Contributors to the Veraison project. -// SPDX-License-Identifier: Apache-2.0 - -package comid - -import "fmt" - -// VerifKey stores the verification key material associated to a signing key. -// Key is - typically, but not necessarily - a public key. Chain is an optional -// X.509 certificate chain corresponding to the public key in Key, encoded as an -// array of one or more base64-encoded DER PKIX certificates. The certificate -// containing the public key in Key MUST be the first certificate. This MAY be -// followed by additional certificates, with each subsequent certificate being -// the one used to certify the previous one. -type VerifKey struct { - Key string `cbor:"0,keyasint" json:"key"` - Chain *[]string `cbor:"1,keyasint,omitempty" json:"chain,omitempty"` -} - -// NewVerifKey instantiates an empty VerifKey -func NewVerifKey() *VerifKey { - return &VerifKey{} -} - -// SetKey sets the Key in the target object to the supplied value -func (o *VerifKey) SetKey(key string) *VerifKey { - if o != nil { - o.Key = key - } - return o -} - -// AddCert adds the supplied base64-encoded DER PKIX certificate in the target -// object -func (o *VerifKey) AddCert(cert string) *VerifKey { - if o != nil { - if o.Chain == nil { - o.Chain = new([]string) - } - *o.Chain = append(*o.Chain, cert) - } - return o -} - -func (o VerifKey) Valid() error { - if o.Key == "" { - return fmt.Errorf("verification key not set") - } - return nil -} diff --git a/corim/unsignedcorim_test.go b/corim/unsignedcorim_test.go index 3fc99166..4f246219 100644 --- a/corim/unsignedcorim_test.go +++ b/corim/unsignedcorim_test.go @@ -184,10 +184,9 @@ func TestUnsignedCorim_Valid_ok(t *testing.T) { Environment: comid.Environment{ Instance: comid.NewInstanceUUID(uuid.UUID(comid.TestUUID)), }, - VerifKeys: *comid.NewVerifKeys(). - AddVerifKey( - comid.NewVerifKey(). - SetKey("FGHIjkisldnASDxvWY..."), + VerifKeys: *comid.NewCryptoKeys(). + AddCryptoKey( + comid.MustNewPKIXBase64Key(comid.TestECPubKey), ), }, ) diff --git a/go.mod b/go.mod index 5730b4f1..e0d0b05f 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,7 @@ require ( github.com/stretchr/testify v1.8.1 github.com/veraison/apiclient v0.0.2 github.com/veraison/eat v0.0.0-20210331113810-3da8a4dd42ff - github.com/veraison/go-cose v1.0.0-rc.1 + github.com/veraison/go-cose v1.1.1-0.20230825153510-da0f9a62ade7 github.com/veraison/swid v1.1.0 golang.org/x/sys v0.1.0 // indirect golang.org/x/text v0.3.8 // indirect diff --git a/go.sum b/go.sum index fc8b5a2b..2ae9cfa8 100644 --- a/go.sum +++ b/go.sum @@ -310,8 +310,8 @@ github.com/veraison/apiclient v0.0.2 h1:S/BG22tt5ewsBRi4A9Z7BH4MCznLNtHkRhWIHu9x github.com/veraison/apiclient v0.0.2/go.mod h1:H8YDx1ixM24GYP/aLbhq+HJsej0lVUqFCRIL5Uu4B0o= github.com/veraison/eat v0.0.0-20210331113810-3da8a4dd42ff h1:r6I2eJL/z8dp5flsQIKHMeDjyV6UO8If3MaVBLvTjF4= github.com/veraison/eat v0.0.0-20210331113810-3da8a4dd42ff/go.mod h1:+kxt8iuFiVvKRs2VQ1Ho7bbAScXAB/kHFFuP5Biw19I= -github.com/veraison/go-cose v1.0.0-rc.1 h1:4qA7dbFJGvt7gcqv5MCIyCQvN+NpHFPkW7do3EeDLb8= -github.com/veraison/go-cose v1.0.0-rc.1/go.mod h1:7ziE85vSq4ScFTg6wyoMXjucIGOf4JkFEZi/an96Ct4= +github.com/veraison/go-cose v1.1.1-0.20230825153510-da0f9a62ade7 h1:KcKzBthSrSZIUEWBjVvkuk/DE3PyYFbXZxhx5byGFtc= +github.com/veraison/go-cose v1.1.1-0.20230825153510-da0f9a62ade7/go.mod h1:t6V8WJzHm1PD5HNsuDjW3KLv577uWb6UTzbZGvdQHD8= github.com/veraison/swid v1.1.0 h1:jEf/jobG6j7r9W9HSj2jDi1IGGs7aMKyDgfGEMxQ6is= github.com/veraison/swid v1.1.0/go.mod h1:d5jt76uMNbTfQ+f2qU4Lt8RvWOTsv6PFgstIM1QdMH0= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=