Skip to content

Commit

Permalink
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]>
  • Loading branch information
setrofim committed Apr 24, 2024
1 parent f4f66ad commit c296156
Show file tree
Hide file tree
Showing 23 changed files with 228 additions and 147 deletions.
18 changes: 12 additions & 6 deletions handler/evidence_rpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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(
Expand Down Expand Up @@ -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)
Expand All @@ -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
Expand Up @@ -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
Expand Down Expand Up @@ -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{}),
}
}
6 changes: 5 additions & 1 deletion handler/istorehandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
51 changes: 51 additions & 0 deletions handler/store_rpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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
}
7 changes: 3 additions & 4 deletions scheme/cca-ssd-platform/evidence_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion scheme/cca-ssd-platform/evidence_handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
10 changes: 7 additions & 3 deletions scheme/cca-ssd-platform/store_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand All @@ -60,7 +64,7 @@ func (s StoreHandler) GetRefValueIDs(claims *handler.ExtractedClaims) ([]string,

return []string{arm.RefValLookupKey(
SchemeName,
claims.TenantId,
tenantID,
arm.MustImplIDString(platformClaims),
)}, nil
}
10 changes: 5 additions & 5 deletions scheme/parsec-cca/evidence_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -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{})
Expand Down Expand Up @@ -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 {
Expand Down
10 changes: 7 additions & 3 deletions scheme/parsec-cca/store_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand All @@ -59,7 +63,7 @@ func (s StoreHandler) GetRefValueIDs(claims *handler.ExtractedClaims) ([]string,

return []string{arm.RefValLookupKey(
SchemeName,
claims.TenantId,
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
Expand Up @@ -8,9 +8,7 @@ import (
"encoding/json"
"errors"
"fmt"
"net/url"
"sort"
"strings"

"github.com/veraison/ear"
"github.com/veraison/parsec/tpm"
Expand All @@ -21,11 +19,6 @@ import (
"github.com/veraison/swid"
)

const (
ScopeTrustAnchor = "trust anchor"
ScopeRefValues = "ref values"
)

type EvidenceHandler struct{}

type SwAttr struct {
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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 {
Expand Down
Loading

0 comments on commit c296156

Please sign in to comment.