From 6c9eac6ad9a5cfb9686fe574d1e53f3f9ce0e189 Mon Sep 17 00:00:00 2001 From: Yogesh Deshpande Date: Fri, 8 Dec 2023 14:27:45 -0500 Subject: [PATCH] Enhance EvidenceHanlder Interface to handle multiple RefVal and TAIDs Fixes #206 Signed-off-by: Yogesh Deshpande --- handler/evidence_rpc.go | 36 +++++------ handler/ievidencehandler.go | 20 +++---- proto/evidence.pb.go | 46 +++++++-------- proto/evidence.proto | 4 +- scheme/cca-ssd-platform/evidence_handler.go | 20 ++++--- .../cca-ssd-platform/evidence_handler_test.go | 15 +++-- scheme/cca-ssd-platform/test/extracted.json | 4 +- scheme/parsec-cca/evidence_handler.go | 20 ++++--- scheme/parsec-cca/evidence_handler_test.go | 19 +++--- .../parsec-cca/test/evidence/extracted.json | 4 +- scheme/parsec-tpm/evidence_handler.go | 18 +++--- scheme/parsec-tpm/evidence_handler_test.go | 29 ++++----- .../parsec-tpm/test/evidence/extracted.json | 4 +- .../test/evidence/matched_extracted.json | 4 +- scheme/psa-iot/evidence_handler.go | 21 ++++--- scheme/psa-iot/evidence_handler_test.go | 21 ++++--- scheme/psa-iot/test/extracted.json | 4 +- scheme/riot/evidence_handler.go | 14 ++--- scheme/riot/evidence_handler_test.go | 4 +- scheme/tpm-enacttrust/evidence_handler.go | 16 ++--- .../tpm-enacttrust/evidence_handler_test.go | 23 ++++---- vts/policymanager/policymanager_test.go | 32 +++++----- vts/trustedservices/trustedservices_grpc.go | 59 +++++++++++-------- 23 files changed, 236 insertions(+), 201 deletions(-) diff --git a/handler/evidence_rpc.go b/handler/evidence_rpc.go index 6a9ea726..c7b4f679 100644 --- a/handler/evidence_rpc.go +++ b/handler/evidence_rpc.go @@ -82,7 +82,7 @@ func (s *RPCServer) SynthKeysFromTrustAnchor(args SynthKeysArgs, resp *[]string) return err } -func (s *RPCServer) GetTrustAnchorID(data []byte, resp *string) error { +func (s *RPCServer) GetTrustAnchorIDs(data []byte, resp *[]string) error { var ( err error token proto.AttestationToken @@ -93,14 +93,14 @@ func (s *RPCServer) GetTrustAnchorID(data []byte, resp *string) error { return fmt.Errorf("unmarshaling attestation token: %w", err) } - *resp, err = s.Impl.GetTrustAnchorID(&token) + *resp, err = s.Impl.GetTrustAnchorIDs(&token) return err } type ExtractClaimsArgs struct { - Token []byte - TrustAnchor string + Token []byte + TrustAnchors []string } func (s *RPCServer) ExtractClaims(args ExtractClaimsArgs, resp *[]byte) error { @@ -111,7 +111,7 @@ func (s *RPCServer) ExtractClaims(args ExtractClaimsArgs, resp *[]byte) error { return fmt.Errorf("unmarshaling token: %w", err) } - extracted, err := s.Impl.ExtractClaims(&token, args.TrustAnchor) + extracted, err := s.Impl.ExtractClaims(&token, args.TrustAnchors) if err != nil { return err } @@ -123,7 +123,7 @@ func (s *RPCServer) ExtractClaims(args ExtractClaimsArgs, resp *[]byte) error { type ValidateEvidenceIntegrityArgs struct { Token []byte - TrustAnchor string + TrustAnchors []string Endorsements []string } @@ -135,7 +135,7 @@ func (s *RPCServer) ValidateEvidenceIntegrity(args ValidateEvidenceIntegrityArgs return fmt.Errorf("unmarshaling token: %w", err) } - err = s.Impl.ValidateEvidenceIntegrity(&token, args.TrustAnchor, args.Endorsements) + err = s.Impl.ValidateEvidenceIntegrity(&token, args.TrustAnchors, args.Endorsements) return err } @@ -262,28 +262,28 @@ func (s *RPCClient) SynthKeysFromTrustAnchor(tenantID string, ta *Endorsement) ( return resp, nil } -func (s *RPCClient) GetTrustAnchorID(token *proto.AttestationToken) (string, error) { +func (s *RPCClient) GetTrustAnchorIDs(token *proto.AttestationToken) ([]string, error) { var ( err error data []byte - resp string + resp []string ) data, err = json.Marshal(token) if err != nil { - return "", fmt.Errorf("marshaling token: %w", err) + return []string{""}, fmt.Errorf("marshaling token: %w", err) } - err = s.client.Call("Plugin.GetTrustAnchorID", data, &resp) + err = s.client.Call("Plugin.GetTrustAnchorIDs", data, &resp) if err != nil { err = ParseError(err) - return "", fmt.Errorf("Plugin.GetTrustAnchorID RPC call failed: %w", err) // nolint + return []string{""}, fmt.Errorf("Plugin.GetTrustAnchorIDs RPC call failed: %w", err) // nolint } return resp, nil } -func (s *RPCClient) ExtractEvidence(token *proto.AttestationToken, trustAnchor string) (*ExtractedClaims, error) { +func (s *RPCClient) ExtractEvidence(token *proto.AttestationToken, trustAnchors []string) (*ExtractedClaims, error) { var ( err error args ExtractClaimsArgs @@ -295,7 +295,7 @@ func (s *RPCClient) ExtractEvidence(token *proto.AttestationToken, trustAnchor s if err != nil { return nil, fmt.Errorf("marshaling token: %w", err) } - args.TrustAnchor = trustAnchor + args.TrustAnchors = trustAnchors err = s.client.Call("Plugin.ExtractEvidence", args, &resp) if err != nil { @@ -313,7 +313,7 @@ func (s *RPCClient) ExtractEvidence(token *proto.AttestationToken, trustAnchor s func (s *RPCClient) ValidateEvidenceIntegrity( token *proto.AttestationToken, - trustAnchor string, + trustAnchors []string, endorsements []string, ) error { var ( @@ -326,7 +326,7 @@ func (s *RPCClient) ValidateEvidenceIntegrity( if err != nil { return fmt.Errorf("marshaling token: %w", err) } - args.TrustAnchor = trustAnchor + args.TrustAnchors = trustAnchors args.Endorsements = endorsements err = s.client.Call("Plugin.ValidateEvidenceIntegrity", args, &resp) @@ -360,7 +360,7 @@ func (s *RPCClient) AppraiseEvidence(ec *proto.EvidenceContext, endorsements []s return &result, err } -func (s *RPCClient) ExtractClaims(token *proto.AttestationToken, trustAnchor string) (*ExtractedClaims, error) { +func (s *RPCClient) ExtractClaims(token *proto.AttestationToken, trustAnchors []string) (*ExtractedClaims, error) { var ( err error args ExtractClaimsArgs @@ -372,7 +372,7 @@ func (s *RPCClient) ExtractClaims(token *proto.AttestationToken, trustAnchor str return nil, fmt.Errorf("marshaling token: %w", err) } - args.TrustAnchor = trustAnchor + args.TrustAnchors = trustAnchors var resp []byte err = s.client.Call("Plugin.ExtractClaims", args, &resp) diff --git a/handler/ievidencehandler.go b/handler/ievidencehandler.go index 2a5f8784..96cbcecc 100644 --- a/handler/ievidencehandler.go +++ b/handler/ievidencehandler.go @@ -14,22 +14,22 @@ import ( type IEvidenceHandler interface { plugin.IPluggable - // GetTrustAnchorID returns a string ID used to retrieve a trust anchor - // for this token. The trust anchor may be necessary to validate the - // token and/or extract its claims (if it is encrypted). - GetTrustAnchorID(token *proto.AttestationToken) (string, error) + // GetTrustAnchorIDs returns an array of trust anchor strings(handles) used to retrieve a + // set of trust anchors for this token. The trust anchors may be necessary to validate the + // entire token and/or extract its claims (if it is encrypted). + GetTrustAnchorIDs(token *proto.AttestationToken) ([]string, error) // ExtractClaims parses the attestation token and returns claims // extracted therefrom. ExtractClaims( token *proto.AttestationToken, - trustAnchor string, + trustAnchors []string, ) (*ExtractedClaims, error) // ValidateEvidenceIntegrity verifies the structural integrity and validity of the // token. The exact checks performed are scheme-specific, but they // would typically involve, at the least, verifying the token's - // signature using the provided trust anchor and endorsements. If the + // signature using the provided trust anchors and endorsements. If the // validation fails, an error detailing what went wrong is returned. // Note: key material required to validate the token would typically be // provisioned as a Trust Anchor. However, depending on the @@ -44,7 +44,7 @@ type IEvidenceHandler interface { // (i.e. signature not matching). ValidateEvidenceIntegrity( token *proto.AttestationToken, - trustAnchor string, + trustAnchors []string, endorsementsStrings []string, ) error @@ -65,14 +65,14 @@ type IEvidenceHandler interface { } // ExtractedClaims contains a map of claims extracted from an attestation -// token along with the corresponding ReferenceID that is used to fetch +// token along with the corresponding ReferenceIDs that are used to fetch // the associated endorsements. // // ReferenceID is the key used to fetch all the Endorsements // generated from claims extracted from the token type ExtractedClaims struct { - ClaimsSet map[string]interface{} `json:"claims-set"` - ReferenceID string `json:"reference-id"` + ClaimsSet map[string]interface{} `json:"claims-set"` + ReferenceIDs []string `json:"reference-ids"` // please refer issue #106 for unprocessed claim set } diff --git a/proto/evidence.pb.go b/proto/evidence.pb.go index d4946379..45fd89ad 100644 --- a/proto/evidence.pb.go +++ b/proto/evidence.pb.go @@ -26,10 +26,10 @@ type EvidenceContext struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - TenantId string `protobuf:"bytes,1,opt,name=tenant_id,json=tenant-id,proto3" json:"tenant_id,omitempty"` - TrustAnchorId string `protobuf:"bytes,2,opt,name=trust_anchor_id,json=trust-anchor-id,proto3" json:"trust_anchor_id,omitempty"` - ReferenceId string `protobuf:"bytes,3,opt,name=reference_id,json=reference-id,proto3" json:"reference_id,omitempty"` - Evidence *structpb.Struct `protobuf:"bytes,5,opt,name=evidence,proto3" json:"evidence,omitempty"` + TenantId string `protobuf:"bytes,1,opt,name=tenant_id,json=tenant-id,proto3" json:"tenant_id,omitempty"` + TrustAnchorIds []string `protobuf:"bytes,2,rep,name=trust_anchor_ids,json=trust-anchor-ids,proto3" json:"trust_anchor_ids,omitempty"` + ReferenceIds []string `protobuf:"bytes,3,rep,name=reference_ids,json=reference-ids,proto3" json:"reference_ids,omitempty"` + Evidence *structpb.Struct `protobuf:"bytes,5,opt,name=evidence,proto3" json:"evidence,omitempty"` } func (x *EvidenceContext) Reset() { @@ -71,18 +71,18 @@ func (x *EvidenceContext) GetTenantId() string { return "" } -func (x *EvidenceContext) GetTrustAnchorId() string { +func (x *EvidenceContext) GetTrustAnchorIds() []string { if x != nil { - return x.TrustAnchorId + return x.TrustAnchorIds } - return "" + return nil } -func (x *EvidenceContext) GetReferenceId() string { +func (x *EvidenceContext) GetReferenceIds() []string { if x != nil { - return x.ReferenceId + return x.ReferenceIds } - return "" + return nil } func (x *EvidenceContext) GetEvidence() *structpb.Struct { @@ -98,21 +98,21 @@ var file_evidence_proto_rawDesc = []byte{ 0x0a, 0x0e, 0x65, 0x76, 0x69, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xb2, 0x01, 0x0a, 0x0f, 0x45, 0x76, 0x69, 0x64, 0x65, 0x6e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xb6, 0x01, 0x0a, 0x0f, 0x45, 0x76, 0x69, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x74, 0x65, - 0x6e, 0x61, 0x6e, 0x74, 0x2d, 0x69, 0x64, 0x12, 0x28, 0x0a, 0x0f, 0x74, 0x72, 0x75, 0x73, 0x74, - 0x5f, 0x61, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0f, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2d, 0x61, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x2d, 0x69, - 0x64, 0x12, 0x22, 0x0a, 0x0c, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x5f, 0x69, - 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, - 0x63, 0x65, 0x2d, 0x69, 0x64, 0x12, 0x33, 0x0a, 0x08, 0x65, 0x76, 0x69, 0x64, 0x65, 0x6e, 0x63, - 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, - 0x52, 0x08, 0x65, 0x76, 0x69, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x42, 0x24, 0x5a, 0x22, 0x67, 0x69, - 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x65, 0x72, 0x61, 0x69, 0x73, 0x6f, - 0x6e, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6e, 0x61, 0x6e, 0x74, 0x2d, 0x69, 0x64, 0x12, 0x2a, 0x0a, 0x10, 0x74, 0x72, 0x75, 0x73, 0x74, + 0x5f, 0x61, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, + 0x09, 0x52, 0x10, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2d, 0x61, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x2d, + 0x69, 0x64, 0x73, 0x12, 0x24, 0x0a, 0x0d, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, + 0x5f, 0x69, 0x64, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x72, 0x65, 0x66, 0x65, + 0x72, 0x65, 0x6e, 0x63, 0x65, 0x2d, 0x69, 0x64, 0x73, 0x12, 0x33, 0x0a, 0x08, 0x65, 0x76, 0x69, + 0x64, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, + 0x72, 0x75, 0x63, 0x74, 0x52, 0x08, 0x65, 0x76, 0x69, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x42, 0x24, + 0x5a, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x65, 0x72, + 0x61, 0x69, 0x73, 0x6f, 0x6e, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/proto/evidence.proto b/proto/evidence.proto index a83c0a81..0887f37e 100644 --- a/proto/evidence.proto +++ b/proto/evidence.proto @@ -7,7 +7,7 @@ option go_package = "github.com/veraison/services/proto"; message EvidenceContext { string tenant_id = 1 [json_name = "tenant-id"]; - string trust_anchor_id = 2 [json_name = "trust-anchor-id"]; - string reference_id = 3 [json_name = "reference-id"]; + repeated string trust_anchor_ids = 2 [json_name = "trust-anchor-ids"]; + repeated string reference_ids = 3 [json_name = "reference-ids"]; google.protobuf.Struct evidence = 5; } diff --git a/scheme/cca-ssd-platform/evidence_handler.go b/scheme/cca-ssd-platform/evidence_handler.go index e5a688bf..a8f756b8 100644 --- a/scheme/cca-ssd-platform/evidence_handler.go +++ b/scheme/cca-ssd-platform/evidence_handler.go @@ -46,13 +46,17 @@ func (s EvidenceHandler) SynthKeysFromTrustAnchor(tenantID string, ta *handler.E return arm.SynthKeysFromTrustAnchors(SchemeName, tenantID, ta) } -func (s EvidenceHandler) GetTrustAnchorID(token *proto.AttestationToken) (string, error) { - return arm.GetTrustAnchorID(SchemeName, token) +func (s EvidenceHandler) GetTrustAnchorIDs(token *proto.AttestationToken) ([]string, error) { + ta, err := arm.GetTrustAnchorID(SchemeName, token) + if err != nil { + return nil, err + } + return []string{ta}, nil } func (s EvidenceHandler) ExtractClaims( token *proto.AttestationToken, - trustAnchor string, + trustAnchors []string, ) (*handler.ExtractedClaims, error) { var ccaToken ccatoken.Evidence @@ -80,12 +84,12 @@ func (s EvidenceHandler) ExtractClaims( "realm": realmClaimsSet, } - extracted.ReferenceID = arm.RefValLookupKey( + extracted.ReferenceIDs = []string{arm.RefValLookupKey( SchemeName, token.TenantId, arm.MustImplIDString(ccaToken.PlatformClaims), - ) - log.Debugf("extracted Reference ID Key = %s", extracted.ReferenceID) + )} + log.Debugf("extracted Reference ID Key = %s", extracted.ReferenceIDs) return &extracted, nil } @@ -95,7 +99,7 @@ func (s EvidenceHandler) ExtractClaims( // realm token. func (s EvidenceHandler) ValidateEvidenceIntegrity( token *proto.AttestationToken, - trustAnchor string, + trustAnchors []string, endorsementsStrings []string, ) error { var ( @@ -125,7 +129,7 @@ func (s EvidenceHandler) ValidateEvidenceIntegrity( ) } - pk, err := arm.GetPublicKeyFromTA(SchemeName, trustAnchor) + pk, err := arm.GetPublicKeyFromTA(SchemeName, trustAnchors[0]) if err != nil { return fmt.Errorf("could not get public key from trust anchor: %w", err) } diff --git a/scheme/cca-ssd-platform/evidence_handler_test.go b/scheme/cca-ssd-platform/evidence_handler_test.go index bffd2013..da740ace 100644 --- a/scheme/cca-ssd-platform/evidence_handler_test.go +++ b/scheme/cca-ssd-platform/evidence_handler_test.go @@ -27,7 +27,7 @@ var testNonce = []byte{ 0x41, 0x42, 0x41, 0x42, 0x41, 0x42, 0x41, 0x42, } -func Test_GetTrustAnchorID_ok(t *testing.T) { +func Test_GetTrustAnchorIDs_ok(t *testing.T) { tokenBytes, err := os.ReadFile("test/cca-token.cbor") require.NoError(t, err) @@ -37,11 +37,11 @@ func Test_GetTrustAnchorID_ok(t *testing.T) { Nonce: testNonce, } - expectedTaID := "CCA_SSD_PLATFORM://1/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=/AQICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC" + expectedTaID := []string{"CCA_SSD_PLATFORM://1/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=/AQICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC"} scheme := &EvidenceHandler{} - taID, err := scheme.GetTrustAnchorID(&token) + taID, err := scheme.GetTrustAnchorIDs(&token) require.NoError(t, err) assert.Equal(t, expectedTaID, taID) } @@ -169,8 +169,9 @@ func Test_ExtractVerifiedClaims_ok(t *testing.T) { Data: tokenBytes, Nonce: testNonce, } + ta := string(taEndValBytes) - extracted, err := scheme.ExtractClaims(&token, string(taEndValBytes)) + extracted, err := scheme.ExtractClaims(&token, []string{ta}) platformClaims := extracted.ClaimsSet["platform"].(map[string]interface{}) require.NoError(t, err) @@ -198,8 +199,9 @@ func Test_ValidateEvidenceIntegrity_ok(t *testing.T) { Data: tokenBytes, Nonce: testNonce, } + ta := string(taEndValBytes) - err = scheme.ValidateEvidenceIntegrity(&token, string(taEndValBytes), nil) + err = scheme.ValidateEvidenceIntegrity(&token, []string{ta}, nil) assert.NoError(t, err) } @@ -220,7 +222,8 @@ func Test_ValidateEvidenceIntegrity_invalid_key(t *testing.T) { } expectedErr := `could not get public key from trust anchor: could not decode subject public key info: unsupported key type: "PRIVATE KEY"` - err = scheme.ValidateEvidenceIntegrity(&token, string(taEndValBytes), nil) + ta := string(taEndValBytes) + err = scheme.ValidateEvidenceIntegrity(&token, []string{ta}, nil) assert.EqualError(t, err, expectedErr) } diff --git a/scheme/cca-ssd-platform/test/extracted.json b/scheme/cca-ssd-platform/test/extracted.json index eeea8b7d..3641e7bd 100644 --- a/scheme/cca-ssd-platform/test/extracted.json +++ b/scheme/cca-ssd-platform/test/extracted.json @@ -52,7 +52,7 @@ "cca-realm-public-key-hash-algo-id": "sha-512" } }, - "reference-id": "CCA_SSD_PLATFORM://1/BwYFBAMCAQAPDg0MCwoJCBcWFRQTEhEQHx4dHBsaGRg=/AQcGBQQDAgEADw4NDAsKCQgXFhUUExIREB8eHRwbGhkY", - "trust-anchor-id": "CCA_SSD_PLATFORM://1/BwYFBAMCAQAPDg0MCwoJCBcWFRQTEhEQHx4dHBsaGRg=/", + "reference-ids": ["CCA_SSD_PLATFORM://1/BwYFBAMCAQAPDg0MCwoJCBcWFRQTEhEQHx4dHBsaGRg=/AQcGBQQDAgEADw4NDAsKCQgXFhUUExIREB8eHRwbGhkY"], + "trust-anchor-ids": ["CCA_SSD_PLATFORM://1/BwYFBAMCAQAPDg0MCwoJCBcWFRQTEhEQHx4dHBsaGRg=/"], "tenant-id": "1" } diff --git a/scheme/parsec-cca/evidence_handler.go b/scheme/parsec-cca/evidence_handler.go index 62ae0e5b..4a4785c7 100644 --- a/scheme/parsec-cca/evidence_handler.go +++ b/scheme/parsec-cca/evidence_handler.go @@ -51,11 +51,15 @@ func (s EvidenceHandler) SynthKeysFromTrustAnchor(tenantID string, ta *handler.E return arm.SynthKeysFromTrustAnchors(SchemeName, tenantID, ta) } -func (s EvidenceHandler) GetTrustAnchorID(token *proto.AttestationToken) (string, error) { - return arm.GetTrustAnchorID(SchemeName, token) +func (s EvidenceHandler) GetTrustAnchorIDs(token *proto.AttestationToken) ([]string, error) { + ta, err := arm.GetTrustAnchorID(SchemeName, token) + if err != nil { + return nil, err + } + return []string{ta}, nil } -func (s EvidenceHandler) ExtractClaims(token *proto.AttestationToken, trustAnchor string) (*handler.ExtractedClaims, error) { +func (s EvidenceHandler) ExtractClaims(token *proto.AttestationToken, trustAnchors []string) (*handler.ExtractedClaims, error) { var ( extracted handler.ExtractedClaims evidence parsec_cca.Evidence @@ -89,16 +93,16 @@ func (s EvidenceHandler) ExtractClaims(token *proto.AttestationToken, trustAncho extracted.ClaimsSet = claimsSet - extracted.ReferenceID = arm.RefValLookupKey( + extracted.ReferenceIDs = []string{arm.RefValLookupKey( SchemeName, token.TenantId, arm.MustImplIDString(evidence.Pat.PlatformClaims), - ) - log.Debugf("extracted Reference ID Key = %s", extracted.ReferenceID) + )} + log.Debugf("extracted Reference ID Key = %s", extracted.ReferenceIDs) return &extracted, nil } -func (s EvidenceHandler) ValidateEvidenceIntegrity(token *proto.AttestationToken, trustAnchor string, endorsements []string) error { +func (s EvidenceHandler) ValidateEvidenceIntegrity(token *proto.AttestationToken, trustAnchors []string, endorsements []string) error { var ( evidence parsec_cca.Evidence ) @@ -107,7 +111,7 @@ func (s EvidenceHandler) ValidateEvidenceIntegrity(token *proto.AttestationToken return handler.BadEvidence(err) } - pk, err := arm.GetPublicKeyFromTA(SchemeName, trustAnchor) + pk, err := arm.GetPublicKeyFromTA(SchemeName, trustAnchors[0]) if err != nil { return fmt.Errorf("could not get public key from trust anchor: %w", err) } diff --git a/scheme/parsec-cca/evidence_handler_test.go b/scheme/parsec-cca/evidence_handler_test.go index c41b9cf6..9f93ef50 100644 --- a/scheme/parsec-cca/evidence_handler_test.go +++ b/scheme/parsec-cca/evidence_handler_test.go @@ -16,7 +16,7 @@ import ( "github.com/veraison/services/proto" ) -func Test_GetTrustAnchorID_ok(t *testing.T) { +func Test_GetTrustAnchorIDs_ok(t *testing.T) { tokenBytes, err := os.ReadFile("test/evidence/evidence.cbor") require.NoError(t, err) @@ -29,9 +29,9 @@ func Test_GetTrustAnchorID_ok(t *testing.T) { handler := &EvidenceHandler{} - taID, err := handler.GetTrustAnchorID(&token) + taIDs, err := handler.GetTrustAnchorIDs(&token) require.NoError(t, err) - assert.Equal(t, expectedTaID, taID) + assert.Equal(t, expectedTaID, taIDs[0]) } func Test_ExtractClaims_ok(t *testing.T) { @@ -48,7 +48,8 @@ func Test_ExtractClaims_ok(t *testing.T) { Data: tokenBytes, } - _, err = handler.ExtractClaims(&token, string(taEndValBytes)) + ta := string(taEndValBytes) + _, err = handler.ExtractClaims(&token, []string{ta}) require.NoError(t, err) } @@ -65,8 +66,8 @@ func Test_ExtractClaims_nok_bad_evidence(t *testing.T) { TenantId: "0", Data: tokenBytes, } - - _, err = h.ExtractClaims(&token, string(taEndValBytes)) + ta := string(taEndValBytes) + _, err = h.ExtractClaims(&token, []string{ta}) err1 := errors.Unwrap(err) require.NotNil(t, err1) assert.EqualError(t, err1, expectedErr) @@ -83,7 +84,8 @@ func Test_ValidateEvidenceIntegrity_ok(t *testing.T) { TenantId: "1", Data: tokenBytes, } - err = h.ValidateEvidenceIntegrity(&token, string(taEndValBytes), nil) + ta := string(taEndValBytes) + err = h.ValidateEvidenceIntegrity(&token, []string{ta}, nil) require.NoError(t, err) } @@ -120,6 +122,7 @@ func Test_ValidateEvidenceIntegrity_nok(t *testing.T) { require.NoError(t, err) taEndValBytes, err := os.ReadFile(tv.input) + ta := string(taEndValBytes) require.NoError(t, err) h := &EvidenceHandler{} @@ -128,7 +131,7 @@ func Test_ValidateEvidenceIntegrity_nok(t *testing.T) { Data: tokenBytes, } - err = h.ValidateEvidenceIntegrity(&token, string(taEndValBytes), nil) + err = h.ValidateEvidenceIntegrity(&token, []string{ta}, nil) assert.EqualError(t, err, tv.expectedErr) } } diff --git a/scheme/parsec-cca/test/evidence/extracted.json b/scheme/parsec-cca/test/evidence/extracted.json index be72e4ec..69939249 100755 --- a/scheme/parsec-cca/test/evidence/extracted.json +++ b/scheme/parsec-cca/test/evidence/extracted.json @@ -46,7 +46,7 @@ "nonce": "AAECAwQFBgc=" } }, - "reference-id": "PARSEC_CCA://0/f0VMRgIBAQAAAAAAAAAAAAMAPgABAAAAUFgAAAAAAAA=", - "trust-anchor-id": "PARSEC_CCA://1/f0VMRgIBAQAAAAAAAAAAAAMAPgABAAAAUFgAAAAAAAA=/AQcGBQQDAgEADw4NDAsKCQgXFhUUExIREB8eHRwbGhkY", + "reference-ids": ["PARSEC_CCA://0/f0VMRgIBAQAAAAAAAAAAAAMAPgABAAAAUFgAAAAAAAA="], + "trust-anchor-ids": ["PARSEC_CCA://1/f0VMRgIBAQAAAAAAAAAAAAMAPgABAAAAUFgAAAAAAAA=/AQcGBQQDAgEADw4NDAsKCQgXFhUUExIREB8eHRwbGhkY"], "tenant-id": "1" } \ No newline at end of file diff --git a/scheme/parsec-tpm/evidence_handler.go b/scheme/parsec-tpm/evidence_handler.go index 9ea1f759..1fb8bd07 100644 --- a/scheme/parsec-tpm/evidence_handler.go +++ b/scheme/parsec-tpm/evidence_handler.go @@ -74,24 +74,24 @@ func (s EvidenceHandler) SynthKeysFromTrustAnchor(tenantID string, ta *handler.E return synthKeysFromAttr(ScopeTrustAnchor, tenantID, ta.Attributes) } -func (s EvidenceHandler) GetTrustAnchorID(token *proto.AttestationToken) (string, error) { +func (s EvidenceHandler) GetTrustAnchorIDs(token *proto.AttestationToken) ([]string, error) { var ev tpm.Evidence err := ev.FromCBOR(token.Data) if err != nil { - return "", handler.BadEvidence(err) + return nil, handler.BadEvidence(err) } kat := ev.Kat if kat == nil { - return "", errors.New("no key attestation token to fetch Key ID") + return nil, errors.New("no key attestation token to fetch Key ID") } kid := *kat.KID instance_id := base64.StdEncoding.EncodeToString(kid) - return tpmLookupKey(ScopeTrustAnchor, token.TenantId, "", instance_id), nil + return []string{tpmLookupKey(ScopeTrustAnchor, token.TenantId, "", instance_id)}, nil } -func (s EvidenceHandler) ExtractClaims(token *proto.AttestationToken, trustAnchor string) (*handler.ExtractedClaims, error) { +func (s EvidenceHandler) ExtractClaims(token *proto.AttestationToken, trustAnchors []string) (*handler.ExtractedClaims, error) { var ( evidence tpm.Evidence endorsement TaEndorsements @@ -108,17 +108,17 @@ func (s EvidenceHandler) ExtractClaims(token *proto.AttestationToken, trustAncho return nil, handler.BadEvidence(err) } extracted.ClaimsSet = claimsSet - if err := json.Unmarshal([]byte(trustAnchor), &endorsement); err != nil { + if err := json.Unmarshal([]byte(trustAnchors[0]), &endorsement); err != nil { log.Errorf("Could not decode Endorsements in ExtractClaims: %v", err) return nil, fmt.Errorf("could not decode endorsement: %w", err) } class_id := *endorsement.Attr.ClassID - extracted.ReferenceID = tpmLookupKey(ScopeRefValues, token.TenantId, class_id, "") + extracted.ReferenceIDs = []string{tpmLookupKey(ScopeRefValues, token.TenantId, class_id, "")} return &extracted, nil } -func (s EvidenceHandler) ValidateEvidenceIntegrity(token *proto.AttestationToken, trustAnchor string, endorsements []string) error { +func (s EvidenceHandler) ValidateEvidenceIntegrity(token *proto.AttestationToken, trustAnchors []string, endorsements []string) error { var ( endorsement TaEndorsements ev tpm.Evidence @@ -128,7 +128,7 @@ func (s EvidenceHandler) ValidateEvidenceIntegrity(token *proto.AttestationToken return handler.BadEvidence(err) } - if err := json.Unmarshal([]byte(trustAnchor), &endorsement); err != nil { + if err := json.Unmarshal([]byte(trustAnchors[0]), &endorsement); err != nil { log.Errorf("Could not decode trust anchor in ValidateEvidenceIntegrity: %v", err) return fmt.Errorf("could not decode trust anchor: %w", err) } diff --git a/scheme/parsec-tpm/evidence_handler_test.go b/scheme/parsec-tpm/evidence_handler_test.go index 9c79b921..b8b6f580 100644 --- a/scheme/parsec-tpm/evidence_handler_test.go +++ b/scheme/parsec-tpm/evidence_handler_test.go @@ -15,7 +15,7 @@ import ( "github.com/veraison/services/proto" ) -func Test_GetTrustAnchorID_ok(t *testing.T) { +func Test_GetTrustAnchorIDs_ok(t *testing.T) { tokenBytes, err := os.ReadFile("test/evidence/evidence.cbor") require.NoError(t, err) @@ -28,9 +28,9 @@ func Test_GetTrustAnchorID_ok(t *testing.T) { handler := &EvidenceHandler{} - taID, err := handler.GetTrustAnchorID(&token) + taIDs, err := handler.GetTrustAnchorIDs(&token) require.NoError(t, err) - assert.Equal(t, expectedTaID, taID) + assert.Equal(t, []string{expectedTaID}, taIDs) } func Test_ExtractClaims_ok(t *testing.T) { @@ -46,8 +46,8 @@ func Test_ExtractClaims_ok(t *testing.T) { TenantId: "0", Data: tokenBytes, } - - ex, err := handler.ExtractClaims(&token, string(taEndValBytes)) + ta := string(taEndValBytes) + ex, err := handler.ExtractClaims(&token, []string{ta}) require.NoError(t, err) claims := ex.ClaimsSet assert.Equal(t, claims["kat"].(map[string]interface{})["kid"].(string), claims["pat"].(map[string]interface{})["kid"].(string)) @@ -66,8 +66,8 @@ func Test_ExtractClaims_nok_bad_evidence(t *testing.T) { TenantId: "0", Data: tokenBytes, } - - _, err = h.ExtractClaims(&token, string(taEndValBytes)) + ta := string(taEndValBytes) + _, err = h.ExtractClaims(&token, []string{ta}) err1 := errors.Unwrap(err) require.NotNil(t, err1) assert.EqualError(t, err1, expectedErr) @@ -86,8 +86,8 @@ func Test_ExtractClaims_nok_bad_endorsement(t *testing.T) { TenantId: "0", Data: tokenBytes, } - - _, err = h.ExtractClaims(&token, string(taEndValBytes)) + ta := string(taEndValBytes) + _, err = h.ExtractClaims(&token, []string{ta}) assert.EqualError(t, err, expectedErr) } @@ -102,7 +102,8 @@ func Test_ValidateEvidenceIntegrity_ok(t *testing.T) { TenantId: "1", Data: tokenBytes, } - err = h.ValidateEvidenceIntegrity(&token, string(taEndValBytes), nil) + ta := string(taEndValBytes) + err = h.ValidateEvidenceIntegrity(&token, []string{ta}, nil) require.NoError(t, err) } @@ -119,8 +120,8 @@ func Test_ValidateEvidenceIntegrity_nok(t *testing.T) { TenantId: "1", Data: tokenBytes, } - - err = h.ValidateEvidenceIntegrity(&token, string(taEndValBytes), nil) + ta := string(taEndValBytes) + err = h.ValidateEvidenceIntegrity(&token, []string{ta}, nil) err1 := errors.Unwrap(err) require.NotNil(t, err1) assert.EqualError(t, err1, expectedErr) @@ -161,8 +162,8 @@ func Test_ValidateEvidenceIntegrity_BadKey(t *testing.T) { TenantId: "1", Data: tokenBytes, } - - err = h.ValidateEvidenceIntegrity(&token, string(taEndValBytes), nil) + ta := string(taEndValBytes) + err = h.ValidateEvidenceIntegrity(&token, []string{ta}, nil) assert.EqualError(t, err, tv.expectedErr) } } diff --git a/scheme/parsec-tpm/test/evidence/extracted.json b/scheme/parsec-tpm/test/evidence/extracted.json index 38659415..9b78c954 100644 --- a/scheme/parsec-tpm/test/evidence/extracted.json +++ b/scheme/parsec-tpm/test/evidence/extracted.json @@ -14,7 +14,7 @@ "tpmVer": "2.0" } }, - "reference-id": "PARSEC_TPM://1/YWNtZS1pbXBsZW1lbnRhdGlvbi1pZC0wMDAwMDAwMDE=", - "trust-anchor-id": "PARSEC_TPM://1/AagIEsUMYDNxd1p5UuAACkxJGfJf9rcUZ/oyRFHDcAxn", + "reference-ids": ["PARSEC_TPM://1/YWNtZS1pbXBsZW1lbnRhdGlvbi1pZC0wMDAwMDAwMDE="], + "trust-anchor-ids": ["PARSEC_TPM://1/AagIEsUMYDNxd1p5UuAACkxJGfJf9rcUZ/oyRFHDcAxn"], "tenant-id": "1" } \ No newline at end of file diff --git a/scheme/parsec-tpm/test/evidence/matched_extracted.json b/scheme/parsec-tpm/test/evidence/matched_extracted.json index c227940b..45ef7fb0 100644 --- a/scheme/parsec-tpm/test/evidence/matched_extracted.json +++ b/scheme/parsec-tpm/test/evidence/matched_extracted.json @@ -14,7 +14,7 @@ "tpmVer": "2.0" } }, - "reference-id": "PARSEC_TPM://1/YWNtZS1pbXBsZW1lbnRhdGlvbi1pZC0wMDAwMDAwMDE=", - "trust-anchor-id": "PARSEC_TPM://1/AagIEsUMYDNxd1p5UuAACkxJGfJf9rcUZ/oyRFHDcAxn", + "reference-ids": ["PARSEC_TPM://1/YWNtZS1pbXBsZW1lbnRhdGlvbi1pZC0wMDAwMDAwMDE="], + "trust-anchor-ids": ["PARSEC_TPM://1/AagIEsUMYDNxd1p5UuAACkxJGfJf9rcUZ/oyRFHDcAxn"], "tenant-id": "1" } \ No newline at end of file diff --git a/scheme/psa-iot/evidence_handler.go b/scheme/psa-iot/evidence_handler.go index 772d4f54..9f634033 100644 --- a/scheme/psa-iot/evidence_handler.go +++ b/scheme/psa-iot/evidence_handler.go @@ -44,13 +44,18 @@ func (s EvidenceHandler) SynthKeysFromTrustAnchor(tenantID string, ta *handler.E return arm.SynthKeysFromTrustAnchors(SchemeName, tenantID, ta) } -func (s EvidenceHandler) GetTrustAnchorID(token *proto.AttestationToken) (string, error) { - return arm.GetTrustAnchorID(SchemeName, token) +func (s EvidenceHandler) GetTrustAnchorIDs(token *proto.AttestationToken) ([]string, error) { + taID, err := arm.GetTrustAnchorID(SchemeName, token) + if err != nil { + return nil, err + } + + return []string{taID}, nil } func (s EvidenceHandler) ExtractClaims( token *proto.AttestationToken, - trustAnchor string, + trustAnchors []string, ) (*handler.ExtractedClaims, error) { var psaToken psatoken.Evidence @@ -66,18 +71,18 @@ func (s EvidenceHandler) ExtractClaims( } extracted.ClaimsSet = claimsSet - extracted.ReferenceID = arm.RefValLookupKey( + extracted.ReferenceIDs = []string{arm.RefValLookupKey( SchemeName, token.TenantId, arm.MustImplIDString(psaToken.Claims), - ) - log.Printf("\n Extracted SW ID Key = %s", extracted.ReferenceID) + )} + log.Printf("\n Extracted SW ID Key = %s", extracted.ReferenceIDs) return &extracted, nil } func (s EvidenceHandler) ValidateEvidenceIntegrity( token *proto.AttestationToken, - trustAnchor string, + trustAnchors []string, endorsementsStrings []string, ) error { var ( @@ -100,7 +105,7 @@ func (s EvidenceHandler) ValidateEvidenceIntegrity( ) } - pk, err := arm.GetPublicKeyFromTA(SchemeName, trustAnchor) + pk, err := arm.GetPublicKeyFromTA(SchemeName, trustAnchors[0]) if err != nil { return fmt.Errorf("could not get public key from trust anchor: %w", err) } diff --git a/scheme/psa-iot/evidence_handler_test.go b/scheme/psa-iot/evidence_handler_test.go index 672ff6de..9c138454 100644 --- a/scheme/psa-iot/evidence_handler_test.go +++ b/scheme/psa-iot/evidence_handler_test.go @@ -21,7 +21,7 @@ var testNonce = []byte{ 0x1f, 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, } -func Test_GetTrustAnchorID_ok(t *testing.T) { +func Test_GetTrustAnchorIDs_ok(t *testing.T) { tokenBytes, err := os.ReadFile("test/psa-token.cbor") require.NoError(t, err) @@ -35,9 +35,10 @@ func Test_GetTrustAnchorID_ok(t *testing.T) { handler := &EvidenceHandler{} - taID, err := handler.GetTrustAnchorID(&token) + taIDs, err := handler.GetTrustAnchorIDs(&token) require.NoError(t, err) - assert.Equal(t, expectedTaID, taID) + assert.Equal(t, 1, len(taIDs)) + assert.Equal(t, expectedTaID, taIDs[0]) } func Test_ExtractVerifiedClaimsInteg_ok(t *testing.T) { @@ -54,8 +55,8 @@ func Test_ExtractVerifiedClaimsInteg_ok(t *testing.T) { Data: tokenBytes, Nonce: testNonce, } - - _, err = handler.ExtractClaims(&token, string(taEndValBytes)) + ta := string(taEndValBytes) + _, err = handler.ExtractClaims(&token, []string{ta}) require.NoError(t, err) @@ -75,8 +76,8 @@ func Test_ExtractVerifiedClaims_ok(t *testing.T) { Data: tokenBytes, Nonce: testNonce, } - - extracted, err := handler.ExtractClaims(&token, string(taEndValBytes)) + ta := string(taEndValBytes) + extracted, err := handler.ExtractClaims(&token, []string{ta}) require.NoError(t, err) assert.Equal(t, "PSA_IOT_PROFILE_1", extracted.ClaimsSet["psa-profile"].(string)) @@ -101,7 +102,8 @@ func Test_ValidateEvidenceIntegrity_ok(t *testing.T) { Nonce: testNonce, } - err = handler.ValidateEvidenceIntegrity(&token, string(taEndValBytes), nil) + ta := string(taEndValBytes) + err = handler.ValidateEvidenceIntegrity(&token, []string{ta}, nil) assert.NoError(t, err) } @@ -142,8 +144,9 @@ func Test_ValidateEvidenceIntegrity_BadKey(t *testing.T) { Data: tokenBytes, Nonce: testNonce, } + ta := string(taEndValBytes) + err = h.ValidateEvidenceIntegrity(&token, []string{ta}, nil) - err = h.ValidateEvidenceIntegrity(&token, string(taEndValBytes), nil) assert.EqualError(t, err, tv.expectedErr) } } diff --git a/scheme/psa-iot/test/extracted.json b/scheme/psa-iot/test/extracted.json index 958ec39c..d417c411 100644 --- a/scheme/psa-iot/test/extracted.json +++ b/scheme/psa-iot/test/extracted.json @@ -35,7 +35,7 @@ } ] }, - "reference-id": "PSA_IOT://1/BwYFBAMCAQAPDg0MCwoJCBcWFRQTEhEQHx4dHBsaGRg=/AQcGBQQDAgEADw4NDAsKCQgXFhUUExIREB8eHRwbGhkY", - "trust-anchor-id": "PSA_IOT://1/BwYFBAMCAQAPDg0MCwoJCBcWFRQTEhEQHx4dHBsaGRg=/", + "reference-ids": ["PSA_IOT://1/BwYFBAMCAQAPDg0MCwoJCBcWFRQTEhEQHx4dHBsaGRg=/AQcGBQQDAgEADw4NDAsKCQgXFhUUExIREB8eHRwbGhkY"], + "trust-anchor-ids": ["PSA_IOT://1/BwYFBAMCAQAPDg0MCwoJCBcWFRQTEhEQHx4dHBsaGRg=/"], "tenant-id": "1" } diff --git a/scheme/riot/evidence_handler.go b/scheme/riot/evidence_handler.go index 35caee71..82d6e4bc 100644 --- a/scheme/riot/evidence_handler.go +++ b/scheme/riot/evidence_handler.go @@ -33,8 +33,8 @@ func (s EvidenceHandler) GetSupportedMediaTypes() []string { return EvidenceMediaTypes } -func (s EvidenceHandler) GetTrustAnchorID(token *proto.AttestationToken) (string, error) { - return "dice://", nil +func (s EvidenceHandler) GetTrustAnchorIDs(token *proto.AttestationToken) ([]string, error) { + return []string{"dice://"}, nil } func (s EvidenceHandler) SynthKeysFromRefValue(tenantID string, swComp *handler.Endorsement) ([]string, error) { @@ -47,12 +47,12 @@ func (s EvidenceHandler) SynthKeysFromTrustAnchor(tenantID string, ta *handler.E func (s EvidenceHandler) ExtractClaims( token *proto.AttestationToken, - trustAnchor string, + trustAnchors []string, ) (*handler.ExtractedClaims, error) { roots := x509.NewCertPool() intermediates := x509.NewCertPool() - if err := parseTrustAnchor([]byte(trustAnchor), roots, intermediates); err != nil { + if err := parseTrustAnchor([]byte(trustAnchors[0]), roots, intermediates); err != nil { return nil, err } @@ -80,8 +80,8 @@ func (s EvidenceHandler) ExtractClaims( } extracted := handler.ExtractedClaims{ - ClaimsSet: claims, - ReferenceID: "dice://", + ClaimsSet: claims, + ReferenceIDs: []string{"dice://"}, } return &extracted, nil @@ -89,7 +89,7 @@ func (s EvidenceHandler) ExtractClaims( func (s EvidenceHandler) ValidateEvidenceIntegrity( token *proto.AttestationToken, - trustAnchor string, + trustAnchors []string, endorsements []string, ) error { // Cert verified earlier when extracting claims -- see note inside ExtractClaims above. diff --git a/scheme/riot/evidence_handler_test.go b/scheme/riot/evidence_handler_test.go index 02ba9870..64b7bc68 100644 --- a/scheme/riot/evidence_handler_test.go +++ b/scheme/riot/evidence_handler_test.go @@ -41,8 +41,8 @@ func Test_ExtractVerifiedClaims_ok(t *testing.T) { TenantId: "1", Data: deviceData, } - - evidence, err := s.ExtractClaims(&token, string(taData)) + ta := string(taData) + evidence, err := s.ExtractClaims(&token, []string{ta}) assert.Nil(t, err) assert.Equal(t, FWID, evidence.ClaimsSet["FWID"]) assert.Equal(t, DeviceID, evidence.ClaimsSet["DeviceID"]) diff --git a/scheme/tpm-enacttrust/evidence_handler.go b/scheme/tpm-enacttrust/evidence_handler.go index 5a7cc41f..a6ec5903 100644 --- a/scheme/tpm-enacttrust/evidence_handler.go +++ b/scheme/tpm-enacttrust/evidence_handler.go @@ -43,7 +43,7 @@ func (s EvidenceHandler) SynthKeysFromTrustAnchor(tenantID string, ta *handler.E return synthKeysFromAttrs("trust anchor", tenantID, ta.Attributes) } -func (s EvidenceHandler) GetTrustAnchorID(token *proto.AttestationToken) (string, error) { +func (s EvidenceHandler) GetTrustAnchorIDs(token *proto.AttestationToken) ([]string, error) { supported := false for _, mt := range EvidenceMediaTypes { if token.MediaType == mt { @@ -58,21 +58,21 @@ func (s EvidenceHandler) GetTrustAnchorID(token *proto.AttestationToken) (string strings.Join(EvidenceMediaTypes, ", "), token.MediaType, ) - return "", err + return nil, err } var decoded Token if err := decoded.Decode(token.Data); err != nil { - return "", handler.BadEvidence(err) + return nil, handler.BadEvidence(err) } - return tpmEnactTrustLookupKey(token.TenantId, decoded.NodeId.String()), nil + return []string{tpmEnactTrustLookupKey(token.TenantId, decoded.NodeId.String())}, nil } func (s EvidenceHandler) ExtractClaims( token *proto.AttestationToken, - trustAnchor string, + trustAnchors []string, ) (*handler.ExtractedClaims, error) { supported := false for _, mt := range EvidenceMediaTypes { @@ -111,14 +111,14 @@ func (s EvidenceHandler) ExtractClaims( evidence.ClaimsSet["firmware-version"] = decoded.AttestationData.FirmwareVersion evidence.ClaimsSet["node-id"] = decoded.NodeId.String() evidence.ClaimsSet["pcr-digest"] = []byte(decoded.AttestationData.AttestedQuoteInfo.PCRDigest) - evidence.ReferenceID = tpmEnactTrustLookupKey(token.TenantId, decoded.NodeId.String()) + evidence.ReferenceIDs = []string{tpmEnactTrustLookupKey(token.TenantId, decoded.NodeId.String())} return evidence, nil } func (s EvidenceHandler) ValidateEvidenceIntegrity( token *proto.AttestationToken, - trustAnchor string, + trustAnchors []string, endorsements []string, ) error { var decoded Token @@ -127,7 +127,7 @@ func (s EvidenceHandler) ValidateEvidenceIntegrity( return handler.BadEvidence("could not decode token: %w", err) } - pubKey, err := parseKey(trustAnchor) + pubKey, err := parseKey(trustAnchors[0]) if err != nil { return fmt.Errorf("could not parse trust anchor: %w", err) } diff --git a/scheme/tpm-enacttrust/evidence_handler_test.go b/scheme/tpm-enacttrust/evidence_handler_test.go index 1c0ce83f..50335f6d 100644 --- a/scheme/tpm-enacttrust/evidence_handler_test.go +++ b/scheme/tpm-enacttrust/evidence_handler_test.go @@ -27,7 +27,7 @@ func Test_DecodeAttestationData_ok(t *testing.T) { assert.Equal(t, uint64(0x7), decoded.AttestationData.FirmwareVersion) } -func Test_GetTrustAnchorID_ok(t *testing.T) { +func Test_GetTrustAnchorIds_ok(t *testing.T) { data, err := os.ReadFile("test/tokens/basic.token") require.NoError(t, err) @@ -39,9 +39,9 @@ func Test_GetTrustAnchorID_ok(t *testing.T) { var s EvidenceHandler - taID, err := s.GetTrustAnchorID(&ta) + taIDs, err := s.GetTrustAnchorIDs(&ta) require.NoError(t, err) - assert.Equal(t, "TPM_ENACTTRUST://0/7df7714e-aa04-4638-bcbf-434b1dd720f1", taID) + assert.Equal(t, "TPM_ENACTTRUST://0/7df7714e-aa04-4638-bcbf-434b1dd720f1", taIDs[0]) } func readPublicKeyBytes(path string) ([]byte, error) { @@ -69,7 +69,7 @@ func Test_ExtractVerifiedClaims_ok(t *testing.T) { require.NoError(t, err) trustAnchor := base64.StdEncoding.EncodeToString(trustAnchorBytes) - ev, err := s.ExtractClaims(&ta, trustAnchor) + ev, err := s.ExtractClaims(&ta, []string{trustAnchor}) require.Nil(t, err) expectedPCRDigest := []byte{ @@ -78,7 +78,8 @@ func Test_ExtractVerifiedClaims_ok(t *testing.T) { 0x7a, 0xf, 0xde, 0x60, 0xc4, 0xcf, 0x25, 0xc7, } - assert.Equal(t, "TPM_ENACTTRUST://0/7df7714e-aa04-4638-bcbf-434b1dd720f1", ev.ReferenceID) + assert.Equal(t, 1, len(ev.ReferenceIDs)) + assert.Equal(t, "TPM_ENACTTRUST://0/7df7714e-aa04-4638-bcbf-434b1dd720f1", ev.ReferenceIDs[0]) assert.Equal(t, []interface{}{int64(1), int64(2), int64(3), int64(4)}, ev.ClaimsSet["pcr-selection"]) assert.Equal(t, int64(11), ev.ClaimsSet["hash-algorithm"]) @@ -99,8 +100,8 @@ func Test_ValidateEvidenceIntegrity_ok(t *testing.T) { trustAnchorBytes, err := os.ReadFile("test/trustanchor.json") require.NoError(t, err) - - err = s.ValidateEvidenceIntegrity(&ta, string(trustAnchorBytes), nil) + tas := string(trustAnchorBytes) + err = s.ValidateEvidenceIntegrity(&ta, []string{tas}, nil) assert.Nil(t, err) } @@ -118,10 +119,10 @@ func Test_GetAttestation(t *testing.T) { require.NoError(t, err) evidenceContext := &proto.EvidenceContext{ - TenantId: "0", - TrustAnchorId: "TPM_ENACTTRUST://0/7df7714e-aa04-4638-bcbf-434b1dd720f1", - ReferenceId: "TPM_ENACTTRUST://0/7df7714e-aa04-4638-bcbf-434b1dd720f1", - Evidence: evStruct, + TenantId: "0", + TrustAnchorIds: []string{"TPM_ENACTTRUST://0/7df7714e-aa04-4638-bcbf-434b1dd720f1"}, + ReferenceIds: []string{"TPM_ENACTTRUST://0/7df7714e-aa04-4638-bcbf-434b1dd720f1"}, + Evidence: evStruct, } refvalBytes, err := os.ReadFile("test/refval.json") diff --git a/vts/policymanager/policymanager_test.go b/vts/policymanager/policymanager_test.go index a9eb41dd..7ccd15e4 100644 --- a/vts/policymanager/policymanager_test.go +++ b/vts/policymanager/policymanager_test.go @@ -38,10 +38,10 @@ func TestPolicyMgr_getPolicy_not_found(t *testing.T) { appraisal := &appraisal.Appraisal{ Scheme: "TPM_ENACTTRUST", EvidenceContext: &proto.EvidenceContext{ - TenantId: "0", - TrustAnchorId: "TPM_ENACTTRUST://0/7df7714e-aa04-4638-bcbf-434b1dd720f1", - ReferenceId: "TPM_ENACTTRUST://0/7df7714e-aa04-4638-bcbf-434b1dd720f1", - Evidence: evStruct, + TenantId: "0", + TrustAnchorIds: []string{"TPM_ENACTTRUST://0/7df7714e-aa04-4638-bcbf-434b1dd720f1"}, + ReferenceIds: []string{"TPM_ENACTTRUST://0/7df7714e-aa04-4638-bcbf-434b1dd720f1"}, + Evidence: evStruct, }, } @@ -73,10 +73,10 @@ func TestPolicyMgr_getPolicy_OK(t *testing.T) { appraisal := &appraisal.Appraisal{ Scheme: "TPM_ENACTTRUST", EvidenceContext: &proto.EvidenceContext{ - TenantId: "0", - TrustAnchorId: "TPM_ENACTTRUST://0/7df7714e-aa04-4638-bcbf-434b1dd720f1", - ReferenceId: "TPM_ENACTTRUST://0/7df7714e-aa04-4638-bcbf-434b1dd720f1", - Evidence: evStruct, + TenantId: "0", + TrustAnchorIds: []string{"TPM_ENACTTRUST://0/7df7714e-aa04-4638-bcbf-434b1dd720f1"}, + ReferenceIds: []string{"TPM_ENACTTRUST://0/7df7714e-aa04-4638-bcbf-434b1dd720f1"}, + Evidence: evStruct, }, } @@ -121,10 +121,10 @@ func TestPolicyMgr_Evaluate_OK(t *testing.T) { Return([]string{`{"uuid": "7df7714e-aa04-4638-bcbf-434b1dd720f1", "active": true}`}, nil) ec := &proto.EvidenceContext{ - TenantId: "0", - TrustAnchorId: "TPM_ENACTTRUST://0/7df7714e-aa04-4638-bcbf-434b1dd720f1", - ReferenceId: "TPM_ENACTTRUST://0/7df7714e-aa04-4638-bcbf-434b1dd720f1", - Evidence: evStruct, + TenantId: "0", + TrustAnchorIds: []string{"TPM_ENACTTRUST://0/7df7714e-aa04-4638-bcbf-434b1dd720f1"}, + ReferenceIds: []string{"TPM_ENACTTRUST://0/7df7714e-aa04-4638-bcbf-434b1dd720f1"}, + Evidence: evStruct, } endorsements := []string{"h0KPxSKAPTEGXnvOPPA/5HUJZjHl4Hu9eg/eYMTPJcc="} ar := ear.NewAttestationResult("test", "test", "test") @@ -167,10 +167,10 @@ func TestPolicyMgr_Evaluate_NOK(t *testing.T) { Return([]string{`{"uuid": "7df7714e-aa04-4638-bcbf-434b1dd720f1", "active": true}`}, nil) ec := &proto.EvidenceContext{ - TenantId: "0", - TrustAnchorId: "TPM_ENACTTRUST://0/7df7714e-aa04-4638-bcbf-434b1dd720f1", - ReferenceId: "TPM_ENACTTRUST://0/7df7714e-aa04-4638-bcbf-434b1dd720f1", - Evidence: evStruct, + TenantId: "0", + TrustAnchorIds: []string{"TPM_ENACTTRUST://0/7df7714e-aa04-4638-bcbf-434b1dd720f1"}, + ReferenceIds: []string{"TPM_ENACTTRUST://0/7df7714e-aa04-4638-bcbf-434b1dd720f1"}, + Evidence: evStruct, } endorsements := []string{"h0KPxSKAPTEGXnvOPPA/5HUJZjHl4Hu9eg/eYMTPJcc="} ar := ear.NewAttestationResult("test", "test", "test") diff --git a/vts/trustedservices/trustedservices_grpc.go b/vts/trustedservices/trustedservices_grpc.go index 03db670d..6d5ef9e0 100644 --- a/vts/trustedservices/trustedservices_grpc.go +++ b/vts/trustedservices/trustedservices_grpc.go @@ -335,18 +335,18 @@ func (o *GRPC) GetAttestation( return o.finalize(appraisal, err) } - ta, err := o.getTrustAnchor(appraisal.EvidenceContext.TrustAnchorId) + tas, err := o.getTrustAnchors(appraisal.EvidenceContext.TrustAnchorIds) if err != nil { if errors.Is(err, kvstore.ErrKeyNotFound) { err = handlermod.BadEvidence("no trust anchor for %s", - appraisal.EvidenceContext.TrustAnchorId) + appraisal.EvidenceContext.TrustAnchorIds) appraisal.SetAllClaims(ear.CryptoValidationFailedClaim) appraisal.AddPolicyClaim("problem", "no trust anchor for evidence") } return o.finalize(appraisal, err) } - extracted, err := handler.ExtractClaims(token, ta) + extracted, err := handler.ExtractClaims(token, tas) if err != nil { if errors.Is(err, handlermod.BadEvidenceError{}) { appraisal.AddPolicyClaim("problem", err.Error()) @@ -360,22 +360,28 @@ func (o *GRPC) GetAttestation( return o.finalize(appraisal, err) } - appraisal.EvidenceContext.ReferenceId = extracted.ReferenceID + appraisal.EvidenceContext.ReferenceIds = extracted.ReferenceIDs o.logger.Debugw("constructed evidence context", - "software-id", appraisal.EvidenceContext.ReferenceId, - "trust-anchor-id", appraisal.EvidenceContext.TrustAnchorId) + "software-id", appraisal.EvidenceContext.ReferenceIds, + "trust-anchor-id", appraisal.EvidenceContext.TrustAnchorIds) - endorsements, err := o.EnStore.Get(appraisal.EvidenceContext.ReferenceId) - if err != nil && !errors.Is(err, kvstore.ErrKeyNotFound) { - return o.finalize(appraisal, err) - } + var tendorsements []string + for _, reference := range appraisal.EvidenceContext.ReferenceIds { + + endorsements, err := o.EnStore.Get(reference) + if err != nil && !errors.Is(err, kvstore.ErrKeyNotFound) { + return o.finalize(appraisal, err) + } + + if len(endorsements) > 0 { + o.logger.Debugw("obtained endorsements", "endorsements", endorsements) + } + tendorsements = append(tendorsements, endorsements...) - if len(endorsements) > 0 { - o.logger.Debugw("obtained endorsements", "endorsements", endorsements) } - if err = handler.ValidateEvidenceIntegrity(token, ta, endorsements); err != nil { + if err = handler.ValidateEvidenceIntegrity(token, tas, tendorsements); err != nil { if errors.Is(err, handlermod.BadEvidenceError{}) { appraisal.SetAllClaims(ear.CryptoValidationFailedClaim) appraisal.AddPolicyClaim("problem", "integrity validation failed") @@ -383,7 +389,7 @@ func (o *GRPC) GetAttestation( return o.finalize(appraisal, err) } - appraisedResult, err := handler.AppraiseEvidence(appraisal.EvidenceContext, endorsements) + appraisedResult, err := handler.AppraiseEvidence(appraisal.EvidenceContext, tendorsements) if err != nil { return o.finalize(appraisal, err) } @@ -391,7 +397,7 @@ func (o *GRPC) GetAttestation( appraisal.Result = appraisedResult appraisal.InitPolicyID() - err = o.PolicyManager.Evaluate(ctx, handler.GetAttestationScheme(), appraisal, endorsements) + err = o.PolicyManager.Evaluate(ctx, handler.GetAttestationScheme(), appraisal, tendorsements) if err != nil { return o.finalize(appraisal, err) } @@ -408,7 +414,7 @@ func (c *GRPC) initEvidenceContext( var err error appraisal := appraisal.New(token.TenantId, token.Nonce, handler.GetAttestationScheme()) - appraisal.EvidenceContext.TrustAnchorId, err = handler.GetTrustAnchorID(token) + appraisal.EvidenceContext.TrustAnchorIds, err = handler.GetTrustAnchorIDs(token) if errors.Is(err, handlermod.BadEvidenceError{}) { appraisal.SetAllClaims(ear.CryptoValidationFailedClaim) @@ -418,17 +424,22 @@ func (c *GRPC) initEvidenceContext( return appraisal, err } -func (c *GRPC) getTrustAnchor(id string) (string, error) { - values, err := c.TaStore.Get(id) - if err != nil { - return "", err - } +func (c *GRPC) getTrustAnchors(id []string) ([]string, error) { + + ta_values := make([]string, 0) + for _, taId := range id { + values, err := c.TaStore.Get(taId) + if err != nil { + return []string{""}, err + } - if len(values) != 1 { - return "", fmt.Errorf("found %d trust anchors, want 1", len(values)) + if len(values) != 1 { + return []string{""}, fmt.Errorf("found %d trust anchors, want 1", len(values)) + } + ta_values = append(ta_values, values[0]) } - return values[0], nil + return ta_values, nil } func (c *GRPC) GetSupportedVerificationMediaTypes(context.Context, *emptypb.Empty) (*proto.MediaTypeList, error) {