Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file added pr_comment.md
Empty file.
2 changes: 1 addition & 1 deletion scheme/tpm-enacttrust/store_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func (s StoreHandler) GetTrustAnchorIDs(token *proto.AttestationToken) ([]string
strings.Join(EvidenceMediaTypes, ", "),
token.MediaType,
)
return []string{""}, err
return nil, err
}

var decoded Token
Expand Down
29 changes: 28 additions & 1 deletion verification/api/challengeresponsesession.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
package api

import (
"encoding/base64"
"encoding/json"
"fmt"
"time"
Expand Down Expand Up @@ -64,6 +65,32 @@ func (o *Status) UnmarshalJSON(b []byte) error {
return o.FromString(s)
}

// URLSafeNonce is a wrapper around []byte that marshals/unmarshals using URL-safe base64
type URLSafeNonce []byte

func (n URLSafeNonce) MarshalJSON() ([]byte, error) {
if n == nil {
return []byte("null"), nil
}
encoded := base64.URLEncoding.EncodeToString(n)
return json.Marshal(encoded)
}

func (n *URLSafeNonce) UnmarshalJSON(data []byte) error {
var s string
if err := json.Unmarshal(data, &s); err != nil {
return err
}

decoded, err := base64.URLEncoding.DecodeString(s)
if err != nil {
return err
}

*n = URLSafeNonce(decoded)
return nil
}

type EvidenceBlob struct {
Type string `json:"type"`
Value []byte `json:"value"`
Expand All @@ -72,7 +99,7 @@ type EvidenceBlob struct {
type ChallengeResponseSession struct {
id string
Status Status `json:"status"`
Nonce []byte `json:"nonce"`
Nonce URLSafeNonce `json:"nonce"`
Expiry time.Time `json:"expiry"`
Accept []string `json:"accept"`
Evidence *EvidenceBlob `json:"evidence,omitempty"`
Expand Down
4 changes: 2 additions & 2 deletions verification/api/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ func newSession(nonce []byte, supportedMediaTypes []string, ttl time.Duration) (
session := &ChallengeResponseSession{
id: id.String(),
Status: StatusWaiting, // start in waiting status
Nonce: nonce,
Nonce: URLSafeNonce(nonce),
Expiry: time.Now().Add(ttl), // RFC3339 format, with sub-second precision added if present
Accept: supportedMediaTypes,
}
Expand Down Expand Up @@ -394,7 +394,7 @@ func (o *Handler) SubmitEvidence(c *gin.Context) {
// reported if something in the verifier or the connection goes wrong.
// Any problems with the evidence are expected to be reported via the
// attestation result.
attestationResult, err := o.Verifier.ProcessEvidence(tenantID, session.Nonce,
attestationResult, err := o.Verifier.ProcessEvidence(tenantID, []byte(session.Nonce),
evidence, mediaType)
if err != nil {
o.logger.Error(err)
Expand Down
38 changes: 34 additions & 4 deletions verification/api/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ var (
testJSONBody = `{ "k": "v" }`
testSession = `{
"status": "waiting",
"nonce": "mVubqtg3Wa5GSrx3L/2B99cQU2bMQFVYUI9aTmDYi64=",
"nonce": "mVubqtg3Wa5GSrx3L_2B99cQU2bMQFVYUI9aTmDYi64=",
"expiry": "2022-07-13T13:50:24.520525+01:00",
"accept": [
"application/eat_cwt;profile=http://arm.com/psa/2.0.0",
Expand All @@ -61,7 +61,7 @@ var (
}`
testProcessingSession = `{
"status": "processing",
"nonce": "mVubqtg3Wa5GSrx3L/2B99cQU2bMQFVYUI9aTmDYi64=",
"nonce": "mVubqtg3Wa5GSrx3L_2B99cQU2bMQFVYUI9aTmDYi64=",
"expiry": "2022-07-13T13:50:24.520525+01:00",
"accept": [
"application/eat_cwt;profile=http://arm.com/psa/2.0.0",
Expand All @@ -75,7 +75,7 @@ var (
}`
testCompleteSession = `{
"status": "complete",
"nonce": "mVubqtg3Wa5GSrx3L/2B99cQU2bMQFVYUI9aTmDYi64=",
"nonce": "mVubqtg3Wa5GSrx3L_2B99cQU2bMQFVYUI9aTmDYi64=",
"expiry": "2022-07-13T13:50:24.520525+01:00",
"accept": [
"application/eat_cwt;profile=http://arm.com/psa/2.0.0",
Expand Down Expand Up @@ -289,12 +289,42 @@ func TestHandler_NewChallengeResponse_NonceParameter(t *testing.T) {
assert.Equal(t, expectedCode, w.Code)
assert.Equal(t, expectedType, w.Result().Header.Get("Content-Type"))
assert.Regexp(t, expectedLocationRE, w.Result().Header.Get("Location"))
assert.Equal(t, expectedNonce, body.Nonce)
assert.Equal(t, expectedNonce, []byte(body.Nonce))
assert.Nil(t, body.Evidence)
assert.Nil(t, body.Result)
assert.Equal(t, expectedSessionStatus, body.Status)
}

func TestURLSafeNonce_EncodingFormat(t *testing.T) {
// Test that nonces with characters that would be URL-unsafe in standard base64
// are properly encoded as URL-safe base64
testNonce := []byte{0x99, 0x5b, 0x9b, 0xaa, 0xd8, 0x37, 0x59, 0xae,
0x46, 0x4a, 0xbc, 0x77, 0x2f, 0xfd, 0x81, 0xf7,
0xd7, 0x10, 0x53, 0x66, 0xcc, 0x40, 0x55, 0x58,
0x50, 0x8f, 0x5a, 0x4e, 0x60, 0xd8, 0x8b, 0xae}

urlSafeNonce := URLSafeNonce(testNonce)
jsonBytes, err := json.Marshal(urlSafeNonce)
require.NoError(t, err)

jsonStr := string(jsonBytes)
t.Logf("Encoded nonce: %s", jsonStr)

// Should not contain URL-unsafe characters '+' or '/'
assert.NotContains(t, jsonStr, "+", "Nonce should not contain '+' character")
assert.NotContains(t, jsonStr, "/", "Nonce should not contain '/' character")

// Should contain URL-safe alternatives '_' and '-' instead
// Note: This specific test nonce should contain '_' character
assert.Contains(t, jsonStr, "_", "URL-safe nonce should contain '_' character")

// Test round-trip: unmarshal and compare
var unmarshaled URLSafeNonce
err = json.Unmarshal(jsonBytes, &unmarshaled)
require.NoError(t, err)
assert.Equal(t, testNonce, []byte(unmarshaled), "Round-trip encoding should preserve nonce data")
}

func TestHandler_NewChallengeResponse_NonceSizeParameter(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
Expand Down
1 change: 0 additions & 1 deletion vts/trustedservices/trustedservices_grpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -442,7 +442,6 @@ func (o *GRPC) GetAttestation(

var multEndorsements []string
for _, refvalID := range appraisal.EvidenceContext.ReferenceIds {

endorsements, err := o.EnStore.Get(refvalID)
if err != nil && !errors.Is(err, kvstore.ErrKeyNotFound) {
return o.finalize(appraisal, err)
Expand Down