aes_kw_unittest.cc 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529
  1. // Copyright 2014 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 <stddef.h>
  5. #include <stdint.h>
  6. #include <memory>
  7. #include "base/values.h"
  8. #include "components/webcrypto/algorithm_dispatch.h"
  9. #include "components/webcrypto/algorithms/test_helpers.h"
  10. #include "components/webcrypto/status.h"
  11. #include "third_party/blink/public/platform/web_crypto_algorithm_params.h"
  12. #include "third_party/blink/public/platform/web_crypto_key_algorithm.h"
  13. namespace webcrypto {
  14. namespace {
  15. blink::WebCryptoAlgorithm CreateAesKwKeyGenAlgorithm(uint16_t key_length_bits) {
  16. return CreateAesKeyGenAlgorithm(blink::kWebCryptoAlgorithmIdAesKw,
  17. key_length_bits);
  18. }
  19. class WebCryptoAesKwTest : public WebCryptoTestBase {};
  20. TEST_F(WebCryptoAesKwTest, GenerateKeyBadLength) {
  21. blink::WebCryptoKey key;
  22. for (auto len : {0, 127, 257}) {
  23. SCOPED_TRACE(len);
  24. EXPECT_EQ(Status::ErrorGenerateAesKeyLength(),
  25. GenerateSecretKey(CreateAesKwKeyGenAlgorithm(len), true,
  26. blink::kWebCryptoKeyUsageWrapKey, &key));
  27. }
  28. }
  29. TEST_F(WebCryptoAesKwTest, GenerateKeyEmptyUsage) {
  30. blink::WebCryptoKey key;
  31. EXPECT_EQ(Status::ErrorCreateKeyEmptyUsages(),
  32. GenerateSecretKey(CreateAesKwKeyGenAlgorithm(256), true, 0, &key));
  33. }
  34. TEST_F(WebCryptoAesKwTest, ImportKeyEmptyUsage) {
  35. blink::WebCryptoKey key;
  36. EXPECT_EQ(Status::ErrorCreateKeyEmptyUsages(),
  37. ImportKey(blink::kWebCryptoKeyFormatRaw, std::vector<uint8_t>(16),
  38. CreateAlgorithm(blink::kWebCryptoAlgorithmIdAesKw), true,
  39. 0, &key));
  40. }
  41. TEST_F(WebCryptoAesKwTest, ImportKeyJwkKeyOpsWrapUnwrap) {
  42. blink::WebCryptoKey key;
  43. base::DictionaryValue dict;
  44. dict.SetString("kty", "oct");
  45. dict.SetString("k", "GADWrMRHwQfoNaXU5fZvTg");
  46. base::Value* key_ops =
  47. dict.SetKey("key_ops", base::Value(base::Value::Type::LIST));
  48. key_ops->Append("wrapKey");
  49. EXPECT_EQ(Status::Success(),
  50. ImportKeyJwkFromDict(
  51. dict, CreateAlgorithm(blink::kWebCryptoAlgorithmIdAesKw), false,
  52. blink::kWebCryptoKeyUsageWrapKey, &key));
  53. EXPECT_EQ(blink::kWebCryptoKeyUsageWrapKey, key.Usages());
  54. key_ops->Append("unwrapKey");
  55. EXPECT_EQ(Status::Success(),
  56. ImportKeyJwkFromDict(
  57. dict, CreateAlgorithm(blink::kWebCryptoAlgorithmIdAesKw), false,
  58. blink::kWebCryptoKeyUsageUnwrapKey, &key));
  59. EXPECT_EQ(blink::kWebCryptoKeyUsageUnwrapKey, key.Usages());
  60. }
  61. TEST_F(WebCryptoAesKwTest, ImportExportJwk) {
  62. const blink::WebCryptoAlgorithm algorithm =
  63. CreateAlgorithm(blink::kWebCryptoAlgorithmIdAesKw);
  64. // AES-KW 128
  65. ImportExportJwkSymmetricKey(
  66. 128, algorithm,
  67. blink::kWebCryptoKeyUsageWrapKey | blink::kWebCryptoKeyUsageUnwrapKey,
  68. "A128KW");
  69. // AES-KW 256
  70. ImportExportJwkSymmetricKey(
  71. 256, algorithm,
  72. blink::kWebCryptoKeyUsageWrapKey | blink::kWebCryptoKeyUsageUnwrapKey,
  73. "A256KW");
  74. }
  75. TEST_F(WebCryptoAesKwTest, AesKwKeyImport) {
  76. blink::WebCryptoKey key;
  77. blink::WebCryptoAlgorithm algorithm =
  78. CreateAlgorithm(blink::kWebCryptoAlgorithmIdAesKw);
  79. // Import a 128-bit Key Encryption Key (KEK)
  80. std::string key_raw_hex_in = "025a8cf3f08b4f6c5f33bbc76a471939";
  81. ASSERT_EQ(
  82. Status::Success(),
  83. ImportKey(blink::kWebCryptoKeyFormatRaw, HexStringToBytes(key_raw_hex_in),
  84. algorithm, true, blink::kWebCryptoKeyUsageWrapKey, &key));
  85. std::vector<uint8_t> key_raw_out;
  86. EXPECT_EQ(Status::Success(),
  87. ExportKey(blink::kWebCryptoKeyFormatRaw, key, &key_raw_out));
  88. EXPECT_BYTES_EQ_HEX(key_raw_hex_in, key_raw_out);
  89. // Import a 192-bit KEK
  90. key_raw_hex_in = "c0192c6466b2370decbb62b2cfef4384544ffeb4d2fbc103";
  91. ASSERT_EQ(
  92. Status::ErrorAes192BitUnsupported(),
  93. ImportKey(blink::kWebCryptoKeyFormatRaw, HexStringToBytes(key_raw_hex_in),
  94. algorithm, true, blink::kWebCryptoKeyUsageWrapKey, &key));
  95. // Import a 256-bit Key Encryption Key (KEK)
  96. key_raw_hex_in =
  97. "e11fe66380d90fa9ebefb74e0478e78f95664d0c67ca20ce4a0b5842863ac46f";
  98. ASSERT_EQ(
  99. Status::Success(),
  100. ImportKey(blink::kWebCryptoKeyFormatRaw, HexStringToBytes(key_raw_hex_in),
  101. algorithm, true, blink::kWebCryptoKeyUsageWrapKey, &key));
  102. EXPECT_EQ(Status::Success(),
  103. ExportKey(blink::kWebCryptoKeyFormatRaw, key, &key_raw_out));
  104. EXPECT_BYTES_EQ_HEX(key_raw_hex_in, key_raw_out);
  105. // Fail import of 0 length key
  106. EXPECT_EQ(Status::ErrorImportAesKeyLength(),
  107. ImportKey(blink::kWebCryptoKeyFormatRaw, HexStringToBytes(""),
  108. algorithm, true, blink::kWebCryptoKeyUsageWrapKey, &key));
  109. // Fail import of 120-bit KEK
  110. key_raw_hex_in = "3e4566a2bdaa10cb68134fa66c15dd";
  111. EXPECT_EQ(
  112. Status::ErrorImportAesKeyLength(),
  113. ImportKey(blink::kWebCryptoKeyFormatRaw, HexStringToBytes(key_raw_hex_in),
  114. algorithm, true, blink::kWebCryptoKeyUsageWrapKey, &key));
  115. // Fail import of 200-bit KEK
  116. key_raw_hex_in = "0a1d88608a5ad9fec64f1ada269ebab4baa2feeb8d95638c0e";
  117. EXPECT_EQ(
  118. Status::ErrorImportAesKeyLength(),
  119. ImportKey(blink::kWebCryptoKeyFormatRaw, HexStringToBytes(key_raw_hex_in),
  120. algorithm, true, blink::kWebCryptoKeyUsageWrapKey, &key));
  121. }
  122. TEST_F(WebCryptoAesKwTest, UnwrapFailures) {
  123. auto tests = ReadJsonTestFileAsList("aes_kw.json");
  124. const base::Value& test_value = tests[0];
  125. ASSERT_TRUE(test_value.is_dict());
  126. const base::DictionaryValue* test =
  127. &base::Value::AsDictionaryValue(test_value);
  128. const std::vector<uint8_t> test_kek = GetBytesFromHexString(test, "kek");
  129. const std::vector<uint8_t> test_ciphertext =
  130. GetBytesFromHexString(test, "ciphertext");
  131. blink::WebCryptoKey unwrapped_key;
  132. // Using a wrapping algorithm that does not match the wrapping key algorithm
  133. // should fail.
  134. blink::WebCryptoKey wrapping_key = ImportSecretKeyFromRaw(
  135. test_kek, CreateAlgorithm(blink::kWebCryptoAlgorithmIdAesKw),
  136. blink::kWebCryptoKeyUsageUnwrapKey);
  137. EXPECT_EQ(
  138. Status::ErrorUnexpected(),
  139. UnwrapKey(blink::kWebCryptoKeyFormatRaw, test_ciphertext, wrapping_key,
  140. CreateAlgorithm(blink::kWebCryptoAlgorithmIdAesCbc),
  141. CreateAlgorithm(blink::kWebCryptoAlgorithmIdAesCbc), true,
  142. blink::kWebCryptoKeyUsageEncrypt, &unwrapped_key));
  143. }
  144. TEST_F(WebCryptoAesKwTest, AesKwRawSymkeyWrapUnwrapKnownAnswer) {
  145. base::Value::List tests = ReadJsonTestFileAsList("aes_kw.json");
  146. for (const auto& test_value : tests) {
  147. SCOPED_TRACE(&test_value - &tests[0]);
  148. ASSERT_TRUE(test_value.is_dict());
  149. const base::DictionaryValue* test =
  150. &base::Value::AsDictionaryValue(test_value);
  151. const std::vector<uint8_t> test_kek = GetBytesFromHexString(test, "kek");
  152. const std::vector<uint8_t> test_key = GetBytesFromHexString(test, "key");
  153. const std::vector<uint8_t> test_ciphertext =
  154. GetBytesFromHexString(test, "ciphertext");
  155. const blink::WebCryptoAlgorithm wrapping_algorithm =
  156. CreateAlgorithm(blink::kWebCryptoAlgorithmIdAesKw);
  157. // Import the wrapping key.
  158. blink::WebCryptoKey wrapping_key = ImportSecretKeyFromRaw(
  159. test_kek, wrapping_algorithm,
  160. blink::kWebCryptoKeyUsageWrapKey | blink::kWebCryptoKeyUsageUnwrapKey);
  161. // Import the key to be wrapped.
  162. blink::WebCryptoKey key = ImportSecretKeyFromRaw(
  163. test_key,
  164. CreateHmacImportAlgorithmNoLength(blink::kWebCryptoAlgorithmIdSha1),
  165. blink::kWebCryptoKeyUsageSign);
  166. // Wrap the key and verify the ciphertext result against the known answer.
  167. std::vector<uint8_t> wrapped_key;
  168. ASSERT_EQ(Status::Success(),
  169. WrapKey(blink::kWebCryptoKeyFormatRaw, key, wrapping_key,
  170. wrapping_algorithm, &wrapped_key));
  171. EXPECT_BYTES_EQ(test_ciphertext, wrapped_key);
  172. // Unwrap the known ciphertext to get a new test_key.
  173. blink::WebCryptoKey unwrapped_key;
  174. ASSERT_EQ(Status::Success(),
  175. UnwrapKey(blink::kWebCryptoKeyFormatRaw, test_ciphertext,
  176. wrapping_key, wrapping_algorithm,
  177. CreateHmacImportAlgorithmNoLength(
  178. blink::kWebCryptoAlgorithmIdSha1),
  179. true, blink::kWebCryptoKeyUsageSign, &unwrapped_key));
  180. EXPECT_FALSE(key.IsNull());
  181. EXPECT_TRUE(key.Handle());
  182. EXPECT_EQ(blink::kWebCryptoKeyTypeSecret, key.GetType());
  183. EXPECT_EQ(blink::kWebCryptoAlgorithmIdHmac, key.Algorithm().Id());
  184. EXPECT_EQ(true, key.Extractable());
  185. EXPECT_EQ(blink::kWebCryptoKeyUsageSign, key.Usages());
  186. // Export the new key and compare its raw bytes with the original known key.
  187. std::vector<uint8_t> raw_key;
  188. EXPECT_EQ(Status::Success(), ExportKey(blink::kWebCryptoKeyFormatRaw,
  189. unwrapped_key, &raw_key));
  190. EXPECT_BYTES_EQ(test_key, raw_key);
  191. }
  192. }
  193. // Unwrap a HMAC key using AES-KW, and then try doing a sign/verify with the
  194. // unwrapped key
  195. TEST_F(WebCryptoAesKwTest, AesKwRawSymkeyUnwrapSignVerifyHmac) {
  196. auto tests = ReadJsonTestFileAsList("aes_kw.json");
  197. const base::Value& test_value = tests[0];
  198. ASSERT_TRUE(test_value.is_dict());
  199. const base::DictionaryValue* test =
  200. &base::Value::AsDictionaryValue(test_value);
  201. const std::vector<uint8_t> test_kek = GetBytesFromHexString(test, "kek");
  202. const std::vector<uint8_t> test_ciphertext =
  203. GetBytesFromHexString(test, "ciphertext");
  204. const blink::WebCryptoAlgorithm wrapping_algorithm =
  205. CreateAlgorithm(blink::kWebCryptoAlgorithmIdAesKw);
  206. // Import the wrapping key.
  207. blink::WebCryptoKey wrapping_key = ImportSecretKeyFromRaw(
  208. test_kek, wrapping_algorithm, blink::kWebCryptoKeyUsageUnwrapKey);
  209. // Unwrap the known ciphertext.
  210. blink::WebCryptoKey key;
  211. ASSERT_EQ(
  212. Status::Success(),
  213. UnwrapKey(
  214. blink::kWebCryptoKeyFormatRaw, test_ciphertext, wrapping_key,
  215. wrapping_algorithm,
  216. CreateHmacImportAlgorithmNoLength(blink::kWebCryptoAlgorithmIdSha1),
  217. false,
  218. blink::kWebCryptoKeyUsageSign | blink::kWebCryptoKeyUsageVerify,
  219. &key));
  220. EXPECT_EQ(blink::kWebCryptoKeyTypeSecret, key.GetType());
  221. EXPECT_EQ(blink::kWebCryptoAlgorithmIdHmac, key.Algorithm().Id());
  222. EXPECT_FALSE(key.Extractable());
  223. EXPECT_EQ(blink::kWebCryptoKeyUsageSign | blink::kWebCryptoKeyUsageVerify,
  224. key.Usages());
  225. // Sign an empty message and ensure it is verified.
  226. std::vector<uint8_t> test_message;
  227. std::vector<uint8_t> signature;
  228. ASSERT_EQ(Status::Success(),
  229. Sign(CreateAlgorithm(blink::kWebCryptoAlgorithmIdHmac), key,
  230. test_message, &signature));
  231. EXPECT_GT(signature.size(), 0u);
  232. bool verify_result;
  233. ASSERT_EQ(Status::Success(),
  234. Verify(CreateAlgorithm(blink::kWebCryptoAlgorithmIdHmac), key,
  235. signature, test_message, &verify_result));
  236. }
  237. TEST_F(WebCryptoAesKwTest, AesKwRawSymkeyWrapUnwrapErrors) {
  238. // Use 256 bits of data with a 256-bit KEK
  239. auto tests = ReadJsonTestFileAsList("aes_kw.json");
  240. const base::Value& test_value = tests[3];
  241. ASSERT_TRUE(test_value.is_dict());
  242. const base::DictionaryValue* test =
  243. &base::Value::AsDictionaryValue(test_value);
  244. const std::vector<uint8_t> test_kek = GetBytesFromHexString(test, "kek");
  245. const std::vector<uint8_t> test_key = GetBytesFromHexString(test, "key");
  246. const std::vector<uint8_t> test_ciphertext =
  247. GetBytesFromHexString(test, "ciphertext");
  248. const blink::WebCryptoAlgorithm wrapping_algorithm =
  249. CreateAlgorithm(blink::kWebCryptoAlgorithmIdAesKw);
  250. const blink::WebCryptoAlgorithm key_algorithm =
  251. CreateAlgorithm(blink::kWebCryptoAlgorithmIdAesCbc);
  252. // Import the wrapping key.
  253. blink::WebCryptoKey wrapping_key = ImportSecretKeyFromRaw(
  254. test_kek, wrapping_algorithm,
  255. blink::kWebCryptoKeyUsageWrapKey | blink::kWebCryptoKeyUsageUnwrapKey);
  256. // Import the key to be wrapped.
  257. blink::WebCryptoKey key = ImportSecretKeyFromRaw(
  258. test_key, CreateAlgorithm(blink::kWebCryptoAlgorithmIdAesCbc),
  259. blink::kWebCryptoKeyUsageEncrypt);
  260. // Unwrap with wrapped data too small must fail.
  261. const std::vector<uint8_t> small_data(test_ciphertext.begin(),
  262. test_ciphertext.begin() + 23);
  263. blink::WebCryptoKey unwrapped_key;
  264. EXPECT_EQ(Status::ErrorDataTooSmall(),
  265. UnwrapKey(blink::kWebCryptoKeyFormatRaw, small_data, wrapping_key,
  266. wrapping_algorithm, key_algorithm, true,
  267. blink::kWebCryptoKeyUsageEncrypt, &unwrapped_key));
  268. // Unwrap with wrapped data size not a multiple of 8 bytes must fail.
  269. const std::vector<uint8_t> unaligned_data(test_ciphertext.begin(),
  270. test_ciphertext.end() - 2);
  271. EXPECT_EQ(Status::ErrorInvalidAesKwDataLength(),
  272. UnwrapKey(blink::kWebCryptoKeyFormatRaw, unaligned_data,
  273. wrapping_key, wrapping_algorithm, key_algorithm, true,
  274. blink::kWebCryptoKeyUsageEncrypt, &unwrapped_key));
  275. }
  276. TEST_F(WebCryptoAesKwTest, AesKwRawSymkeyUnwrapCorruptData) {
  277. // Use 256 bits of data with a 256-bit KEK
  278. auto tests = ReadJsonTestFileAsList("aes_kw.json");
  279. const base::Value& test_value = tests[3];
  280. ASSERT_TRUE(test_value.is_dict());
  281. const base::DictionaryValue* test =
  282. &base::Value::AsDictionaryValue(test_value);
  283. const std::vector<uint8_t> test_kek = GetBytesFromHexString(test, "kek");
  284. const std::vector<uint8_t> test_key = GetBytesFromHexString(test, "key");
  285. const std::vector<uint8_t> test_ciphertext =
  286. GetBytesFromHexString(test, "ciphertext");
  287. const blink::WebCryptoAlgorithm wrapping_algorithm =
  288. CreateAlgorithm(blink::kWebCryptoAlgorithmIdAesKw);
  289. // Import the wrapping key.
  290. blink::WebCryptoKey wrapping_key = ImportSecretKeyFromRaw(
  291. test_kek, wrapping_algorithm,
  292. blink::kWebCryptoKeyUsageWrapKey | blink::kWebCryptoKeyUsageUnwrapKey);
  293. // Unwrap of a corrupted version of the known ciphertext should fail, due to
  294. // AES-KW's built-in integrity check.
  295. blink::WebCryptoKey unwrapped_key;
  296. EXPECT_EQ(Status::OperationError(),
  297. UnwrapKey(blink::kWebCryptoKeyFormatRaw, Corrupted(test_ciphertext),
  298. wrapping_key, wrapping_algorithm,
  299. CreateAlgorithm(blink::kWebCryptoAlgorithmIdAesCbc), true,
  300. blink::kWebCryptoKeyUsageEncrypt, &unwrapped_key));
  301. }
  302. TEST_F(WebCryptoAesKwTest, AesKwJwkSymkeyUnwrapKnownData) {
  303. // The following data lists a known HMAC SHA-256 key, then a JWK
  304. // representation of this key which was encrypted ("wrapped") using AES-KW and
  305. // the following wrapping key.
  306. // For reference, the intermediate clear JWK is
  307. // {"alg":"HS256","ext":true,"k":<b64urlKey>,"key_ops":["verify"],"kty":"oct"}
  308. // (Not shown is space padding to ensure the cleartext meets the size
  309. // requirements of the AES-KW algorithm.)
  310. const std::vector<uint8_t> key_data = HexStringToBytes(
  311. "000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F");
  312. const std::vector<uint8_t> wrapped_key_data = HexStringToBytes(
  313. "14E6380B35FDC5B72E1994764B6CB7BFDD64E7832894356AAEE6C3768FC3D0F115E6B0"
  314. "6729756225F999AA99FDF81FD6A359F1576D3D23DE6CB69C3937054EB497AC1E8C38D5"
  315. "5E01B9783A20C8D930020932CF25926103002213D0FC37279888154FEBCEDF31832158"
  316. "97938C5CFE5B10B4254D0C399F39D0");
  317. const std::vector<uint8_t> wrapping_key_data =
  318. HexStringToBytes("000102030405060708090A0B0C0D0E0F");
  319. const blink::WebCryptoAlgorithm wrapping_algorithm =
  320. CreateAlgorithm(blink::kWebCryptoAlgorithmIdAesKw);
  321. // Import the wrapping key.
  322. blink::WebCryptoKey wrapping_key =
  323. ImportSecretKeyFromRaw(wrapping_key_data, wrapping_algorithm,
  324. blink::kWebCryptoKeyUsageUnwrapKey);
  325. // Unwrap the known wrapped key data to produce a new key
  326. blink::WebCryptoKey unwrapped_key;
  327. ASSERT_EQ(Status::Success(),
  328. UnwrapKey(blink::kWebCryptoKeyFormatJwk, wrapped_key_data,
  329. wrapping_key, wrapping_algorithm,
  330. CreateHmacImportAlgorithmNoLength(
  331. blink::kWebCryptoAlgorithmIdSha256),
  332. true, blink::kWebCryptoKeyUsageVerify, &unwrapped_key));
  333. // Validate the new key's attributes.
  334. EXPECT_FALSE(unwrapped_key.IsNull());
  335. EXPECT_TRUE(unwrapped_key.Handle());
  336. EXPECT_EQ(blink::kWebCryptoKeyTypeSecret, unwrapped_key.GetType());
  337. EXPECT_EQ(blink::kWebCryptoAlgorithmIdHmac, unwrapped_key.Algorithm().Id());
  338. EXPECT_EQ(blink::kWebCryptoAlgorithmIdSha256,
  339. unwrapped_key.Algorithm().HmacParams()->GetHash().Id());
  340. EXPECT_EQ(256u, unwrapped_key.Algorithm().HmacParams()->LengthBits());
  341. EXPECT_EQ(true, unwrapped_key.Extractable());
  342. EXPECT_EQ(blink::kWebCryptoKeyUsageVerify, unwrapped_key.Usages());
  343. // Export the new key's raw data and compare to the known original.
  344. std::vector<uint8_t> raw_key;
  345. EXPECT_EQ(Status::Success(),
  346. ExportKey(blink::kWebCryptoKeyFormatRaw, unwrapped_key, &raw_key));
  347. EXPECT_BYTES_EQ(key_data, raw_key);
  348. }
  349. // Try importing an AES-KW key with unsupported key usages using raw
  350. // format. AES-KW keys support the following usages:
  351. // 'wrapKey', 'unwrapKey'
  352. TEST_F(WebCryptoAesKwTest, ImportKeyBadUsage_Raw) {
  353. const blink::WebCryptoAlgorithm algorithm =
  354. CreateAlgorithm(blink::kWebCryptoAlgorithmIdAesKw);
  355. const blink::WebCryptoKeyUsageMask kBadUsages[] = {
  356. blink::kWebCryptoKeyUsageEncrypt,
  357. blink::kWebCryptoKeyUsageDecrypt,
  358. blink::kWebCryptoKeyUsageSign,
  359. blink::kWebCryptoKeyUsageSign | blink::kWebCryptoKeyUsageUnwrapKey,
  360. blink::kWebCryptoKeyUsageDeriveBits,
  361. blink::kWebCryptoKeyUsageUnwrapKey | blink::kWebCryptoKeyUsageVerify,
  362. };
  363. std::vector<uint8_t> key_bytes(16);
  364. for (auto usage : kBadUsages) {
  365. SCOPED_TRACE(usage);
  366. blink::WebCryptoKey key;
  367. ASSERT_EQ(Status::ErrorCreateKeyBadUsages(),
  368. ImportKey(blink::kWebCryptoKeyFormatRaw, key_bytes, algorithm,
  369. true, usage, &key));
  370. }
  371. }
  372. // Try unwrapping an HMAC key with unsupported usages using JWK format and
  373. // AES-KW. HMAC keys support the following usages:
  374. // 'sign', 'verify'
  375. TEST_F(WebCryptoAesKwTest, UnwrapHmacKeyBadUsage_JWK) {
  376. const blink::WebCryptoAlgorithm unwrap_algorithm =
  377. CreateAlgorithm(blink::kWebCryptoAlgorithmIdAesKw);
  378. const blink::WebCryptoKeyUsageMask kBadUsages[] = {
  379. blink::kWebCryptoKeyUsageEncrypt,
  380. blink::kWebCryptoKeyUsageDecrypt,
  381. blink::kWebCryptoKeyUsageWrapKey,
  382. blink::kWebCryptoKeyUsageSign | blink::kWebCryptoKeyUsageWrapKey,
  383. blink::kWebCryptoKeyUsageVerify | blink::kWebCryptoKeyUsageDeriveKey,
  384. };
  385. // Import the wrapping key.
  386. blink::WebCryptoKey wrapping_key;
  387. ASSERT_EQ(Status::Success(),
  388. ImportKey(blink::kWebCryptoKeyFormatRaw, std::vector<uint8_t>(16),
  389. unwrap_algorithm, true,
  390. blink::kWebCryptoKeyUsageUnwrapKey, &wrapping_key));
  391. // The JWK plain text is:
  392. // {"kty":"oct","alg":"HS256","k":"GADWrMRHwQfoNaXU5fZvTg"}
  393. const char* kWrappedJwk =
  394. "C2B7F19A32EE31372CD40C9C969B8CD67553E5AEA7FD1144874584E46ABCD79FDC308848"
  395. "B2DD8BD36A2D61062B9C5B8B499B8D6EF8EB320D87A614952B4EE771";
  396. for (auto usage : kBadUsages) {
  397. SCOPED_TRACE(usage);
  398. blink::WebCryptoKey key;
  399. ASSERT_EQ(
  400. Status::ErrorCreateKeyBadUsages(),
  401. UnwrapKey(blink::kWebCryptoKeyFormatJwk, HexStringToBytes(kWrappedJwk),
  402. wrapping_key, unwrap_algorithm,
  403. CreateHmacImportAlgorithmNoLength(
  404. blink::kWebCryptoAlgorithmIdSha256),
  405. true, usage, &key));
  406. }
  407. }
  408. // Try unwrapping an RSA-SSA public key with unsupported usages using JWK format
  409. // and AES-KW. RSA-SSA public keys support the following usages:
  410. // 'verify'
  411. TEST_F(WebCryptoAesKwTest, UnwrapRsaSsaPublicKeyBadUsage_JWK) {
  412. const blink::WebCryptoAlgorithm unwrap_algorithm =
  413. CreateAlgorithm(blink::kWebCryptoAlgorithmIdAesKw);
  414. const blink::WebCryptoKeyUsageMask kBadUsages[] = {
  415. blink::kWebCryptoKeyUsageEncrypt,
  416. blink::kWebCryptoKeyUsageSign,
  417. blink::kWebCryptoKeyUsageDecrypt,
  418. blink::kWebCryptoKeyUsageWrapKey,
  419. blink::kWebCryptoKeyUsageSign | blink::kWebCryptoKeyUsageWrapKey,
  420. };
  421. // Import the wrapping key.
  422. blink::WebCryptoKey wrapping_key;
  423. ASSERT_EQ(Status::Success(),
  424. ImportKey(blink::kWebCryptoKeyFormatRaw, std::vector<uint8_t>(16),
  425. unwrap_algorithm, true,
  426. blink::kWebCryptoKeyUsageUnwrapKey, &wrapping_key));
  427. // The JWK plaintext is:
  428. // { "kty": "RSA","alg": "RS256","n": "...","e": "AQAB"}
  429. const char* kWrappedJwk =
  430. "CE8DAEF99E977EE58958B8C4494755C846E883B2ECA575C5366622839AF71AB30875F152"
  431. "E8E33E15A7817A3A2874EB53EFE05C774D98BC936BA9BA29BEB8BB3F3C3CE2323CB3359D"
  432. "E3F426605CF95CCF0E01E870ABD7E35F62E030B5FB6E520A5885514D1D850FB64B57806D"
  433. "1ADA57C6E27DF345D8292D80F6B074F1BE51C4CF3D76ECC8886218551308681B44FAC60B"
  434. "8CF6EA439BC63239103D0AE81ADB96F908680586C6169284E32EB7DD09D31103EBDAC0C2"
  435. "40C72DCF0AEA454113CC47457B13305B25507CBEAB9BDC8D8E0F867F9167F9DCEF0D9F9B"
  436. "30F2EE83CEDFD51136852C8A5939B768";
  437. for (auto usage : kBadUsages) {
  438. SCOPED_TRACE(usage);
  439. blink::WebCryptoKey key;
  440. ASSERT_EQ(
  441. Status::ErrorCreateKeyBadUsages(),
  442. UnwrapKey(blink::kWebCryptoKeyFormatJwk, HexStringToBytes(kWrappedJwk),
  443. wrapping_key, unwrap_algorithm,
  444. CreateRsaHashedImportAlgorithm(
  445. blink::kWebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
  446. blink::kWebCryptoAlgorithmIdSha256),
  447. true, usage, &key));
  448. }
  449. }
  450. } // namespace
  451. } // namespace webcrypto