diff --git a/handler/evidence_rpc.go b/handler/evidence_rpc.go index c6b1ed0c..36f30f19 100644 --- a/handler/evidence_rpc.go +++ b/handler/evidence_rpc.go @@ -163,12 +163,15 @@ func (s *RPCClient) GetSupportedMediaTypes() []string { return resp } -func (s *RPCClient) ExtractEvidence(token *proto.AttestationToken, trustAnchors []string) (*ExtractedClaims, error) { +func (s *RPCClient) ExtractEvidence( + token *proto.AttestationToken, + trustAnchors []string, +) (map[string]interface{}, error) { var ( err error args ExtractClaimsArgs resp []byte - extracted ExtractedClaims + extracted map[string]interface{} ) args.Token, err = json.Marshal(token) @@ -188,7 +191,7 @@ func (s *RPCClient) ExtractEvidence(token *proto.AttestationToken, trustAnchors return nil, fmt.Errorf("unmarshaling extracted evidence: %w", err) } - return &extracted, nil + return extracted, nil } func (s *RPCClient) ValidateEvidenceIntegrity( @@ -240,11 +243,14 @@ func (s *RPCClient) AppraiseEvidence(ec *proto.EvidenceContext, endorsements []s return &result, err } -func (s *RPCClient) ExtractClaims(token *proto.AttestationToken, trustAnchors []string) (*ExtractedClaims, error) { +func (s *RPCClient) ExtractClaims( + token *proto.AttestationToken, + trustAnchors []string, +) (map[string]interface{}, error) { var ( err error args ExtractClaimsArgs - extractedClaims ExtractedClaims + extractedClaims map[string]interface{} ) args.Token, err = json.Marshal(token) @@ -266,5 +272,5 @@ func (s *RPCClient) ExtractClaims(token *proto.AttestationToken, trustAnchors [] return nil, fmt.Errorf("unmarshaling extracted claims: %w", err) } - return &extractedClaims, nil + return extractedClaims, nil } diff --git a/handler/ievidencehandler.go b/handler/ievidencehandler.go index 06345bc1..84f3c7c4 100644 --- a/handler/ievidencehandler.go +++ b/handler/ievidencehandler.go @@ -19,7 +19,7 @@ type IEvidenceHandler interface { ExtractClaims( token *proto.AttestationToken, trustAnchors []string, - ) (*ExtractedClaims, error) + ) (map[string]interface{}, error) // ValidateEvidenceIntegrity verifies the structural integrity and validity of the // token. The exact checks performed are scheme-specific, but they @@ -50,21 +50,3 @@ type IEvidenceHandler interface { endorsements []string, ) (*ear.AttestationResult, error) } - -// ExtractedClaims contains a map of claims extracted from an attestation -// 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"` - ReferenceIDs []string `json:"reference-ids"` - // please refer issue #106 for unprocessed claim set -} - -func NewExtractedClaims() *ExtractedClaims { - return &ExtractedClaims{ - ClaimsSet: make(map[string]interface{}), - } -} diff --git a/handler/istorehandler.go b/handler/istorehandler.go index 4b838b90..42e0ec92 100644 --- a/handler/istorehandler.go +++ b/handler/istorehandler.go @@ -22,7 +22,11 @@ type IStoreHandler interface { // GetRefValueIDs returns a slice of refrence value identifiers used token // to retrieve the reference values associated with the token from // which the claims have been extracted. - GetRefValueIDs(claims *ExtractedClaims) ([]string, error) + GetRefValueIDs( + tenantID string, + trustAnchors []string, + claims map[string]interface{}, + ) ([]string, error) // SynthKeysFromRefValue synthesizes lookup key(s) for the // provided reference value endorsement. diff --git a/handler/store_rpc.go b/handler/store_rpc.go index 94cf64ab..f87e6ed3 100644 --- a/handler/store_rpc.go +++ b/handler/store_rpc.go @@ -101,6 +101,28 @@ func (s *StoreRPCServer) GetTrustAnchorIDs(data []byte, resp *[]string) error { return err } +type GetRefValueIDsArgs struct { + TenantID string + TrustAnchors []string + Claims []byte +} + +func (s *StoreRPCServer) GetRefValueIDs(args GetRefValueIDsArgs, resp *[]string) error { + var claims map[string]interface{} + + err := json.Unmarshal(args.Claims, &claims) + if err != nil { + return fmt.Errorf("unmarshaling token: %w", err) + } + + *resp, err = s.Impl.GetRefValueIDs(args.TenantID, args.TrustAnchors, claims) + if err != nil { + return err + } + + return err +} + /* RPC client (plugin caller side) @@ -230,3 +252,32 @@ func (s *StoreRPCClient) GetTrustAnchorIDs(token *proto.AttestationToken) ([]str return resp, nil } + +func (s *StoreRPCClient) GetRefValueIDs( + tenantID string, + trustAnchors []string, + claims map[string]interface{}, +) ([]string, error) { + var ( + err error + resp []string + ) + + args := GetRefValueIDsArgs{ + TenantID: tenantID, + TrustAnchors: trustAnchors, + } + + args.Claims, err = json.Marshal(claims) + if err != nil { + return nil, err + } + + err = s.client.Call("Plugin.GetRefValueIDs", args, &resp) + if err != nil { + err = ParseError(err) + return nil, fmt.Errorf("Plugin.GetRefValueIDs RPC call failed: %w", err) // nolint + } + + return resp, nil +} diff --git a/scheme/cca-ssd-platform/evidence_handler.go b/scheme/cca-ssd-platform/evidence_handler.go index 05b2d5f1..019588ae 100644 --- a/scheme/cca-ssd-platform/evidence_handler.go +++ b/scheme/cca-ssd-platform/evidence_handler.go @@ -36,7 +36,7 @@ func (s EvidenceHandler) GetSupportedMediaTypes() []string { func (s EvidenceHandler) ExtractClaims( token *proto.AttestationToken, trustAnchors []string, -) (*handler.ExtractedClaims, error) { +) (map[string]interface{}, error) { var ccaToken ccatoken.Evidence @@ -44,7 +44,6 @@ func (s EvidenceHandler) ExtractClaims( return nil, handler.BadEvidence(err) } - var extracted handler.ExtractedClaims platformClaimsSet, err := common.ClaimsToMap(ccaToken.PlatformClaims) if err != nil { @@ -58,12 +57,12 @@ func (s EvidenceHandler) ExtractClaims( "could not convert realm claims: %w", err)) } - extracted.ClaimsSet = map[string]interface{}{ + extracted := map[string]interface{}{ "platform": platformClaimsSet, "realm": realmClaimsSet, } - return &extracted, nil + return extracted, nil } // ValidateEvidenceIntegrity, decodes CCA collection and then invokes Verify API of ccatoken library diff --git a/scheme/cca-ssd-platform/evidence_handler_test.go b/scheme/cca-ssd-platform/evidence_handler_test.go index fb4b6936..69c1a86f 100644 --- a/scheme/cca-ssd-platform/evidence_handler_test.go +++ b/scheme/cca-ssd-platform/evidence_handler_test.go @@ -110,7 +110,7 @@ func Test_ExtractVerifiedClaims_ok(t *testing.T) { ta := string(taEndValBytes) extracted, err := scheme.ExtractClaims(&token, []string{ta}) - platformClaims := extracted.ClaimsSet["platform"].(map[string]interface{}) + platformClaims := extracted["platform"].(map[string]interface{}) require.NoError(t, err) assert.Equal(t, "http://arm.com/CCA-SSD/1.0.0", diff --git a/scheme/cca-ssd-platform/store_handler.go b/scheme/cca-ssd-platform/store_handler.go index d88d0997..1f5b2f89 100644 --- a/scheme/cca-ssd-platform/store_handler.go +++ b/scheme/cca-ssd-platform/store_handler.go @@ -47,8 +47,12 @@ func (s StoreHandler) GetTrustAnchorIDs(token *proto.AttestationToken) ([]string return []string{ta}, nil } -func (s StoreHandler) GetRefValueIDs(claims *handler.ExtractedClaims) ([]string, error) { - platformClaimsMap, ok := claims.ClaimsSet["platform"].(map[string]interface{}) +func (s StoreHandler) GetRefValueIDs( + tenantID string, + trustAnchors []string, + claims map[string]interface{}, +) ([]string, error) { + platformClaimsMap, ok := claims["platform"].(map[string]interface{}) if !ok { return nil, fmt.Errorf("claims to do not contain patform map: %v", claims) } @@ -60,7 +64,7 @@ func (s StoreHandler) GetRefValueIDs(claims *handler.ExtractedClaims) ([]string, return []string{arm.RefValLookupKey( SchemeName, - claims.TenantId, + tenantID, arm.MustImplIDString(platformClaims), )}, nil } diff --git a/scheme/parsec-cca/evidence_handler.go b/scheme/parsec-cca/evidence_handler.go index 686638b6..ad983208 100644 --- a/scheme/parsec-cca/evidence_handler.go +++ b/scheme/parsec-cca/evidence_handler.go @@ -38,9 +38,11 @@ func (s EvidenceHandler) GetSupportedMediaTypes() []string { return EvidenceMediaTypes } -func (s EvidenceHandler) ExtractClaims(token *proto.AttestationToken, trustAnchors []string) (*handler.ExtractedClaims, error) { +func (s EvidenceHandler) ExtractClaims( + token *proto.AttestationToken, + trustAnchors []string, +) (map[string]interface{}, error) { var ( - extracted handler.ExtractedClaims evidence parsec_cca.Evidence claimsSet = make(map[string]interface{}) kat = make(map[string]interface{}) @@ -70,9 +72,7 @@ func (s EvidenceHandler) ExtractClaims(token *proto.AttestationToken, trustAncho } claimsSet["cca.realm"] = rmap - extracted.ClaimsSet = claimsSet - - return &extracted, nil + return claimsSet, nil } func (s EvidenceHandler) ValidateEvidenceIntegrity(token *proto.AttestationToken, trustAnchors []string, endorsements []string) error { diff --git a/scheme/parsec-cca/store_handler.go b/scheme/parsec-cca/store_handler.go index 90d599f7..9b23cddf 100644 --- a/scheme/parsec-cca/store_handler.go +++ b/scheme/parsec-cca/store_handler.go @@ -46,8 +46,12 @@ func (s StoreHandler) GetTrustAnchorIDs(token *proto.AttestationToken) ([]string return []string{ta}, nil } -func (s StoreHandler) GetRefValueIDs(claims *handler.ExtractedClaims) ([]string, error) { - platformClaimsMap, ok := claims.ClaimsSet["cca.platform"].(map[string]interface{}) +func (s StoreHandler) GetRefValueIDs( + tenantID string, + trustAnchors []string, + claims map[string]interface{}, +) ([]string, error) { + platformClaimsMap, ok := claims["cca.platform"].(map[string]interface{}) if !ok { return nil, fmt.Errorf("claims to do not contain patform map: %v", claims) } @@ -59,7 +63,7 @@ func (s StoreHandler) GetRefValueIDs(claims *handler.ExtractedClaims) ([]string, return []string{arm.RefValLookupKey( SchemeName, - claims.TenantId, + tenantID, arm.MustImplIDString(platformClaims), )}, nil } diff --git a/scheme/parsec-tpm/common.go b/scheme/parsec-tpm/common.go new file mode 100644 index 00000000..389246dc --- /dev/null +++ b/scheme/parsec-tpm/common.go @@ -0,0 +1,9 @@ +// Copyright 2024 Contributors to the Veraison project. +// SPDX-License-Identifier: Apache-2.0 +package parsec_tpm + +const ( + ScopeTrustAnchor = "trust anchor" + ScopeRefValues = "ref values" +) + diff --git a/scheme/parsec-tpm/evidence_handler.go b/scheme/parsec-tpm/evidence_handler.go index 2f431c6b..c7f04f58 100644 --- a/scheme/parsec-tpm/evidence_handler.go +++ b/scheme/parsec-tpm/evidence_handler.go @@ -8,9 +8,7 @@ import ( "encoding/json" "errors" "fmt" - "net/url" "sort" - "strings" "github.com/veraison/ear" "github.com/veraison/parsec/tpm" @@ -21,11 +19,6 @@ import ( "github.com/veraison/swid" ) -const ( - ScopeTrustAnchor = "trust anchor" - ScopeRefValues = "ref values" -) - type EvidenceHandler struct{} type SwAttr struct { @@ -65,31 +58,23 @@ func (s EvidenceHandler) GetSupportedMediaTypes() []string { return EvidenceMediaTypes } -func (s EvidenceHandler) ExtractClaims(token *proto.AttestationToken, trustAnchors []string) (*handler.ExtractedClaims, error) { - var ( - evidence tpm.Evidence - endorsement TaEndorsements - extracted handler.ExtractedClaims - ) +func (s EvidenceHandler) ExtractClaims( + token *proto.AttestationToken, + trustAnchors []string, +) (map[string]interface{}, error) { + var evidence tpm.Evidence err := evidence.FromCBOR(token.Data) if err != nil { return nil, handler.BadEvidence(err) } - claimsSet, err := evidenceAsMap(evidence) + claims, err := evidenceAsMap(evidence) if err != nil { return nil, handler.BadEvidence(err) } - extracted.ClaimsSet = claimsSet - 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.ReferenceIDs = []string{tpmLookupKey(ScopeRefValues, token.TenantId, class_id, "")} - return &extracted, nil + return claims, nil } func (s EvidenceHandler) ValidateEvidenceIntegrity(token *proto.AttestationToken, trustAnchors []string, endorsements []string) error { @@ -138,25 +123,6 @@ func (s EvidenceHandler) AppraiseEvidence(ec *proto.EvidenceContext, endorsement return result, err } -func tpmLookupKey(scope, tenantID, class, instance string) string { - var absPath []string - - switch scope { - case ScopeTrustAnchor: - absPath = []string{instance} - case ScopeRefValues: - absPath = []string{class} - } - - u := url.URL{ - Scheme: SchemeName, - Host: tenantID, - Path: strings.Join(absPath, "/"), - } - - return u.String() -} - func evidenceAsMap(e tpm.Evidence) (map[string]interface{}, error) { data, err := e.ToJSON() if err != nil { diff --git a/scheme/parsec-tpm/evidence_handler_test.go b/scheme/parsec-tpm/evidence_handler_test.go index f87395ee..65773d94 100644 --- a/scheme/parsec-tpm/evidence_handler_test.go +++ b/scheme/parsec-tpm/evidence_handler_test.go @@ -28,9 +28,8 @@ func Test_ExtractClaims_ok(t *testing.T) { Data: tokenBytes, } ta := string(taEndValBytes) - ex, err := handler.ExtractClaims(&token, []string{ta}) + claims, 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)) } @@ -54,21 +53,17 @@ func Test_ExtractClaims_nok_bad_evidence(t *testing.T) { assert.EqualError(t, err1, expectedErr) } -func Test_ExtractClaims_nok_bad_endorsement(t *testing.T) { - tokenBytes, err := os.ReadFile("test/evidence/evidence.cbor") - require.NoError(t, err) - +func Test_GetRefValueIDs_nok_bad_endorsement(t *testing.T) { taEndValBytes, err := os.ReadFile("test/evidence/bad_ta_endorsements.json") require.NoError(t, err) expectedErr := "could not decode endorsement: json: cannot unmarshal number into Go struct field TaAttr.attributes.parsec-tpm.class-id of type string" - h := &EvidenceHandler{} - token := proto.AttestationToken{ - TenantId: "0", - Data: tokenBytes, - } + h := &StoreHandler{} + ta := string(taEndValBytes) - _, err = h.ExtractClaims(&token, []string{ta}) + claims := map[string]interface{}{} + + _, err = h.GetRefValueIDs("0", []string{ta}, claims) assert.EqualError(t, err, expectedErr) } @@ -174,8 +169,10 @@ func Test_AppraiseEvidence_nok(t *testing.T) { var ec proto.EvidenceContext err = json.Unmarshal(extractedBytes, &ec) require.NoError(t, err) + endorsementsBytes, err := os.ReadFile(tv.input) require.NoError(t, err) + err = json.Unmarshal(endorsementsBytes, &endorsemementsArray) require.NoError(t, err) diff --git a/scheme/parsec-tpm/store_handler.go b/scheme/parsec-tpm/store_handler.go index 3e762744..27d67cb3 100644 --- a/scheme/parsec-tpm/store_handler.go +++ b/scheme/parsec-tpm/store_handler.go @@ -7,9 +7,12 @@ import ( "encoding/json" "errors" "fmt" + "net/url" + "strings" "github.com/veraison/parsec/tpm" "github.com/veraison/services/handler" + "github.com/veraison/services/log" "github.com/veraison/services/proto" ) @@ -52,6 +55,22 @@ func (s StoreHandler) GetTrustAnchorIDs(token *proto.AttestationToken) ([]string } +func (s StoreHandler) GetRefValueIDs( + tenantID string, + trustAnchors []string, + claims map[string]interface{}, +) ([]string, error) { + var endorsement TaEndorsements + + 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 + return []string{tpmLookupKey(ScopeRefValues, tenantID, class_id, "")}, nil +} + func synthKeysFromAttr(scope, tenantID string, attr json.RawMessage) ([]string, error) { var ( instance string @@ -85,3 +104,23 @@ func synthKeysFromAttr(scope, tenantID string, attr json.RawMessage) ([]string, return []string{tpmLookupKey(scope, tenantID, class, instance)}, nil } + +func tpmLookupKey(scope, tenantID, class, instance string) string { + var absPath []string + + switch scope { + case ScopeTrustAnchor: + absPath = []string{instance} + case ScopeRefValues: + absPath = []string{class} + } + + u := url.URL{ + Scheme: SchemeName, + Host: tenantID, + Path: strings.Join(absPath, "/"), + } + + return u.String() +} + diff --git a/scheme/psa-iot/evidence_handler.go b/scheme/psa-iot/evidence_handler.go index 7f8f2695..559bf9e3 100644 --- a/scheme/psa-iot/evidence_handler.go +++ b/scheme/psa-iot/evidence_handler.go @@ -34,22 +34,19 @@ func (s EvidenceHandler) GetSupportedMediaTypes() []string { func (s EvidenceHandler) ExtractClaims( token *proto.AttestationToken, trustAnchors []string, -) (*handler.ExtractedClaims, error) { +) (map[string]interface{}, error) { var psaToken psatoken.Evidence if err := psaToken.FromCOSE(token.Data); err != nil { return nil, handler.BadEvidence(err) } - var extracted handler.ExtractedClaims - claimsSet, err := common.ClaimsToMap(psaToken.Claims) if err != nil { return nil, handler.BadEvidence(err) } - extracted.ClaimsSet = claimsSet - return &extracted, nil + return claimsSet, nil } func (s EvidenceHandler) ValidateEvidenceIntegrity( diff --git a/scheme/psa-iot/evidence_handler_test.go b/scheme/psa-iot/evidence_handler_test.go index 4ddd214b..8e956b45 100644 --- a/scheme/psa-iot/evidence_handler_test.go +++ b/scheme/psa-iot/evidence_handler_test.go @@ -57,12 +57,12 @@ func Test_ExtractVerifiedClaims_ok(t *testing.T) { Nonce: testNonce, } ta := string(taEndValBytes) - extracted, err := handler.ExtractClaims(&token, []string{ta}) + claims, err := handler.ExtractClaims(&token, []string{ta}) require.NoError(t, err) - assert.Equal(t, "PSA_IOT_PROFILE_1", extracted.ClaimsSet["psa-profile"].(string)) + assert.Equal(t, "PSA_IOT_PROFILE_1", claims["psa-profile"].(string)) - swComponents := extracted.ClaimsSet["psa-software-components"].([]interface{}) + swComponents := claims["psa-software-components"].([]interface{}) assert.Len(t, swComponents, 4) assert.Equal(t, "BL", swComponents[0].(map[string]interface{})["measurement-type"].(string)) } diff --git a/scheme/psa-iot/store_handler.go b/scheme/psa-iot/store_handler.go index eaf27b0c..6c46dc9f 100644 --- a/scheme/psa-iot/store_handler.go +++ b/scheme/psa-iot/store_handler.go @@ -4,8 +4,6 @@ package psa_iot import ( - "fmt" - "github.com/veraison/services/handler" "github.com/veraison/services/proto" "github.com/veraison/services/scheme/common" @@ -46,15 +44,19 @@ func (s StoreHandler) GetTrustAnchorIDs(token *proto.AttestationToken) ([]string return []string{taID}, nil } -func (s StoreHandler) GetRefValueIDs(claims *handler.ExtractedClaims) ([]string, error) { - psaClaims, err := common.MapToClaims(claims.ClaimsSet) +func (s StoreHandler) GetRefValueIDs( + tenantID string, + trustAnchors []string, + claims map[string]interface{}, +) ([]string, error) { + psaClaims, err := common.MapToClaims(claims) if err != nil { return nil, err } return []string{arm.RefValLookupKey( SchemeName, - claims.TenantId, + tenantID, arm.MustImplIDString(psaClaims), )}, nil } diff --git a/scheme/riot/evidence_handler.go b/scheme/riot/evidence_handler.go index bb2143df..18de7415 100644 --- a/scheme/riot/evidence_handler.go +++ b/scheme/riot/evidence_handler.go @@ -36,7 +36,7 @@ func (s EvidenceHandler) GetSupportedMediaTypes() []string { func (s EvidenceHandler) ExtractClaims( token *proto.AttestationToken, trustAnchors []string, -) (*handler.ExtractedClaims, error) { +) (map[string]interface{}, error) { roots := x509.NewCertPool() intermediates := x509.NewCertPool() @@ -67,12 +67,7 @@ func (s EvidenceHandler) ExtractClaims( "failed to verify alias cert: " + err.Error()) } - extracted := handler.ExtractedClaims{ - ClaimsSet: claims, - ReferenceIDs: []string{"dice://"}, - } - - return &extracted, nil + return claims, nil } func (s EvidenceHandler) ValidateEvidenceIntegrity( diff --git a/scheme/riot/evidence_handler_test.go b/scheme/riot/evidence_handler_test.go index bb0ed0a1..3bb1b2f2 100644 --- a/scheme/riot/evidence_handler_test.go +++ b/scheme/riot/evidence_handler_test.go @@ -42,8 +42,8 @@ func Test_ExtractVerifiedClaims_ok(t *testing.T) { Data: deviceData, } ta := string(taData) - evidence, err := s.ExtractClaims(&token, []string{ta}) + claims, err := s.ExtractClaims(&token, []string{ta}) assert.Nil(t, err) - assert.Equal(t, FWID, evidence.ClaimsSet["FWID"]) - assert.Equal(t, DeviceID, evidence.ClaimsSet["DeviceID"]) + assert.Equal(t, FWID, claims["FWID"]) + assert.Equal(t, DeviceID, claims["DeviceID"]) } diff --git a/scheme/riot/store_handler.go b/scheme/riot/store_handler.go index 6fad429b..7618e566 100644 --- a/scheme/riot/store_handler.go +++ b/scheme/riot/store_handler.go @@ -29,6 +29,14 @@ func (s StoreHandler) GetTrustAnchorIDs(token *proto.AttestationToken) ([]string return []string{"dice://"}, nil } +func (s StoreHandler) GetRefValueIDs( + tenantID string, + trustAnchors []string, + claims map[string]interface{}, +) ([]string, error) { + return []string{"dice://"}, nil +} + func (s StoreHandler) SynthKeysFromRefValue(tenantID string, swComp *handler.Endorsement) ([]string, error) { return nil, errors.New("TODO") } diff --git a/scheme/tpm-enacttrust/evidence_handler.go b/scheme/tpm-enacttrust/evidence_handler.go index 669b4a5f..354a4d0f 100644 --- a/scheme/tpm-enacttrust/evidence_handler.go +++ b/scheme/tpm-enacttrust/evidence_handler.go @@ -6,7 +6,6 @@ import ( "crypto/ecdsa" "encoding/json" "fmt" - "net/url" "strings" tpm2 "github.com/google/go-tpm/tpm2" @@ -35,7 +34,7 @@ func (s EvidenceHandler) GetSupportedMediaTypes() []string { func (s EvidenceHandler) ExtractClaims( token *proto.AttestationToken, trustAnchors []string, -) (*handler.ExtractedClaims, error) { +) (map[string]interface{}, error) { supported := false for _, mt := range EvidenceMediaTypes { if token.MediaType == mt { @@ -67,15 +66,14 @@ func (s EvidenceHandler) ExtractClaims( pcrs = append(pcrs, int64(pcr)) } - evidence := handler.NewExtractedClaims() - evidence.ClaimsSet["pcr-selection"] = pcrs - evidence.ClaimsSet["hash-algorithm"] = int64(decoded.AttestationData.AttestedQuoteInfo.PCRSelection.Hash) - evidence.ClaimsSet["firmware-version"] = decoded.AttestationData.FirmwareVersion - evidence.ClaimsSet["node-id"] = decoded.NodeId.String() - evidence.ClaimsSet["pcr-digest"] = []byte(decoded.AttestationData.AttestedQuoteInfo.PCRDigest) - evidence.ReferenceIDs = []string{tpmEnactTrustLookupKey(token.TenantId, decoded.NodeId.String())} + claims := make(map[string]interface{}) + claims["pcr-selection"] = pcrs + claims["hash-algorithm"] = int64(decoded.AttestationData.AttestedQuoteInfo.PCRSelection.Hash) + claims["firmware-version"] = decoded.AttestationData.FirmwareVersion + claims["node-id"] = decoded.NodeId.String() + claims["pcr-digest"] = []byte(decoded.AttestationData.AttestedQuoteInfo.PCRDigest) - return evidence, nil + return claims, nil } func (s EvidenceHandler) ValidateEvidenceIntegrity( @@ -164,15 +162,3 @@ func parseKey(trustAnchor string) (*ecdsa.PublicKey, error) { return ret, nil } - -func tpmEnactTrustLookupKey(tenantID, nodeID string) string { - absPath := []string{nodeID} - - u := url.URL{ - Scheme: SchemeName, - Host: tenantID, - Path: strings.Join(absPath, "/"), - } - - return u.String() -} diff --git a/scheme/tpm-enacttrust/evidence_handler_test.go b/scheme/tpm-enacttrust/evidence_handler_test.go index 000ea145..23d9117e 100644 --- a/scheme/tpm-enacttrust/evidence_handler_test.go +++ b/scheme/tpm-enacttrust/evidence_handler_test.go @@ -61,12 +61,18 @@ func Test_ExtractVerifiedClaims_ok(t *testing.T) { 0x7a, 0xf, 0xde, 0x60, 0xc4, 0xcf, 0x25, 0xc7, } - 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"]) - assert.Equal(t, expectedPCRDigest, ev.ClaimsSet["pcr-digest"]) + ev["pcr-selection"]) + assert.Equal(t, int64(11), ev["hash-algorithm"]) + assert.Equal(t, expectedPCRDigest, ev["pcr-digest"]) + + var sh StoreHandler + + refIDs, err := sh.GetRefValueIDs("0", []string{trustAnchor}, ev) + + assert.NoError(t, err) + assert.Equal(t, 1, len(refIDs)) + assert.Equal(t, "TPM_ENACTTRUST://0/7df7714e-aa04-4638-bcbf-434b1dd720f1", refIDs[0]) } func Test_ValidateEvidenceIntegrity_ok(t *testing.T) { diff --git a/scheme/tpm-enacttrust/store_handler.go b/scheme/tpm-enacttrust/store_handler.go index 5a5cb638..09aaf5a9 100644 --- a/scheme/tpm-enacttrust/store_handler.go +++ b/scheme/tpm-enacttrust/store_handler.go @@ -6,6 +6,7 @@ package tpm_enacttrust import ( "encoding/json" "fmt" + "net/url" "strings" "github.com/veraison/services/handler" @@ -54,6 +55,19 @@ func (s StoreHandler) GetTrustAnchorIDs(token *proto.AttestationToken) ([]string return []string{tpmEnactTrustLookupKey(token.TenantId, decoded.NodeId.String())}, nil } +func (s StoreHandler) GetRefValueIDs( + tenantID string, + trustAnchors []string, + claims map[string]interface{}, +) ([]string, error) { + nodeID, ok := claims["node-id"].(string) + if !ok { + return nil, fmt.Errorf("invalid node-id value: %v", claims["node-id"]) + } + + return []string{tpmEnactTrustLookupKey(tenantID, nodeID)}, nil +} + func (s StoreHandler) SynthKeysFromRefValue( tenantID string, swComp *handler.Endorsement, @@ -90,3 +104,15 @@ func synthKeysFromAttrs(scope string, tenantID string, attr json.RawMessage) ([] return []string{tpmEnactTrustLookupKey(tenantID, nodeID)}, nil } + +func tpmEnactTrustLookupKey(tenantID, nodeID string) string { + absPath := []string{nodeID} + + u := url.URL{ + Scheme: SchemeName, + Host: tenantID, + Path: strings.Join(absPath, "/"), + } + + return u.String() +} diff --git a/vts/trustedservices/trustedservices_grpc.go b/vts/trustedservices/trustedservices_grpc.go index 6930fa3c..44964174 100644 --- a/vts/trustedservices/trustedservices_grpc.go +++ b/vts/trustedservices/trustedservices_grpc.go @@ -376,12 +376,12 @@ func (o *GRPC) GetAttestation( return o.finalize(appraisal, err) } - referenceIDs, err := stHandler.GetReferenceIDs(extracted) + referenceIDs, err := stHandler.GetRefValueIDs(token.TenantId, tas, extracted) if err != nil { return o.finalize(appraisal, err) } - appraisal.EvidenceContext.Evidence, err = structpb.NewStruct(extracted.ClaimsSet) + appraisal.EvidenceContext.Evidence, err = structpb.NewStruct(extracted) if err != nil { err = fmt.Errorf("unserializable claims in result: %w", err) return o.finalize(appraisal, err)