ctap_response_unittest.cc 31 KB

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