1 // Copyright 2018 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <algorithm>
6 
7 #include "base/stl_util.h"
8 #include "components/cbor/reader.h"
9 #include "components/cbor/values.h"
10 #include "components/cbor/writer.h"
11 #include "device/fido/attestation_statement_formats.h"
12 #include "device/fido/authenticator_get_assertion_response.h"
13 #include "device/fido/authenticator_make_credential_response.h"
14 #include "device/fido/device_response_converter.h"
15 #include "device/fido/ec_public_key.h"
16 #include "device/fido/fido_constants.h"
17 #include "device/fido/fido_parsing_utils.h"
18 #include "device/fido/fido_test_data.h"
19 #include "device/fido/opaque_attestation_statement.h"
20 #include "device/fido/opaque_public_key.h"
21 #include "testing/gmock/include/gmock/gmock.h"
22 #include "testing/gtest/include/gtest/gtest.h"
23 
24 namespace device {
25 
26 namespace {
27 
28 constexpr uint8_t kTestAuthenticatorGetInfoResponseWithNoVersion[] = {
29     // Success status byte
30     0x00,
31     // Map of 6 elements
32     0xA6,
33     // Key(01) - versions
34     0x01,
35     // Array(0)
36     0x80,
37     // Key(02) - extensions
38     0x02,
39     // Array(2)
40     0x82,
41     // "uvm"
42     0x63, 0x75, 0x76, 0x6D,
43     // "hmac-secret"
44     0x6B, 0x68, 0x6D, 0x61, 0x63, 0x2D, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74,
45     // Key(03) - AAGUID
46     0x03,
47     // Bytes(16)
48     0x50, 0xF8, 0xA0, 0x11, 0xF3, 0x8C, 0x0A, 0x4D, 0x15, 0x80, 0x06, 0x17,
49     0x11, 0x1F, 0x9E, 0xDC, 0x7D,
50     // Key(04) - options
51     0x04,
52     // Map(05)
53     0xA5,
54     // Key - "rk"
55     0x62, 0x72, 0x6B,
56     // true
57     0xF5,
58     // Key - "up"
59     0x62, 0x75, 0x70,
60     // true
61     0xF5,
62     // Key - "uv"
63     0x62, 0x75, 0x76,
64     // true
65     0xF5,
66     // Key - "plat"
67     0x64, 0x70, 0x6C, 0x61, 0x74,
68     // true
69     0xF5,
70     // Key - "clientPin"
71     0x69, 0x63, 0x6C, 0x69, 0x65, 0x6E, 0x74, 0x50, 0x69, 0x6E,
72     // false
73     0xF4,
74     // Key(05) - Max message size
75     0x05,
76     // 1200
77     0x19, 0x04, 0xB0,
78     // Key(06) - Pin protocols
79     0x06,
80     // Array[1]
81     0x81, 0x01,
82 };
83 
84 constexpr uint8_t kTestAuthenticatorGetInfoResponseWithDuplicateVersion[] = {
85     // Success status byte
86     0x00,
87     // Map of 6 elements
88     0xA6,
89     // Key(01) - versions
90     0x01,
91     // Array(03)
92     0x83,
93     // "U2F_V9"
94     0x66, 0x55, 0x32, 0x46, 0x5F, 0x56, 0x39,
95     // "U2F_V9"
96     0x66, 0x55, 0x32, 0x46, 0x5F, 0x56, 0x39,
97     // "U2F_V2"
98     0x66, 0x55, 0x32, 0x46, 0x5F, 0x56, 0x32,
99     // Key(02) - extensions
100     0x02,
101     // Array(2)
102     0x82,
103     // "uvm"
104     0x63, 0x75, 0x76, 0x6D,
105     // "hmac-secret"
106     0x6B, 0x68, 0x6D, 0x61, 0x63, 0x2D, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74,
107     // Key(03) - AAGUID
108     0x03,
109     // Bytes(16)
110     0x50, 0xF8, 0xA0, 0x11, 0xF3, 0x8C, 0x0A, 0x4D, 0x15, 0x80, 0x06, 0x17,
111     0x11, 0x1F, 0x9E, 0xDC, 0x7D,
112     // Key(04) - options
113     0x04,
114     // Map(05)
115     0xA5,
116     // Key - "rk"
117     0x62, 0x72, 0x6B,
118     // true
119     0xF5,
120     // Key - "up"
121     0x62, 0x75, 0x70,
122     // true
123     0xF5,
124     // Key - "uv"
125     0x62, 0x75, 0x76,
126     // true
127     0xF5,
128     // Key - "plat"
129     0x64, 0x70, 0x6C, 0x61, 0x74,
130     // true
131     0xF5,
132     // Key - "clientPin"
133     0x69, 0x63, 0x6C, 0x69, 0x65, 0x6E, 0x74, 0x50, 0x69, 0x6E,
134     // false
135     0xF4,
136     // Key(05) - Max message size
137     0x05,
138     // 1200
139     0x19, 0x04, 0xB0,
140     // Key(06) - Pin protocols
141     0x06,
142     // Array[1]
143     0x81, 0x01,
144 };
145 
146 constexpr uint8_t kTestAuthenticatorGetInfoResponseWithIncorrectAaguid[] = {
147     // Success status byte
148     0x00,
149     // Map of 6 elements
150     0xA6,
151     // Key(01) - versions
152     0x01,
153     // Array(01)
154     0x81,
155     // "U2F_V2"
156     0x66, 0x55, 0x32, 0x46, 0x5F, 0x56, 0x32,
157     // Key(02) - extensions
158     0x02,
159     // Array(2)
160     0x82,
161     // "uvm"
162     0x63, 0x75, 0x76, 0x6D,
163     // "hmac-secret"
164     0x6B, 0x68, 0x6D, 0x61, 0x63, 0x2D, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74,
165     // Key(03) - AAGUID
166     0x03,
167     // Bytes(17) - FIDO2 device AAGUID must be 16 bytes long in order to be
168     // correct.
169     0x51, 0xF8, 0xA0, 0x11, 0xF3, 0x8C, 0x0A, 0x4D, 0x15, 0x80, 0x06, 0x17,
170     0x11, 0x1F, 0x9E, 0xDC, 0x7D, 0x00,
171     // Key(04) - options
172     0x04,
173     // Map(05)
174     0xA5,
175     // Key - "rk"
176     0x62, 0x72, 0x6B,
177     // true
178     0xF5,
179     // Key - "up"
180     0x62, 0x75, 0x70,
181     // true
182     0xF5,
183     // Key - "uv"
184     0x62, 0x75, 0x76,
185     // true
186     0xF5,
187     // Key - "plat"
188     0x64, 0x70, 0x6C, 0x61, 0x74,
189     // true
190     0xF5,
191     // Key - "clientPin"
192     0x69, 0x63, 0x6C, 0x69, 0x65, 0x6E, 0x74, 0x50, 0x69, 0x6E,
193     // false
194     0xF4,
195     // Key(05) - Max message size
196     0x05,
197     // 1200
198     0x19, 0x04, 0xB0,
199     // Key(06) - Pin protocols
200     0x06,
201     // Array[1]
202     0x81, 0x01,
203 };
204 
205 // The attested credential data, excluding the public key bytes. Append
206 // with kTestECPublicKeyCOSE to get the complete attestation data.
207 constexpr uint8_t kTestAttestedCredentialDataPrefix[] = {
208     // 16-byte aaguid
209     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
210     0x00, 0x00, 0x00, 0x00,
211     // 2-byte length
212     0x00, 0x40,
213     // 64-byte key handle
214     0x3E, 0xBD, 0x89, 0xBF, 0x77, 0xEC, 0x50, 0x97, 0x55, 0xEE, 0x9C, 0x26,
215     0x35, 0xEF, 0xAA, 0xAC, 0x7B, 0x2B, 0x9C, 0x5C, 0xEF, 0x17, 0x36, 0xC3,
216     0x71, 0x7D, 0xA4, 0x85, 0x34, 0xC8, 0xC6, 0xB6, 0x54, 0xD7, 0xFF, 0x94,
217     0x5F, 0x50, 0xB5, 0xCC, 0x4E, 0x78, 0x05, 0x5B, 0xDD, 0x39, 0x6B, 0x64,
218     0xF7, 0x8D, 0xA2, 0xC5, 0xF9, 0x62, 0x00, 0xCC, 0xD4, 0x15, 0xCD, 0x08,
219     0xFE, 0x42, 0x00, 0x38,
220 };
221 
222 // The authenticator data, excluding the attested credential data bytes. Append
223 // with attested credential data to get the complete authenticator data.
224 constexpr uint8_t kTestAuthenticatorDataPrefix[] = {
225     // sha256 hash of rp id.
226     0x11, 0x94, 0x22, 0x8D, 0xA8, 0xFD, 0xBD, 0xEE, 0xFD, 0x26, 0x1B, 0xD7,
227     0xB6, 0x59, 0x5C, 0xFD, 0x70, 0xA5, 0x0D, 0x70, 0xC6, 0x40, 0x7B, 0xCF,
228     0x01, 0x3D, 0xE9, 0x6D, 0x4E, 0xFB, 0x17, 0xDE,
229     // flags (TUP and AT bits set)
230     0x41,
231     // counter
232     0x00, 0x00, 0x00, 0x00};
233 
234 // Components of the CBOR needed to form an authenticator object.
235 // Combined diagnostic notation:
236 // {"fmt": "fido-u2f", "attStmt": {"sig": h'30...}, "authData": h'D4C9D9...'}
237 constexpr uint8_t kFormatFidoU2fCBOR[] = {
238     // map(3)
239     0xA3,
240     // text(3)
241     0x63,
242     // "fmt"
243     0x66, 0x6D, 0x74,
244     // text(8)
245     0x68,
246     // "fido-u2f"
247     0x66, 0x69, 0x64, 0x6F, 0x2D, 0x75, 0x32, 0x66};
248 
249 constexpr uint8_t kAttStmtCBOR[] = {
250     // text(7)
251     0x67,
252     // "attStmt"
253     0x61, 0x74, 0x74, 0x53, 0x74, 0x6D, 0x74};
254 
255 constexpr uint8_t kAuthDataCBOR[] = {
256     // text(8)
257     0x68,
258     // "authData"
259     0x61, 0x75, 0x74, 0x68, 0x44, 0x61, 0x74, 0x61,
260     // bytes(196). i.e., the authenticator_data byte array corresponding to
261     // kTestAuthenticatorDataPrefix|, |kTestAttestedCredentialDataPrefix|,
262     // and test_data::kTestECPublicKeyCOSE.
263     0x58, 0xC4};
264 
265 constexpr std::array<uint8_t, kAaguidLength> kTestDeviceAaguid = {
266     {0xF8, 0xA0, 0x11, 0xF3, 0x8C, 0x0A, 0x4D, 0x15, 0x80, 0x06, 0x17, 0x11,
267      0x1F, 0x9E, 0xDC, 0x7D}};
268 
GetTestAttestedCredentialDataBytes()269 std::vector<uint8_t> GetTestAttestedCredentialDataBytes() {
270   // Combine kTestAttestedCredentialDataPrefix and kTestECPublicKeyCOSE.
271   auto test_attested_data =
272       fido_parsing_utils::Materialize(kTestAttestedCredentialDataPrefix);
273   fido_parsing_utils::Append(&test_attested_data,
274                              test_data::kTestECPublicKeyCOSE);
275   return test_attested_data;
276 }
277 
GetTestAuthenticatorDataBytes()278 std::vector<uint8_t> GetTestAuthenticatorDataBytes() {
279   // Build the test authenticator data.
280   auto test_authenticator_data =
281       fido_parsing_utils::Materialize(kTestAuthenticatorDataPrefix);
282   auto test_attested_data = GetTestAttestedCredentialDataBytes();
283   fido_parsing_utils::Append(&test_authenticator_data, test_attested_data);
284   return test_authenticator_data;
285 }
286 
GetTestAttestationObjectBytes()287 std::vector<uint8_t> GetTestAttestationObjectBytes() {
288   auto test_authenticator_object =
289       fido_parsing_utils::Materialize(kFormatFidoU2fCBOR);
290   fido_parsing_utils::Append(&test_authenticator_object, kAttStmtCBOR);
291   fido_parsing_utils::Append(&test_authenticator_object,
292                              test_data::kU2fAttestationStatementCBOR);
293   fido_parsing_utils::Append(&test_authenticator_object, kAuthDataCBOR);
294   auto test_authenticator_data = GetTestAuthenticatorDataBytes();
295   fido_parsing_utils::Append(&test_authenticator_object,
296                              test_authenticator_data);
297   return test_authenticator_object;
298 }
299 
GetTestSignResponse()300 std::vector<uint8_t> GetTestSignResponse() {
301   return fido_parsing_utils::Materialize(test_data::kTestU2fSignResponse);
302 }
303 
304 // Get a subset of the response for testing error handling.
GetTestCorruptedSignResponse(size_t length)305 std::vector<uint8_t> GetTestCorruptedSignResponse(size_t length) {
306   DCHECK_LE(length, base::size(test_data::kTestU2fSignResponse));
307   return fido_parsing_utils::Materialize(fido_parsing_utils::ExtractSpan(
308       test_data::kTestU2fSignResponse, 0, length));
309 }
310 
311 // Return a key handle used for GetAssertion request.
GetTestCredentialRawIdBytes()312 std::vector<uint8_t> GetTestCredentialRawIdBytes() {
313   return fido_parsing_utils::Materialize(test_data::kU2fSignKeyHandle);
314 }
315 
316 // DecodeCBOR parses a CBOR structure, ignoring the first byte of |in|, which is
317 // assumed to be a CTAP2 status byte.
DecodeCBOR(base::span<const uint8_t> in)318 base::Optional<cbor::Value> DecodeCBOR(base::span<const uint8_t> in) {
319   CHECK(!in.empty());
320   return cbor::Reader::Read(in.subspan(1));
321 }
322 
323 }  // namespace
324 
325 // Leveraging example 4 of section 6.1 of the spec https://fidoalliance.org
326 // /specs/fido-v2.0-rd-20170927/fido-client-to-authenticator-protocol-v2.0-rd-
327 // 20170927.html
TEST(CTAPResponseTest,TestReadMakeCredentialResponse)328 TEST(CTAPResponseTest, TestReadMakeCredentialResponse) {
329   auto make_credential_response = ReadCTAPMakeCredentialResponse(
330       FidoTransportProtocol::kUsbHumanInterfaceDevice,
331       DecodeCBOR(test_data::kTestMakeCredentialResponse));
332   ASSERT_TRUE(make_credential_response);
333   auto cbor_attestation_object = cbor::Reader::Read(
334       make_credential_response->GetCBOREncodedAttestationObject());
335   ASSERT_TRUE(cbor_attestation_object);
336   ASSERT_TRUE(cbor_attestation_object->is_map());
337 
338   const auto& attestation_object_map = cbor_attestation_object->GetMap();
339   auto it = attestation_object_map.find(cbor::Value(kFormatKey));
340   ASSERT_TRUE(it != attestation_object_map.end());
341   ASSERT_TRUE(it->second.is_string());
342   EXPECT_EQ(it->second.GetString(), "packed");
343 
344   it = attestation_object_map.find(cbor::Value(kAuthDataKey));
345   ASSERT_TRUE(it != attestation_object_map.end());
346   ASSERT_TRUE(it->second.is_bytestring());
347   EXPECT_THAT(
348       it->second.GetBytestring(),
349       ::testing::ElementsAreArray(test_data::kCtap2MakeCredentialAuthData));
350 
351   it = attestation_object_map.find(cbor::Value(kAttestationStatementKey));
352   ASSERT_TRUE(it != attestation_object_map.end());
353   ASSERT_TRUE(it->second.is_map());
354 
355   const auto& attestation_statement_map = it->second.GetMap();
356   auto attStmt_it = attestation_statement_map.find(cbor::Value("alg"));
357 
358   ASSERT_TRUE(attStmt_it != attestation_statement_map.end());
359   ASSERT_TRUE(attStmt_it->second.is_integer());
360   EXPECT_EQ(attStmt_it->second.GetInteger(), -7);
361 
362   attStmt_it = attestation_statement_map.find(cbor::Value("sig"));
363   ASSERT_TRUE(attStmt_it != attestation_statement_map.end());
364   ASSERT_TRUE(attStmt_it->second.is_bytestring());
365   EXPECT_THAT(
366       attStmt_it->second.GetBytestring(),
367       ::testing::ElementsAreArray(test_data::kCtap2MakeCredentialSignature));
368 
369   attStmt_it = attestation_statement_map.find(cbor::Value("x5c"));
370   ASSERT_TRUE(attStmt_it != attestation_statement_map.end());
371   const auto& certificate = attStmt_it->second;
372   ASSERT_TRUE(certificate.is_array());
373   ASSERT_EQ(certificate.GetArray().size(), 1u);
374   ASSERT_TRUE(certificate.GetArray()[0].is_bytestring());
375   EXPECT_THAT(
376       certificate.GetArray()[0].GetBytestring(),
377       ::testing::ElementsAreArray(test_data::kCtap2MakeCredentialCertificate));
378   EXPECT_THAT(
379       make_credential_response->raw_credential_id(),
380       ::testing::ElementsAreArray(test_data::kCtap2MakeCredentialCredentialId));
381 }
382 
TEST(CTAPResponseTest,TestMakeCredentialNoneAttestationResponse)383 TEST(CTAPResponseTest, TestMakeCredentialNoneAttestationResponse) {
384   auto make_credential_response = ReadCTAPMakeCredentialResponse(
385       FidoTransportProtocol::kUsbHumanInterfaceDevice,
386       DecodeCBOR(test_data::kTestMakeCredentialResponse));
387   ASSERT_TRUE(make_credential_response);
388   make_credential_response->EraseAttestationStatement(
389       AttestationObject::AAGUID::kErase);
390   EXPECT_THAT(make_credential_response->GetCBOREncodedAttestationObject(),
391               ::testing::ElementsAreArray(test_data::kNoneAttestationResponse));
392 }
393 
394 // Leveraging example 5 of section 6.1 of the CTAP spec.
395 // https://fidoalliance.org/specs/fido-v2.0-rd-20170927/fido-client-to-authenticator-protocol-v2.0-rd-20170927.html
TEST(CTAPResponseTest,TestReadGetAssertionResponse)396 TEST(CTAPResponseTest, TestReadGetAssertionResponse) {
397   auto get_assertion_response = ReadCTAPGetAssertionResponse(
398       DecodeCBOR(test_data::kDeviceGetAssertionResponse));
399   ASSERT_TRUE(get_assertion_response);
400   ASSERT_TRUE(get_assertion_response->num_credentials());
401   EXPECT_EQ(*get_assertion_response->num_credentials(), 1u);
402 
403   EXPECT_THAT(
404       get_assertion_response->auth_data().SerializeToByteArray(),
405       ::testing::ElementsAreArray(test_data::kCtap2GetAssertionAuthData));
406   EXPECT_THAT(
407       get_assertion_response->signature(),
408       ::testing::ElementsAreArray(test_data::kCtap2GetAssertionSignature));
409 }
410 
411 // Test that U2F register response is properly parsed.
TEST(CTAPResponseTest,TestParseRegisterResponseData)412 TEST(CTAPResponseTest, TestParseRegisterResponseData) {
413   auto response =
414       AuthenticatorMakeCredentialResponse::CreateFromU2fRegisterResponse(
415           FidoTransportProtocol::kUsbHumanInterfaceDevice,
416           test_data::kApplicationParameter,
417           test_data::kTestU2fRegisterResponse);
418   ASSERT_TRUE(response);
419   EXPECT_THAT(response->raw_credential_id(),
420               ::testing::ElementsAreArray(test_data::kU2fSignKeyHandle));
421   EXPECT_EQ(GetTestAttestationObjectBytes(),
422             response->GetCBOREncodedAttestationObject());
423 }
424 
425 // These test the parsing of the U2F raw bytes of the registration response.
426 // Test that an EC public key serializes to CBOR properly.
TEST(CTAPResponseTest,TestSerializedPublicKey)427 TEST(CTAPResponseTest, TestSerializedPublicKey) {
428   auto public_key = ECPublicKey::ExtractFromU2fRegistrationResponse(
429       fido_parsing_utils::kEs256, test_data::kTestU2fRegisterResponse);
430   ASSERT_TRUE(public_key);
431   EXPECT_THAT(public_key->EncodeAsCOSEKey(),
432               ::testing::ElementsAreArray(test_data::kTestECPublicKeyCOSE));
433 }
434 
435 // Test that the attestation statement cbor map is constructed properly.
TEST(CTAPResponseTest,TestParseU2fAttestationStatementCBOR)436 TEST(CTAPResponseTest, TestParseU2fAttestationStatementCBOR) {
437   auto fido_attestation_statement =
438       FidoAttestationStatement::CreateFromU2fRegisterResponse(
439           test_data::kTestU2fRegisterResponse);
440   ASSERT_TRUE(fido_attestation_statement);
441   auto cbor = cbor::Writer::Write(AsCBOR(*fido_attestation_statement));
442   ASSERT_TRUE(cbor);
443   EXPECT_THAT(*cbor, ::testing::ElementsAreArray(
444                          test_data::kU2fAttestationStatementCBOR));
445 }
446 
447 // Tests that well-formed attested credential data serializes properly.
TEST(CTAPResponseTest,TestSerializeAttestedCredentialData)448 TEST(CTAPResponseTest, TestSerializeAttestedCredentialData) {
449   auto public_key = ECPublicKey::ExtractFromU2fRegistrationResponse(
450       fido_parsing_utils::kEs256, test_data::kTestU2fRegisterResponse);
451   auto attested_data = AttestedCredentialData::CreateFromU2fRegisterResponse(
452       test_data::kTestU2fRegisterResponse, std::move(public_key));
453   ASSERT_TRUE(attested_data);
454   EXPECT_EQ(GetTestAttestedCredentialDataBytes(),
455             attested_data->SerializeAsBytes());
456 }
457 
458 // Tests that well-formed authenticator data serializes properly.
TEST(CTAPResponseTest,TestSerializeAuthenticatorData)459 TEST(CTAPResponseTest, TestSerializeAuthenticatorData) {
460   auto public_key = ECPublicKey::ExtractFromU2fRegistrationResponse(
461       fido_parsing_utils::kEs256, test_data::kTestU2fRegisterResponse);
462   auto attested_data = AttestedCredentialData::CreateFromU2fRegisterResponse(
463       test_data::kTestU2fRegisterResponse, std::move(public_key));
464 
465   constexpr uint8_t flags =
466       static_cast<uint8_t>(AuthenticatorData::Flag::kTestOfUserPresence) |
467       static_cast<uint8_t>(AuthenticatorData::Flag::kAttestation);
468 
469   AuthenticatorData authenticator_data(test_data::kApplicationParameter, flags,
470                                        std::array<uint8_t, 4>{} /* counter */,
471                                        std::move(attested_data));
472 
473   EXPECT_EQ(GetTestAuthenticatorDataBytes(),
474             authenticator_data.SerializeToByteArray());
475 }
476 
477 // Tests that a U2F attestation object serializes properly.
TEST(CTAPResponseTest,TestSerializeU2fAttestationObject)478 TEST(CTAPResponseTest, TestSerializeU2fAttestationObject) {
479   auto public_key = ECPublicKey::ExtractFromU2fRegistrationResponse(
480       fido_parsing_utils::kEs256, test_data::kTestU2fRegisterResponse);
481   auto attested_data = AttestedCredentialData::CreateFromU2fRegisterResponse(
482       test_data::kTestU2fRegisterResponse, std::move(public_key));
483 
484   constexpr uint8_t flags =
485       static_cast<uint8_t>(AuthenticatorData::Flag::kTestOfUserPresence) |
486       static_cast<uint8_t>(AuthenticatorData::Flag::kAttestation);
487   AuthenticatorData authenticator_data(test_data::kApplicationParameter, flags,
488                                        std::array<uint8_t, 4>{} /* counter */,
489                                        std::move(attested_data));
490 
491   // Construct the attestation statement.
492   auto fido_attestation_statement =
493       FidoAttestationStatement::CreateFromU2fRegisterResponse(
494           test_data::kTestU2fRegisterResponse);
495 
496   // Construct the attestation object.
497   auto attestation_object = std::make_unique<AttestationObject>(
498       std::move(authenticator_data), std::move(fido_attestation_statement));
499 
500   ASSERT_TRUE(attestation_object);
501   EXPECT_EQ(GetTestAttestationObjectBytes(),
502             cbor::Writer::Write(AsCBOR(*attestation_object))
503                 .value_or(std::vector<uint8_t>()));
504 }
505 
506 // Tests that U2F authenticator data is properly serialized.
TEST(CTAPResponseTest,TestSerializeAuthenticatorDataForSign)507 TEST(CTAPResponseTest, TestSerializeAuthenticatorDataForSign) {
508   constexpr uint8_t flags =
509       static_cast<uint8_t>(AuthenticatorData::Flag::kTestOfUserPresence);
510 
511   EXPECT_THAT(
512       AuthenticatorData(test_data::kApplicationParameter, flags,
513                         test_data::kTestSignatureCounter, base::nullopt)
514           .SerializeToByteArray(),
515       ::testing::ElementsAreArray(test_data::kTestSignAuthenticatorData));
516 }
517 
TEST(CTAPResponseTest,TestParseSignResponseData)518 TEST(CTAPResponseTest, TestParseSignResponseData) {
519   auto response = AuthenticatorGetAssertionResponse::CreateFromU2fSignResponse(
520       test_data::kApplicationParameter, GetTestSignResponse(),
521       GetTestCredentialRawIdBytes());
522   ASSERT_TRUE(response);
523   EXPECT_EQ(GetTestCredentialRawIdBytes(), response->raw_credential_id());
524   EXPECT_THAT(
525       response->auth_data().SerializeToByteArray(),
526       ::testing::ElementsAreArray(test_data::kTestSignAuthenticatorData));
527   EXPECT_THAT(response->signature(),
528               ::testing::ElementsAreArray(test_data::kU2fSignature));
529 }
530 
TEST(CTAPResponseTest,TestParseU2fSignWithNullNullKeyHandle)531 TEST(CTAPResponseTest, TestParseU2fSignWithNullNullKeyHandle) {
532   auto response = AuthenticatorGetAssertionResponse::CreateFromU2fSignResponse(
533       test_data::kApplicationParameter, GetTestSignResponse(),
534       std::vector<uint8_t>());
535   EXPECT_FALSE(response);
536 }
537 
TEST(CTAPResponseTest,TestParseU2fSignWithNullResponse)538 TEST(CTAPResponseTest, TestParseU2fSignWithNullResponse) {
539   auto response = AuthenticatorGetAssertionResponse::CreateFromU2fSignResponse(
540       test_data::kApplicationParameter, std::vector<uint8_t>(),
541       GetTestCredentialRawIdBytes());
542   EXPECT_FALSE(response);
543 }
544 
TEST(CTAPResponseTest,TestParseU2fSignWithCTAP2Flags)545 TEST(CTAPResponseTest, TestParseU2fSignWithCTAP2Flags) {
546   std::vector<uint8_t> sign_response = GetTestSignResponse();
547   // Set two flags that should only be set in CTAP2 responses and expect parsing
548   // to fail.
549   sign_response[0] |=
550       static_cast<uint8_t>(AuthenticatorData::Flag::kExtensionDataIncluded);
551   sign_response[0] |=
552       static_cast<uint8_t>(AuthenticatorData::Flag::kAttestation);
553 
554   auto response = AuthenticatorGetAssertionResponse::CreateFromU2fSignResponse(
555       test_data::kApplicationParameter, sign_response,
556       GetTestCredentialRawIdBytes());
557   EXPECT_FALSE(response);
558 }
559 
TEST(CTAPResponseTest,TestParseU2fSignWithNullCorruptedCounter)560 TEST(CTAPResponseTest, TestParseU2fSignWithNullCorruptedCounter) {
561   // A sign response of less than 5 bytes.
562   auto response = AuthenticatorGetAssertionResponse::CreateFromU2fSignResponse(
563       test_data::kApplicationParameter, GetTestCorruptedSignResponse(3),
564       GetTestCredentialRawIdBytes());
565   EXPECT_FALSE(response);
566 }
567 
TEST(CTAPResponseTest,TestParseU2fSignWithNullCorruptedSignature)568 TEST(CTAPResponseTest, TestParseU2fSignWithNullCorruptedSignature) {
569   // A sign response no more than 5 bytes.
570   auto response = AuthenticatorGetAssertionResponse::CreateFromU2fSignResponse(
571       test_data::kApplicationParameter, GetTestCorruptedSignResponse(5),
572       GetTestCredentialRawIdBytes());
573   EXPECT_FALSE(response);
574 }
575 
TEST(CTAPResponseTest,TestReadGetInfoResponse)576 TEST(CTAPResponseTest, TestReadGetInfoResponse) {
577   auto get_info_response =
578       ReadCTAPGetInfoResponse(test_data::kTestGetInfoResponsePlatformDevice);
579   ASSERT_TRUE(get_info_response);
580   ASSERT_TRUE(get_info_response->max_msg_size);
581   EXPECT_EQ(*get_info_response->max_msg_size, 1200u);
582   EXPECT_TRUE(
583       base::Contains(get_info_response->versions, ProtocolVersion::kCtap2));
584   EXPECT_TRUE(
585       base::Contains(get_info_response->versions, ProtocolVersion::kU2f));
586   EXPECT_TRUE(get_info_response->options.is_platform_device);
587   EXPECT_TRUE(get_info_response->options.supports_resident_key);
588   EXPECT_TRUE(get_info_response->options.supports_user_presence);
589   EXPECT_EQ(AuthenticatorSupportedOptions::UserVerificationAvailability::
590                 kSupportedAndConfigured,
591             get_info_response->options.user_verification_availability);
592   EXPECT_EQ(AuthenticatorSupportedOptions::ClientPinAvailability::
593                 kSupportedButPinNotSet,
594             get_info_response->options.client_pin_availability);
595 }
596 
TEST(CTAPResponseTest,TestReadGetInfoResponseWithDuplicateVersion)597 TEST(CTAPResponseTest, TestReadGetInfoResponseWithDuplicateVersion) {
598   uint8_t
599       get_info[sizeof(kTestAuthenticatorGetInfoResponseWithDuplicateVersion)];
600   memcpy(get_info, kTestAuthenticatorGetInfoResponseWithDuplicateVersion,
601          sizeof(get_info));
602   // Should fail to parse with duplicate versions.
603   EXPECT_FALSE(ReadCTAPGetInfoResponse(get_info));
604 
605   // Find the first of the duplicate versions and change it to a different
606   // value. That should be sufficient to make the data parsable.
607   static const char kU2Fv9[] = "U2F_V9";
608   uint8_t* first_version =
609       std::search(get_info, get_info + sizeof(get_info), kU2Fv9, kU2Fv9 + 6);
610   ASSERT_TRUE(first_version);
611   memcpy(first_version, "U2F_V3", 6);
612   base::Optional<AuthenticatorGetInfoResponse> response =
613       ReadCTAPGetInfoResponse(get_info);
614   ASSERT_TRUE(response);
615   EXPECT_EQ(1u, response->versions.size());
616   EXPECT_TRUE(response->versions.contains(ProtocolVersion::kU2f));
617 }
618 
TEST(CTAPResponseTest,TestReadGetInfoResponseWithIncorrectFormat)619 TEST(CTAPResponseTest, TestReadGetInfoResponseWithIncorrectFormat) {
620   EXPECT_FALSE(
621       ReadCTAPGetInfoResponse(kTestAuthenticatorGetInfoResponseWithNoVersion));
622   EXPECT_FALSE(ReadCTAPGetInfoResponse(
623       kTestAuthenticatorGetInfoResponseWithIncorrectAaguid));
624 }
625 
TEST(CTAPResponseTest,TestSerializeGetInfoResponse)626 TEST(CTAPResponseTest, TestSerializeGetInfoResponse) {
627   AuthenticatorGetInfoResponse response(
628       {ProtocolVersion::kCtap2, ProtocolVersion::kU2f}, kTestDeviceAaguid);
629   response.extensions.emplace({std::string("uvm"), std::string("hmac-secret")});
630   AuthenticatorSupportedOptions options;
631   options.supports_resident_key = true;
632   options.is_platform_device = true;
633   options.client_pin_availability = AuthenticatorSupportedOptions::
634       ClientPinAvailability::kSupportedButPinNotSet;
635   options.user_verification_availability = AuthenticatorSupportedOptions::
636       UserVerificationAvailability::kSupportedAndConfigured;
637   response.options = std::move(options);
638   response.max_msg_size = 1200;
639   response.pin_protocols.emplace({static_cast<uint8_t>(1)});
640 
641   EXPECT_THAT(AuthenticatorGetInfoResponse::EncodeToCBOR(response),
642               ::testing::ElementsAreArray(
643                   base::make_span(test_data::kTestGetInfoResponsePlatformDevice)
644                       .subspan(1)));
645 }
646 
TEST(CTAPResponseTest,TestSerializeMakeCredentialResponse)647 TEST(CTAPResponseTest, TestSerializeMakeCredentialResponse) {
648   constexpr uint8_t kCoseEncodedPublicKey[] = {
649       // map(3)
650       0xa3,
651       //   "x"
652       0x61, 0x78,
653       //   byte(32)
654       0x58, 0x20, 0xf7, 0xc4, 0xf4, 0xa6, 0xf1, 0xd7, 0x95, 0x38, 0xdf, 0xa4,
655       0xc9, 0xac, 0x50, 0x84, 0x8d, 0xf7, 0x08, 0xbc, 0x1c, 0x99, 0xf5, 0xe6,
656       0x0e, 0x51, 0xb4, 0x2a, 0x52, 0x1b, 0x35, 0xd3, 0xb6, 0x9a,
657       //   "y"
658       0x61, 0x79,
659       //   byte(32)
660       0x58, 0x20, 0xde, 0x7b, 0x7d, 0x6c, 0xa5, 0x64, 0xe7, 0x0e, 0xa3, 0x21,
661       0xa4, 0xd5, 0xd9, 0x6e, 0xa0, 0x0e, 0xf0, 0xe2, 0xdb, 0x89, 0xdd, 0x61,
662       0xd4, 0x89, 0x4c, 0x15, 0xac, 0x58, 0x5b, 0xd2, 0x36, 0x84,
663       //   "fmt"
664       0x63, 0x61, 0x6c, 0x67,
665       //   "ES256"
666       0x65, 0x45, 0x53, 0x32, 0x35, 0x36,
667   };
668 
669   const auto application_parameter =
670       base::make_span(test_data::kApplicationParameter)
671           .subspan<0, kRpIdHashLength>();
672   // Starting signature counter value set by example 4 of the CTAP spec. The
673   // signature counter can start at any value but it should never decrease.
674   // https://fidoalliance.org/specs/fido-v2.0-rd-20170927/fido-client-to-authenticator-protocol-v2.0-rd-20170927.html
675   std::array<uint8_t, kSignCounterLength> signature_counter = {
676       {0x00, 0x00, 0x00, 0x0b}};
677   auto flag =
678       base::strict_cast<uint8_t>(AuthenticatorData::Flag::kTestOfUserPresence) |
679       base::strict_cast<uint8_t>(AuthenticatorData::Flag::kAttestation);
680   AttestedCredentialData attested_credential_data(
681       kTestDeviceAaguid,
682       std::array<uint8_t, kCredentialIdLengthLength>{
683           {0x00, 0x10}} /* credential_id_length */,
684       fido_parsing_utils::Materialize(
685           test_data::kCtap2MakeCredentialCredentialId),
686       std::make_unique<OpaquePublicKey>(kCoseEncodedPublicKey));
687   AuthenticatorData authenticator_data(application_parameter, flag,
688                                        signature_counter,
689                                        std::move(attested_credential_data));
690 
691   cbor::Value::MapValue attestation_map;
692   attestation_map.emplace("alg", -7);
693   attestation_map.emplace("sig", fido_parsing_utils::Materialize(
694                                      test_data::kCtap2MakeCredentialSignature));
695   cbor::Value::ArrayValue certificate_chain;
696   certificate_chain.emplace_back(fido_parsing_utils::Materialize(
697       test_data::kCtap2MakeCredentialCertificate));
698   attestation_map.emplace("x5c", std::move(certificate_chain));
699   AuthenticatorMakeCredentialResponse response(
700       FidoTransportProtocol::kUsbHumanInterfaceDevice,
701       AttestationObject(
702           std::move(authenticator_data),
703           std::make_unique<OpaqueAttestationStatement>(
704               "packed", cbor::Value(std::move(attestation_map)))));
705   EXPECT_THAT(
706       AsCTAPStyleCBORBytes(response),
707       ::testing::ElementsAreArray(
708           base::make_span(test_data::kTestMakeCredentialResponse).subspan(1)));
709 }
710 
711 }  // namespace device
712