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
5#include "base/stl_util.h"
6#include "content/child/webcrypto/algorithm_dispatch.h"
7#include "content/child/webcrypto/crypto_data.h"
8#include "content/child/webcrypto/status.h"
9#include "content/child/webcrypto/test/test_helpers.h"
10#include "content/child/webcrypto/webcrypto_util.h"
11#include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
12#include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
13
14namespace content {
15
16namespace webcrypto {
17
18namespace {
19
20blink::WebCryptoAlgorithm CreateAesKwKeyGenAlgorithm(
21    unsigned short key_length_bits) {
22  return CreateAesKeyGenAlgorithm(blink::WebCryptoAlgorithmIdAesKw,
23                                  key_length_bits);
24}
25
26TEST(WebCryptoAesKwTest, GenerateKeyBadLength) {
27  const unsigned short kKeyLen[] = {0, 127, 257};
28  blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
29  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kKeyLen); ++i) {
30    SCOPED_TRACE(i);
31    EXPECT_EQ(Status::ErrorGenerateKeyLength(),
32              GenerateSecretKey(
33                  CreateAesKwKeyGenAlgorithm(kKeyLen[i]), true, 0, &key));
34  }
35}
36
37TEST(WebCryptoAesKwTest, ImportKeyJwkKeyOpsWrapUnwrap) {
38  blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
39  base::DictionaryValue dict;
40  dict.SetString("kty", "oct");
41  dict.SetString("k", "GADWrMRHwQfoNaXU5fZvTg==");
42  base::ListValue* key_ops = new base::ListValue;
43  dict.Set("key_ops", key_ops);  // Takes ownership.
44
45  key_ops->AppendString("wrapKey");
46
47  EXPECT_EQ(
48      Status::Success(),
49      ImportKeyJwkFromDict(dict,
50                           CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw),
51                           false,
52                           blink::WebCryptoKeyUsageWrapKey,
53                           &key));
54
55  EXPECT_EQ(blink::WebCryptoKeyUsageWrapKey, key.usages());
56
57  key_ops->AppendString("unwrapKey");
58
59  EXPECT_EQ(
60      Status::Success(),
61      ImportKeyJwkFromDict(dict,
62                           CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw),
63                           false,
64                           blink::WebCryptoKeyUsageUnwrapKey,
65                           &key));
66
67  EXPECT_EQ(blink::WebCryptoKeyUsageUnwrapKey, key.usages());
68}
69
70TEST(WebCryptoAesKwTest, ImportExportJwk) {
71  const blink::WebCryptoAlgorithm algorithm =
72      CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw);
73
74  // AES-KW 128
75  ImportExportJwkSymmetricKey(
76      128,
77      algorithm,
78      blink::WebCryptoKeyUsageWrapKey | blink::WebCryptoKeyUsageUnwrapKey,
79      "A128KW");
80
81  // AES-KW 256
82  ImportExportJwkSymmetricKey(
83      256,
84      algorithm,
85      blink::WebCryptoKeyUsageWrapKey | blink::WebCryptoKeyUsageUnwrapKey,
86      "A256KW");
87}
88
89TEST(WebCryptoAesKwTest, AesKwKeyImport) {
90  blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
91  blink::WebCryptoAlgorithm algorithm =
92      CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw);
93
94  // Import a 128-bit Key Encryption Key (KEK)
95  std::string key_raw_hex_in = "025a8cf3f08b4f6c5f33bbc76a471939";
96  ASSERT_EQ(Status::Success(),
97            ImportKey(blink::WebCryptoKeyFormatRaw,
98                      CryptoData(HexStringToBytes(key_raw_hex_in)),
99                      algorithm,
100                      true,
101                      blink::WebCryptoKeyUsageWrapKey,
102                      &key));
103  std::vector<uint8_t> key_raw_out;
104  EXPECT_EQ(Status::Success(),
105            ExportKey(blink::WebCryptoKeyFormatRaw, key, &key_raw_out));
106  EXPECT_BYTES_EQ_HEX(key_raw_hex_in, key_raw_out);
107
108  // Import a 192-bit KEK
109  key_raw_hex_in = "c0192c6466b2370decbb62b2cfef4384544ffeb4d2fbc103";
110  ASSERT_EQ(Status::ErrorAes192BitUnsupported(),
111            ImportKey(blink::WebCryptoKeyFormatRaw,
112                      CryptoData(HexStringToBytes(key_raw_hex_in)),
113                      algorithm,
114                      true,
115                      blink::WebCryptoKeyUsageWrapKey,
116                      &key));
117
118  // Import a 256-bit Key Encryption Key (KEK)
119  key_raw_hex_in =
120      "e11fe66380d90fa9ebefb74e0478e78f95664d0c67ca20ce4a0b5842863ac46f";
121  ASSERT_EQ(Status::Success(),
122            ImportKey(blink::WebCryptoKeyFormatRaw,
123                      CryptoData(HexStringToBytes(key_raw_hex_in)),
124                      algorithm,
125                      true,
126                      blink::WebCryptoKeyUsageWrapKey,
127                      &key));
128  EXPECT_EQ(Status::Success(),
129            ExportKey(blink::WebCryptoKeyFormatRaw, key, &key_raw_out));
130  EXPECT_BYTES_EQ_HEX(key_raw_hex_in, key_raw_out);
131
132  // Fail import of 0 length key
133  EXPECT_EQ(Status::ErrorImportAesKeyLength(),
134            ImportKey(blink::WebCryptoKeyFormatRaw,
135                      CryptoData(HexStringToBytes("")),
136                      algorithm,
137                      true,
138                      blink::WebCryptoKeyUsageWrapKey,
139                      &key));
140
141  // Fail import of 124-bit KEK
142  key_raw_hex_in = "3e4566a2bdaa10cb68134fa66c15ddb";
143  EXPECT_EQ(Status::ErrorImportAesKeyLength(),
144            ImportKey(blink::WebCryptoKeyFormatRaw,
145                      CryptoData(HexStringToBytes(key_raw_hex_in)),
146                      algorithm,
147                      true,
148                      blink::WebCryptoKeyUsageWrapKey,
149                      &key));
150
151  // Fail import of 200-bit KEK
152  key_raw_hex_in = "0a1d88608a5ad9fec64f1ada269ebab4baa2feeb8d95638c0e";
153  EXPECT_EQ(Status::ErrorImportAesKeyLength(),
154            ImportKey(blink::WebCryptoKeyFormatRaw,
155                      CryptoData(HexStringToBytes(key_raw_hex_in)),
156                      algorithm,
157                      true,
158                      blink::WebCryptoKeyUsageWrapKey,
159                      &key));
160
161  // Fail import of 260-bit KEK
162  key_raw_hex_in =
163      "72d4e475ff34215416c9ad9c8281247a4d730c5f275ac23f376e73e3bce8d7d5a";
164  EXPECT_EQ(Status::ErrorImportAesKeyLength(),
165            ImportKey(blink::WebCryptoKeyFormatRaw,
166                      CryptoData(HexStringToBytes(key_raw_hex_in)),
167                      algorithm,
168                      true,
169                      blink::WebCryptoKeyUsageWrapKey,
170                      &key));
171}
172
173TEST(WebCryptoAesKwTest, UnwrapFailures) {
174  // This test exercises the code path common to all unwrap operations.
175  scoped_ptr<base::ListValue> tests;
176  ASSERT_TRUE(ReadJsonTestFileToList("aes_kw.json", &tests));
177  base::DictionaryValue* test;
178  ASSERT_TRUE(tests->GetDictionary(0, &test));
179  const std::vector<uint8_t> test_kek = GetBytesFromHexString(test, "kek");
180  const std::vector<uint8_t> test_ciphertext =
181      GetBytesFromHexString(test, "ciphertext");
182
183  blink::WebCryptoKey unwrapped_key = blink::WebCryptoKey::createNull();
184
185  // Using a wrapping algorithm that does not match the wrapping key algorithm
186  // should fail.
187  blink::WebCryptoKey wrapping_key =
188      ImportSecretKeyFromRaw(test_kek,
189                             CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw),
190                             blink::WebCryptoKeyUsageUnwrapKey);
191  EXPECT_EQ(Status::ErrorUnexpected(),
192            UnwrapKey(blink::WebCryptoKeyFormatRaw,
193                      CryptoData(test_ciphertext),
194                      wrapping_key,
195                      CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
196                      CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
197                      true,
198                      blink::WebCryptoKeyUsageEncrypt,
199                      &unwrapped_key));
200}
201
202TEST(WebCryptoAesKwTest, AesKwRawSymkeyWrapUnwrapKnownAnswer) {
203  scoped_ptr<base::ListValue> tests;
204  ASSERT_TRUE(ReadJsonTestFileToList("aes_kw.json", &tests));
205
206  for (size_t test_index = 0; test_index < tests->GetSize(); ++test_index) {
207    SCOPED_TRACE(test_index);
208    base::DictionaryValue* test;
209    ASSERT_TRUE(tests->GetDictionary(test_index, &test));
210    const std::vector<uint8_t> test_kek = GetBytesFromHexString(test, "kek");
211    const std::vector<uint8_t> test_key = GetBytesFromHexString(test, "key");
212    const std::vector<uint8_t> test_ciphertext =
213        GetBytesFromHexString(test, "ciphertext");
214    const blink::WebCryptoAlgorithm wrapping_algorithm =
215        CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw);
216
217    // Import the wrapping key.
218    blink::WebCryptoKey wrapping_key = ImportSecretKeyFromRaw(
219        test_kek,
220        wrapping_algorithm,
221        blink::WebCryptoKeyUsageWrapKey | blink::WebCryptoKeyUsageUnwrapKey);
222
223    // Import the key to be wrapped.
224    blink::WebCryptoKey key = ImportSecretKeyFromRaw(
225        test_key,
226        CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha1),
227        blink::WebCryptoKeyUsageSign);
228
229    // Wrap the key and verify the ciphertext result against the known answer.
230    std::vector<uint8_t> wrapped_key;
231    ASSERT_EQ(Status::Success(),
232              WrapKey(blink::WebCryptoKeyFormatRaw,
233                      key,
234                      wrapping_key,
235                      wrapping_algorithm,
236                      &wrapped_key));
237    EXPECT_BYTES_EQ(test_ciphertext, wrapped_key);
238
239    // Unwrap the known ciphertext to get a new test_key.
240    blink::WebCryptoKey unwrapped_key = blink::WebCryptoKey::createNull();
241    ASSERT_EQ(
242        Status::Success(),
243        UnwrapKey(blink::WebCryptoKeyFormatRaw,
244                  CryptoData(test_ciphertext),
245                  wrapping_key,
246                  wrapping_algorithm,
247                  CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha1),
248                  true,
249                  blink::WebCryptoKeyUsageSign,
250                  &unwrapped_key));
251    EXPECT_FALSE(key.isNull());
252    EXPECT_TRUE(key.handle());
253    EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type());
254    EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac, key.algorithm().id());
255    EXPECT_EQ(true, key.extractable());
256    EXPECT_EQ(blink::WebCryptoKeyUsageSign, key.usages());
257
258    // Export the new key and compare its raw bytes with the original known key.
259    std::vector<uint8_t> raw_key;
260    EXPECT_EQ(Status::Success(),
261              ExportKey(blink::WebCryptoKeyFormatRaw, unwrapped_key, &raw_key));
262    EXPECT_BYTES_EQ(test_key, raw_key);
263  }
264}
265
266// Unwrap a HMAC key using AES-KW, and then try doing a sign/verify with the
267// unwrapped key
268TEST(WebCryptoAesKwTest, AesKwRawSymkeyUnwrapSignVerifyHmac) {
269  scoped_ptr<base::ListValue> tests;
270  ASSERT_TRUE(ReadJsonTestFileToList("aes_kw.json", &tests));
271
272  base::DictionaryValue* test;
273  ASSERT_TRUE(tests->GetDictionary(0, &test));
274  const std::vector<uint8_t> test_kek = GetBytesFromHexString(test, "kek");
275  const std::vector<uint8_t> test_ciphertext =
276      GetBytesFromHexString(test, "ciphertext");
277  const blink::WebCryptoAlgorithm wrapping_algorithm =
278      CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw);
279
280  // Import the wrapping key.
281  blink::WebCryptoKey wrapping_key = ImportSecretKeyFromRaw(
282      test_kek, wrapping_algorithm, blink::WebCryptoKeyUsageUnwrapKey);
283
284  // Unwrap the known ciphertext.
285  blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
286  ASSERT_EQ(
287      Status::Success(),
288      UnwrapKey(blink::WebCryptoKeyFormatRaw,
289                CryptoData(test_ciphertext),
290                wrapping_key,
291                wrapping_algorithm,
292                CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha1),
293                false,
294                blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify,
295                &key));
296
297  EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type());
298  EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac, key.algorithm().id());
299  EXPECT_FALSE(key.extractable());
300  EXPECT_EQ(blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify,
301            key.usages());
302
303  // Sign an empty message and ensure it is verified.
304  std::vector<uint8_t> test_message;
305  std::vector<uint8_t> signature;
306
307  ASSERT_EQ(Status::Success(),
308            Sign(CreateAlgorithm(blink::WebCryptoAlgorithmIdHmac),
309                 key,
310                 CryptoData(test_message),
311                 &signature));
312
313  EXPECT_GT(signature.size(), 0u);
314
315  bool verify_result;
316  ASSERT_EQ(Status::Success(),
317            Verify(CreateAlgorithm(blink::WebCryptoAlgorithmIdHmac),
318                   key,
319                   CryptoData(signature),
320                   CryptoData(test_message),
321                   &verify_result));
322}
323
324TEST(WebCryptoAesKwTest, AesKwRawSymkeyWrapUnwrapErrors) {
325  scoped_ptr<base::ListValue> tests;
326  ASSERT_TRUE(ReadJsonTestFileToList("aes_kw.json", &tests));
327  base::DictionaryValue* test;
328  // Use 256 bits of data with a 256-bit KEK
329  ASSERT_TRUE(tests->GetDictionary(3, &test));
330  const std::vector<uint8_t> test_kek = GetBytesFromHexString(test, "kek");
331  const std::vector<uint8_t> test_key = GetBytesFromHexString(test, "key");
332  const std::vector<uint8_t> test_ciphertext =
333      GetBytesFromHexString(test, "ciphertext");
334  const blink::WebCryptoAlgorithm wrapping_algorithm =
335      CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw);
336  const blink::WebCryptoAlgorithm key_algorithm =
337      CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc);
338  // Import the wrapping key.
339  blink::WebCryptoKey wrapping_key = ImportSecretKeyFromRaw(
340      test_kek,
341      wrapping_algorithm,
342      blink::WebCryptoKeyUsageWrapKey | blink::WebCryptoKeyUsageUnwrapKey);
343  // Import the key to be wrapped.
344  blink::WebCryptoKey key =
345      ImportSecretKeyFromRaw(test_key,
346                             CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
347                             blink::WebCryptoKeyUsageEncrypt);
348
349  // Unwrap with wrapped data too small must fail.
350  const std::vector<uint8_t> small_data(test_ciphertext.begin(),
351                                        test_ciphertext.begin() + 23);
352  blink::WebCryptoKey unwrapped_key = blink::WebCryptoKey::createNull();
353  EXPECT_EQ(Status::ErrorDataTooSmall(),
354            UnwrapKey(blink::WebCryptoKeyFormatRaw,
355                      CryptoData(small_data),
356                      wrapping_key,
357                      wrapping_algorithm,
358                      key_algorithm,
359                      true,
360                      blink::WebCryptoKeyUsageEncrypt,
361                      &unwrapped_key));
362
363  // Unwrap with wrapped data size not a multiple of 8 bytes must fail.
364  const std::vector<uint8_t> unaligned_data(test_ciphertext.begin(),
365                                            test_ciphertext.end() - 2);
366  EXPECT_EQ(Status::ErrorInvalidAesKwDataLength(),
367            UnwrapKey(blink::WebCryptoKeyFormatRaw,
368                      CryptoData(unaligned_data),
369                      wrapping_key,
370                      wrapping_algorithm,
371                      key_algorithm,
372                      true,
373                      blink::WebCryptoKeyUsageEncrypt,
374                      &unwrapped_key));
375}
376
377TEST(WebCryptoAesKwTest, AesKwRawSymkeyUnwrapCorruptData) {
378  scoped_ptr<base::ListValue> tests;
379  ASSERT_TRUE(ReadJsonTestFileToList("aes_kw.json", &tests));
380  base::DictionaryValue* test;
381  // Use 256 bits of data with a 256-bit KEK
382  ASSERT_TRUE(tests->GetDictionary(3, &test));
383  const std::vector<uint8_t> test_kek = GetBytesFromHexString(test, "kek");
384  const std::vector<uint8_t> test_key = GetBytesFromHexString(test, "key");
385  const std::vector<uint8_t> test_ciphertext =
386      GetBytesFromHexString(test, "ciphertext");
387  const blink::WebCryptoAlgorithm wrapping_algorithm =
388      CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw);
389
390  // Import the wrapping key.
391  blink::WebCryptoKey wrapping_key = ImportSecretKeyFromRaw(
392      test_kek,
393      wrapping_algorithm,
394      blink::WebCryptoKeyUsageWrapKey | blink::WebCryptoKeyUsageUnwrapKey);
395
396  // Unwrap of a corrupted version of the known ciphertext should fail, due to
397  // AES-KW's built-in integrity check.
398  blink::WebCryptoKey unwrapped_key = blink::WebCryptoKey::createNull();
399  EXPECT_EQ(Status::OperationError(),
400            UnwrapKey(blink::WebCryptoKeyFormatRaw,
401                      CryptoData(Corrupted(test_ciphertext)),
402                      wrapping_key,
403                      wrapping_algorithm,
404                      CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
405                      true,
406                      blink::WebCryptoKeyUsageEncrypt,
407                      &unwrapped_key));
408}
409
410TEST(WebCryptoAesKwTest, AesKwJwkSymkeyUnwrapKnownData) {
411  // The following data lists a known HMAC SHA-256 key, then a JWK
412  // representation of this key which was encrypted ("wrapped") using AES-KW and
413  // the following wrapping key.
414  // For reference, the intermediate clear JWK is
415  // {"alg":"HS256","ext":true,"k":<b64urlKey>,"key_ops":["verify"],"kty":"oct"}
416  // (Not shown is space padding to ensure the cleartext meets the size
417  // requirements of the AES-KW algorithm.)
418  const std::vector<uint8_t> key_data = HexStringToBytes(
419      "000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F");
420  const std::vector<uint8_t> wrapped_key_data = HexStringToBytes(
421      "14E6380B35FDC5B72E1994764B6CB7BFDD64E7832894356AAEE6C3768FC3D0F115E6B0"
422      "6729756225F999AA99FDF81FD6A359F1576D3D23DE6CB69C3937054EB497AC1E8C38D5"
423      "5E01B9783A20C8D930020932CF25926103002213D0FC37279888154FEBCEDF31832158"
424      "97938C5CFE5B10B4254D0C399F39D0");
425  const std::vector<uint8_t> wrapping_key_data =
426      HexStringToBytes("000102030405060708090A0B0C0D0E0F");
427  const blink::WebCryptoAlgorithm wrapping_algorithm =
428      CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw);
429
430  // Import the wrapping key.
431  blink::WebCryptoKey wrapping_key = ImportSecretKeyFromRaw(
432      wrapping_key_data, wrapping_algorithm, blink::WebCryptoKeyUsageUnwrapKey);
433
434  // Unwrap the known wrapped key data to produce a new key
435  blink::WebCryptoKey unwrapped_key = blink::WebCryptoKey::createNull();
436  ASSERT_EQ(
437      Status::Success(),
438      UnwrapKey(blink::WebCryptoKeyFormatJwk,
439                CryptoData(wrapped_key_data),
440                wrapping_key,
441                wrapping_algorithm,
442                CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha256),
443                true,
444                blink::WebCryptoKeyUsageVerify,
445                &unwrapped_key));
446
447  // Validate the new key's attributes.
448  EXPECT_FALSE(unwrapped_key.isNull());
449  EXPECT_TRUE(unwrapped_key.handle());
450  EXPECT_EQ(blink::WebCryptoKeyTypeSecret, unwrapped_key.type());
451  EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac, unwrapped_key.algorithm().id());
452  EXPECT_EQ(blink::WebCryptoAlgorithmIdSha256,
453            unwrapped_key.algorithm().hmacParams()->hash().id());
454  EXPECT_EQ(256u, unwrapped_key.algorithm().hmacParams()->lengthBits());
455  EXPECT_EQ(true, unwrapped_key.extractable());
456  EXPECT_EQ(blink::WebCryptoKeyUsageVerify, unwrapped_key.usages());
457
458  // Export the new key's raw data and compare to the known original.
459  std::vector<uint8_t> raw_key;
460  EXPECT_EQ(Status::Success(),
461            ExportKey(blink::WebCryptoKeyFormatRaw, unwrapped_key, &raw_key));
462  EXPECT_BYTES_EQ(key_data, raw_key);
463}
464
465// Try importing an AES-KW key with unsupported key usages using raw
466// format. AES-KW keys support the following usages:
467//   'wrapKey', 'unwrapKey'
468TEST(WebCryptoAesKwTest, ImportKeyBadUsage_Raw) {
469  const blink::WebCryptoAlgorithm algorithm =
470      CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw);
471
472  blink::WebCryptoKeyUsageMask bad_usages[] = {
473      blink::WebCryptoKeyUsageEncrypt,
474      blink::WebCryptoKeyUsageDecrypt,
475      blink::WebCryptoKeyUsageSign,
476      blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageUnwrapKey,
477      blink::WebCryptoKeyUsageDeriveBits,
478      blink::WebCryptoKeyUsageUnwrapKey | blink::WebCryptoKeyUsageVerify,
479  };
480
481  std::vector<uint8_t> key_bytes(16);
482
483  for (size_t i = 0; i < arraysize(bad_usages); ++i) {
484    SCOPED_TRACE(i);
485
486    blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
487    ASSERT_EQ(Status::ErrorCreateKeyBadUsages(),
488              ImportKey(blink::WebCryptoKeyFormatRaw,
489                        CryptoData(key_bytes),
490                        algorithm,
491                        true,
492                        bad_usages[i],
493                        &key));
494  }
495}
496
497// Try unwrapping an HMAC key with unsupported usages using JWK format and
498// AES-KW. HMAC keys support the following usages:
499//   'sign', 'verify'
500TEST(WebCryptoAesKwTest, UnwrapHmacKeyBadUsage_JWK) {
501  const blink::WebCryptoAlgorithm unwrap_algorithm =
502      CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw);
503
504  blink::WebCryptoKeyUsageMask bad_usages[] = {
505      blink::WebCryptoKeyUsageEncrypt,
506      blink::WebCryptoKeyUsageDecrypt,
507      blink::WebCryptoKeyUsageWrapKey,
508      blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageWrapKey,
509      blink::WebCryptoKeyUsageVerify | blink::WebCryptoKeyUsageDeriveKey,
510  };
511
512  // Import the wrapping key.
513  blink::WebCryptoKey wrapping_key = blink::WebCryptoKey::createNull();
514  ASSERT_EQ(Status::Success(),
515            ImportKey(blink::WebCryptoKeyFormatRaw,
516                      CryptoData(std::vector<uint8_t>(16)),
517                      unwrap_algorithm,
518                      true,
519                      blink::WebCryptoKeyUsageUnwrapKey,
520                      &wrapping_key));
521
522  // The JWK plain text is:
523  //   {   "kty": "oct","alg": "HS256","k": "GADWrMRHwQfoNaXU5fZvTg=="}
524  const char* kWrappedJwk =
525      "0AA245F17064FFB2A7A094436A39BEBFC962C627303D1327EA750CE9F917688C2782A943"
526      "7AE7586547AC490E8AE7D5B02D63868D5C3BB57D36C4C8C5BF3962ACEC6F42E767E5706"
527      "4";
528
529  for (size_t i = 0; i < arraysize(bad_usages); ++i) {
530    SCOPED_TRACE(i);
531
532    blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
533
534    ASSERT_EQ(
535        Status::ErrorCreateKeyBadUsages(),
536        UnwrapKey(blink::WebCryptoKeyFormatJwk,
537                  CryptoData(HexStringToBytes(kWrappedJwk)),
538                  wrapping_key,
539                  unwrap_algorithm,
540                  CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha256),
541                  true,
542                  bad_usages[i],
543                  &key));
544  }
545}
546
547// Try unwrapping an RSA-SSA public key with unsupported usages using JWK format
548// and AES-KW. RSA-SSA public keys support the following usages:
549//   'verify'
550TEST(WebCryptoAesKwTest, UnwrapRsaSsaPublicKeyBadUsage_JWK) {
551  const blink::WebCryptoAlgorithm unwrap_algorithm =
552      CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw);
553
554  blink::WebCryptoKeyUsageMask bad_usages[] = {
555      blink::WebCryptoKeyUsageEncrypt,
556      blink::WebCryptoKeyUsageSign,
557      blink::WebCryptoKeyUsageDecrypt,
558      blink::WebCryptoKeyUsageWrapKey,
559      blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageWrapKey,
560  };
561
562  // Import the wrapping key.
563  blink::WebCryptoKey wrapping_key = blink::WebCryptoKey::createNull();
564  ASSERT_EQ(Status::Success(),
565            ImportKey(blink::WebCryptoKeyFormatRaw,
566                      CryptoData(std::vector<uint8_t>(16)),
567                      unwrap_algorithm,
568                      true,
569                      blink::WebCryptoKeyUsageUnwrapKey,
570                      &wrapping_key));
571
572  // The JWK plaintext is:
573  // {    "kty": "RSA","alg": "RS256","n": "...","e": "AQAB"}
574
575  const char* kWrappedJwk =
576      "CE8DAEF99E977EE58958B8C4494755C846E883B2ECA575C5366622839AF71AB30875F152"
577      "E8E33E15A7817A3A2874EB53EFE05C774D98BC936BA9BA29BEB8BB3F3C3CE2323CB3359D"
578      "E3F426605CF95CCF0E01E870ABD7E35F62E030B5FB6E520A5885514D1D850FB64B57806D"
579      "1ADA57C6E27DF345D8292D80F6B074F1BE51C4CF3D76ECC8886218551308681B44FAC60B"
580      "8CF6EA439BC63239103D0AE81ADB96F908680586C6169284E32EB7DD09D31103EBDAC0C2"
581      "40C72DCF0AEA454113CC47457B13305B25507CBEAB9BDC8D8E0F867F9167F9DCEF0D9F9B"
582      "30F2EE83CEDFD51136852C8A5939B768";
583
584  for (size_t i = 0; i < arraysize(bad_usages); ++i) {
585    SCOPED_TRACE(i);
586
587    blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
588
589    ASSERT_EQ(Status::ErrorCreateKeyBadUsages(),
590              UnwrapKey(blink::WebCryptoKeyFormatJwk,
591                        CryptoData(HexStringToBytes(kWrappedJwk)),
592                        wrapping_key,
593                        unwrap_algorithm,
594                        CreateRsaHashedImportAlgorithm(
595                            blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
596                            blink::WebCryptoAlgorithmIdSha256),
597                        true,
598                        bad_usages[i],
599                        &key));
600  }
601}
602
603}  // namespace
604
605}  // namespace webcrypto
606
607}  // namespace content
608