Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
handler: add GetRefValueIDs to IStoreHandler
Browse files Browse the repository at this point in the history
Move reference value ID extraction from evidence into store handler.
Prior to this, it was done inside evidence handler as part of claims
extraction.

This ensure that ID generation on both provisioning and verification
paths is handled in the same place, and is symmetrical with trust anchor
ID generation.

This also means that ExtractClaims method is now responsible _only_ for
claim extraction. ExtractedClaims structure is removed, and the method
now returns the map[string]interface{} claims set (ExtractedClaims
combined that with reference IDs).

Signed-off-by: Sergei Trofimov <[email protected]>
setrofim committed Apr 30, 2024
1 parent 2e858b7 commit ddcd318
Showing 23 changed files with 287 additions and 156 deletions.
18 changes: 12 additions & 6 deletions handler/evidence_rpc.go
Original file line number Diff line number Diff line change
@@ -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
}
20 changes: 1 addition & 19 deletions handler/ievidencehandler.go
Original file line number Diff line number Diff line change
@@ -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{}),
}
}
11 changes: 10 additions & 1 deletion handler/istorehandler.go
Original file line number Diff line number Diff line change
@@ -14,11 +14,20 @@ import (
type IStoreHandler interface {
plugin.IPluggable

// GetTrustAnchorIDs returns an array of trust anchor identifiers used
// GetTrustAnchorIDs returns a slice of trust anchor identifiers used
// to retrieve the trust anchors associated with 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)

// GetRefValueIDs returns a slice of identifiers used to retrieve
// reference values for an attestation scheme, using the claims
// extracted from attestation token and the assoced trust anchors.
GetRefValueIDs(
tenantID string,
trustAnchors []string,
claims map[string]interface{},
) ([]string, error)

// SynthKeysFromRefValue synthesizes lookup key(s) for the
// provided reference value endorsement.
SynthKeysFromRefValue(tenantID string, refVal *Endorsement) ([]string, error)
51 changes: 51 additions & 0 deletions handler/store_rpc.go
Original file line number Diff line number Diff line change
@@ -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
}
13 changes: 3 additions & 10 deletions scheme/cca-ssd-platform/evidence_handler.go
Original file line number Diff line number Diff line change
@@ -36,15 +36,14 @@ 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

if err := ccaToken.FromCBOR(token.Data); err != nil {
return nil, handler.BadEvidence(err)
}

var extracted handler.ExtractedClaims

platformClaimsSet, err := common.ClaimsToMap(ccaToken.PlatformClaims)
if err != nil {
@@ -58,18 +57,12 @@ func (s EvidenceHandler) ExtractClaims(
"could not convert realm claims: %w", err))
}

extracted.ClaimsSet = map[string]interface{}{
claims := map[string]interface{}{
"platform": platformClaimsSet,
"realm": realmClaimsSet,
}

extracted.ReferenceIDs = []string{arm.RefValLookupKey(
SchemeName,
token.TenantId,
arm.MustImplIDString(ccaToken.PlatformClaims),
)}
log.Debugf("extracted Reference ID Key = %s", extracted.ReferenceIDs)
return &extracted, nil
return claims, nil
}

// ValidateEvidenceIntegrity, decodes CCA collection and then invokes Verify API of ccatoken library
2 changes: 1 addition & 1 deletion scheme/cca-ssd-platform/evidence_handler_test.go
Original file line number Diff line number Diff line change
@@ -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",
25 changes: 25 additions & 0 deletions scheme/cca-ssd-platform/store_handler.go
Original file line number Diff line number Diff line change
@@ -4,8 +4,11 @@
package cca_ssd_platform

import (
"fmt"

"github.com/veraison/services/handler"
"github.com/veraison/services/proto"
"github.com/veraison/services/scheme/common"
"github.com/veraison/services/scheme/common/arm"
)

@@ -43,3 +46,25 @@ func (s StoreHandler) GetTrustAnchorIDs(token *proto.AttestationToken) ([]string
}
return []string{ta}, nil
}

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)
}

platformClaims, err := common.MapToClaims(platformClaimsMap)
if err != nil {
return nil, err
}

return []string{arm.RefValLookupKey(
SchemeName,
tenantID,
arm.MustImplIDString(platformClaims),
)}, nil
}
16 changes: 5 additions & 11 deletions scheme/parsec-cca/evidence_handler.go
Original file line number Diff line number Diff line change
@@ -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,15 +72,7 @@ func (s EvidenceHandler) ExtractClaims(token *proto.AttestationToken, trustAncho
}
claimsSet["cca.realm"] = rmap

extracted.ClaimsSet = claimsSet

extracted.ReferenceIDs = []string{arm.RefValLookupKey(
SchemeName,
token.TenantId,
arm.MustImplIDString(evidence.Pat.PlatformClaims),
)}
log.Debugf("extracted Reference ID Key = %s", extracted.ReferenceIDs)
return &extracted, nil
return claimsSet, nil
}

func (s EvidenceHandler) ValidateEvidenceIntegrity(token *proto.AttestationToken, trustAnchors []string, endorsements []string) error {
25 changes: 25 additions & 0 deletions scheme/parsec-cca/store_handler.go
Original file line number Diff line number Diff line change
@@ -3,8 +3,11 @@
package parsec_cca

import (
"fmt"

"github.com/veraison/services/handler"
"github.com/veraison/services/proto"
"github.com/veraison/services/scheme/common"
"github.com/veraison/services/scheme/common/arm"
)

@@ -42,3 +45,25 @@ func (s StoreHandler) GetTrustAnchorIDs(token *proto.AttestationToken) ([]string
}
return []string{ta}, nil
}

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)
}

platformClaims, err := common.MapToClaims(platformClaimsMap)
if err != nil {
return nil, err
}

return []string{arm.RefValLookupKey(
SchemeName,
tenantID,
arm.MustImplIDString(platformClaims),
)}, nil
}
9 changes: 9 additions & 0 deletions scheme/parsec-tpm/common.go
Original file line number Diff line number Diff line change
@@ -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"
)

48 changes: 7 additions & 41 deletions scheme/parsec-tpm/evidence_handler.go
Original file line number Diff line number Diff line change
@@ -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 {
21 changes: 9 additions & 12 deletions scheme/parsec-tpm/evidence_handler_test.go
Original file line number Diff line number Diff line change
@@ -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)

39 changes: 39 additions & 0 deletions scheme/parsec-tpm/store_handler.go
Original file line number Diff line number Diff line change
@@ -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()
}

15 changes: 3 additions & 12 deletions scheme/psa-iot/evidence_handler.go
Original file line number Diff line number Diff line change
@@ -34,28 +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

extracted.ReferenceIDs = []string{arm.RefValLookupKey(
SchemeName,
token.TenantId,
arm.MustImplIDString(psaToken.Claims),
)}
log.Printf("\n Extracted SW ID Key = %s", extracted.ReferenceIDs)
return &extracted, nil

return claimsSet, nil
}

func (s EvidenceHandler) ValidateEvidenceIntegrity(
6 changes: 3 additions & 3 deletions scheme/psa-iot/evidence_handler_test.go
Original file line number Diff line number Diff line change
@@ -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))
}
18 changes: 18 additions & 0 deletions scheme/psa-iot/store_handler.go
Original file line number Diff line number Diff line change
@@ -6,6 +6,7 @@ package psa_iot
import (
"github.com/veraison/services/handler"
"github.com/veraison/services/proto"
"github.com/veraison/services/scheme/common"
"github.com/veraison/services/scheme/common/arm"
)

@@ -42,3 +43,20 @@ func (s StoreHandler) GetTrustAnchorIDs(token *proto.AttestationToken) ([]string

return []string{taID}, nil
}

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,
tenantID,
arm.MustImplIDString(psaClaims),
)}, nil
}
9 changes: 2 additions & 7 deletions scheme/riot/evidence_handler.go
Original file line number Diff line number Diff line change
@@ -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(
6 changes: 3 additions & 3 deletions scheme/riot/evidence_handler_test.go
Original file line number Diff line number Diff line change
@@ -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"])
}
8 changes: 8 additions & 0 deletions scheme/riot/store_handler.go
Original file line number Diff line number Diff line change
@@ -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")
}
30 changes: 8 additions & 22 deletions scheme/tpm-enacttrust/evidence_handler.go
Original file line number Diff line number Diff line change
@@ -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()
}
16 changes: 11 additions & 5 deletions scheme/tpm-enacttrust/evidence_handler_test.go
Original file line number Diff line number Diff line change
@@ -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) {
26 changes: 26 additions & 0 deletions scheme/tpm-enacttrust/store_handler.go
Original file line number Diff line number Diff line change
@@ -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()
}
11 changes: 8 additions & 3 deletions vts/trustedservices/trustedservices_grpc.go
Original file line number Diff line number Diff line change
@@ -368,21 +368,26 @@ func (o *GRPC) GetAttestation(
return o.finalize(appraisal, err)
}

extracted, err := handler.ExtractClaims(token, tas)
claims, err := handler.ExtractClaims(token, tas)
if err != nil {
if errors.Is(err, handlermod.BadEvidenceError{}) {
appraisal.AddPolicyClaim("problem", err.Error())
}
return o.finalize(appraisal, err)
}

appraisal.EvidenceContext.Evidence, err = structpb.NewStruct(extracted.ClaimsSet)
referenceIDs, err := stHandler.GetRefValueIDs(token.TenantId, tas, claims)
if err != nil {
return o.finalize(appraisal, err)
}

appraisal.EvidenceContext.Evidence, err = structpb.NewStruct(claims)
if err != nil {
err = fmt.Errorf("unserializable claims in result: %w", err)
return o.finalize(appraisal, err)
}

appraisal.EvidenceContext.ReferenceIds = extracted.ReferenceIDs
appraisal.EvidenceContext.ReferenceIds = referenceIDs

o.logger.Debugw("constructed evidence context",
"software-id", appraisal.EvidenceContext.ReferenceIds,

0 comments on commit ddcd318

Please sign in to comment.