|
1 | 1 | package protocol |
2 | 2 |
|
3 | 3 | import ( |
| 4 | + "context" |
4 | 5 | "errors" |
5 | 6 | "reflect" |
6 | 7 | "testing" |
@@ -248,7 +249,9 @@ func TestAttestationFormatValidationHandlerCompound(t *testing.T) { |
248 | 249 | gotType, gotX5Cs, err := attestationFormatValidationHandlerCompound(att, []byte("hash"), nil) |
249 | 250 | require.NoError(t, err) |
250 | 251 |
|
251 | | - assert.Equal(t, stmtTypNone, gotType) |
| 252 | + // §8.9 returns any combination of the outputs of the successful verification procedures. The type of the |
| 253 | + // first sub-statement is conveyed so the credential isn't recorded as carrying no attestation. |
| 254 | + assert.Equal(t, "packed-type", gotType) |
252 | 255 | assert.Nil(t, gotX5Cs) |
253 | 256 |
|
254 | 257 | require.Len(t, calls, 2) |
@@ -364,10 +367,53 @@ func TestAttestationFormatValidationHandlerCompound(t *testing.T) { |
364 | 367 | gotType, gotX5Cs, err := attestationFormatValidationHandlerCompound(att, []byte("hash"), nil) |
365 | 368 | require.NoError(t, err) |
366 | 369 |
|
367 | | - assert.Equal(t, stmtTypNone, gotType) |
| 370 | + assert.Equal(t, testAttTypeSome, gotType) |
368 | 371 | assert.Nil(t, gotX5Cs) |
369 | 372 | assert.Equal(t, 2, handlerCalls) |
370 | 373 | }) |
| 374 | + |
| 375 | + // A compound attestation which conveys stmtTypNone suppresses the attestation type validation performed by |
| 376 | + // ValidateMetadata, which skips the check for that value, so the type of a sub-statement must reach it. |
| 377 | + t.Run("ShouldValidateMetadataAgainstTheConveyedAttestationType", func(t *testing.T) { |
| 378 | + withFreshAttestationRegistry(t) |
| 379 | + |
| 380 | + attestationRegistry[AttestationFormatPacked] = func(att AttestationObject, clientDataHash []byte, mds metadata.Provider) (string, []any, error) { |
| 381 | + return string(metadata.BasicFull), nil, nil |
| 382 | + } |
| 383 | + |
| 384 | + att := AttestationObject{ |
| 385 | + Format: string(AttestationFormatCompound), |
| 386 | + AuthData: AuthenticatorData{ |
| 387 | + AttData: AttestedCredentialData{AAGUID: make([]byte, 0)}, |
| 388 | + }, |
| 389 | + AttStatement: map[string]any{ |
| 390 | + stmtAttStmt: []any{ |
| 391 | + map[string]any{stmtFmt: string(AttestationFormatPacked), stmtAttStmt: map[string]any{}}, |
| 392 | + map[string]any{stmtFmt: string(AttestationFormatPacked), stmtAttStmt: map[string]any{}}, |
| 393 | + }, |
| 394 | + }, |
| 395 | + } |
| 396 | + |
| 397 | + gotType, _, err := attestationFormatValidationHandlerCompound(att, []byte("hash"), nil) |
| 398 | + require.NoError(t, err) |
| 399 | + require.NotEqual(t, stmtTypNone, gotType) |
| 400 | + |
| 401 | + ctrl := gomock.NewController(t) |
| 402 | + mds := mocks.NewMockMetadataProvider(ctrl) |
| 403 | + |
| 404 | + entry := &metadata.Entry{ |
| 405 | + MetadataStatement: metadata.Statement{ |
| 406 | + AttestationTypes: metadata.AuthenticatorAttestationTypes{metadata.AttCA}, |
| 407 | + }, |
| 408 | + } |
| 409 | + |
| 410 | + mds.EXPECT().GetEntry(gomock.Any(), gomock.Any()).Return(entry, nil) |
| 411 | + mds.EXPECT().GetValidateAttestationTypes(gomock.Any()).Return(true) |
| 412 | + |
| 413 | + protoErr := ValidateMetadata(context.Background(), mds, uuid.Nil, gotType, string(AttestationFormatCompound), nil) |
| 414 | + require.NotNil(t, protoErr) |
| 415 | + assert.Contains(t, protoErr.DevInfo, "is not known to be used by this authenticator") |
| 416 | + }) |
371 | 417 | } |
372 | 418 |
|
373 | 419 | // Supporting functions. |
|
0 commit comments