Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / content / child / webcrypto / test / aes_cbc_unittest.cc
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
14 namespace content {
15
16 namespace webcrypto {
17
18 namespace {
19
20 // Creates an AES-CBC algorithm.
21 blink::WebCryptoAlgorithm CreateAesCbcAlgorithm(
22     const std::vector<uint8_t>& iv) {
23   return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
24       blink::WebCryptoAlgorithmIdAesCbc,
25       new blink::WebCryptoAesCbcParams(vector_as_array(&iv), iv.size()));
26 }
27
28 blink::WebCryptoAlgorithm CreateAesCbcKeyGenAlgorithm(
29     unsigned short key_length_bits) {
30   return CreateAesKeyGenAlgorithm(blink::WebCryptoAlgorithmIdAesCbc,
31                                   key_length_bits);
32 }
33
34 blink::WebCryptoKey GetTestAesCbcKey() {
35   const std::string key_hex = "2b7e151628aed2a6abf7158809cf4f3c";
36   blink::WebCryptoKey key = ImportSecretKeyFromRaw(
37       HexStringToBytes(key_hex),
38       CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
39       blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt);
40
41   // Verify exported raw key is identical to the imported data
42   std::vector<uint8_t> raw_key;
43   EXPECT_EQ(Status::Success(),
44             ExportKey(blink::WebCryptoKeyFormatRaw, key, &raw_key));
45   EXPECT_BYTES_EQ_HEX(key_hex, raw_key);
46   return key;
47 }
48
49 TEST(WebCryptoAesCbcTest, IvTooSmall) {
50   std::vector<uint8_t> output;
51
52   // Use an invalid |iv| (fewer than 16 bytes)
53   std::vector<uint8_t> input(32);
54   std::vector<uint8_t> iv;
55   EXPECT_EQ(Status::ErrorIncorrectSizeAesCbcIv(),
56             Encrypt(CreateAesCbcAlgorithm(iv),
57                     GetTestAesCbcKey(),
58                     CryptoData(input),
59                     &output));
60   EXPECT_EQ(Status::ErrorIncorrectSizeAesCbcIv(),
61             Decrypt(CreateAesCbcAlgorithm(iv),
62                     GetTestAesCbcKey(),
63                     CryptoData(input),
64                     &output));
65 }
66
67 TEST(WebCryptoAesCbcTest, IvTooLarge) {
68   std::vector<uint8_t> output;
69
70   // Use an invalid |iv| (more than 16 bytes)
71   std::vector<uint8_t> input(32);
72   std::vector<uint8_t> iv(17);
73   EXPECT_EQ(Status::ErrorIncorrectSizeAesCbcIv(),
74             Encrypt(CreateAesCbcAlgorithm(iv),
75                     GetTestAesCbcKey(),
76                     CryptoData(input),
77                     &output));
78   EXPECT_EQ(Status::ErrorIncorrectSizeAesCbcIv(),
79             Decrypt(CreateAesCbcAlgorithm(iv),
80                     GetTestAesCbcKey(),
81                     CryptoData(input),
82                     &output));
83 }
84
85 TEST(WebCryptoAesCbcTest, InputTooLarge) {
86   std::vector<uint8_t> output;
87
88   // Give an input that is too large (would cause integer overflow when
89   // narrowing to an int). Note that both OpenSSL and NSS operate on signed int
90   // lengths.
91   std::vector<uint8_t> iv(16);
92
93   // Pretend the input is large. Don't pass data pointer as NULL in case that
94   // is special cased; the implementation shouldn't actually dereference the
95   // data.
96   CryptoData input(&iv[0], INT_MAX - 3);
97
98   EXPECT_EQ(
99       Status::ErrorDataTooLarge(),
100       Encrypt(CreateAesCbcAlgorithm(iv), GetTestAesCbcKey(), input, &output));
101   EXPECT_EQ(
102       Status::ErrorDataTooLarge(),
103       Decrypt(CreateAesCbcAlgorithm(iv), GetTestAesCbcKey(), input, &output));
104 }
105
106 TEST(WebCryptoAesCbcTest, KeyTooSmall) {
107   std::vector<uint8_t> output;
108
109   // Fail importing the key (too few bytes specified)
110   std::vector<uint8_t> key_raw(1);
111   std::vector<uint8_t> iv(16);
112
113   blink::WebCryptoKey key;
114   EXPECT_EQ(Status::ErrorImportAesKeyLength(),
115             ImportKey(blink::WebCryptoKeyFormatRaw,
116                       CryptoData(key_raw),
117                       CreateAesCbcAlgorithm(iv),
118                       true,
119                       blink::WebCryptoKeyUsageEncrypt,
120                       &key));
121 }
122
123 TEST(WebCryptoAesCbcTest, ExportKeyUnsupportedFormat) {
124   std::vector<uint8_t> output;
125
126   // Fail exporting the key in SPKI and PKCS#8 formats (not allowed for secret
127   // keys).
128   EXPECT_EQ(
129       Status::ErrorUnsupportedExportKeyFormat(),
130       ExportKey(blink::WebCryptoKeyFormatSpki, GetTestAesCbcKey(), &output));
131   EXPECT_EQ(
132       Status::ErrorUnsupportedExportKeyFormat(),
133       ExportKey(blink::WebCryptoKeyFormatPkcs8, GetTestAesCbcKey(), &output));
134 }
135
136 TEST(WebCryptoAesCbcTest, ImportKeyUnsupportedFormat) {
137   blink::WebCryptoKey key;
138   ASSERT_EQ(Status::ErrorUnsupportedImportKeyFormat(),
139             ImportKey(blink::WebCryptoKeyFormatSpki,
140                       CryptoData(HexStringToBytes(kPublicKeySpkiDerHex)),
141                       CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
142                       true,
143                       blink::WebCryptoKeyUsageEncrypt,
144                       &key));
145   ASSERT_EQ(Status::ErrorUnsupportedImportKeyFormat(),
146             ImportKey(blink::WebCryptoKeyFormatPkcs8,
147                       CryptoData(HexStringToBytes(kPublicKeySpkiDerHex)),
148                       CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
149                       true,
150                       blink::WebCryptoKeyUsageEncrypt,
151                       &key));
152 }
153
154 TEST(WebCryptoAesCbcTest, KnownAnswerEncryptDecrypt) {
155   scoped_ptr<base::ListValue> tests;
156   ASSERT_TRUE(ReadJsonTestFileToList("aes_cbc.json", &tests));
157
158   for (size_t test_index = 0; test_index < tests->GetSize(); ++test_index) {
159     SCOPED_TRACE(test_index);
160     base::DictionaryValue* test;
161     ASSERT_TRUE(tests->GetDictionary(test_index, &test));
162
163     std::vector<uint8_t> test_key = GetBytesFromHexString(test, "key");
164     std::vector<uint8_t> test_iv = GetBytesFromHexString(test, "iv");
165     std::vector<uint8_t> test_plain_text =
166         GetBytesFromHexString(test, "plain_text");
167     std::vector<uint8_t> test_cipher_text =
168         GetBytesFromHexString(test, "cipher_text");
169
170     blink::WebCryptoKey key = ImportSecretKeyFromRaw(
171         test_key,
172         CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
173         blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt);
174
175     EXPECT_EQ(test_key.size() * 8, key.algorithm().aesParams()->lengthBits());
176
177     // Verify exported raw key is identical to the imported data
178     std::vector<uint8_t> raw_key;
179     EXPECT_EQ(Status::Success(),
180               ExportKey(blink::WebCryptoKeyFormatRaw, key, &raw_key));
181     EXPECT_BYTES_EQ(test_key, raw_key);
182
183     std::vector<uint8_t> output;
184
185     // Test encryption.
186     EXPECT_EQ(Status::Success(),
187               Encrypt(CreateAesCbcAlgorithm(test_iv),
188                       key,
189                       CryptoData(test_plain_text),
190                       &output));
191     EXPECT_BYTES_EQ(test_cipher_text, output);
192
193     // Test decryption.
194     EXPECT_EQ(Status::Success(),
195               Decrypt(CreateAesCbcAlgorithm(test_iv),
196                       key,
197                       CryptoData(test_cipher_text),
198                       &output));
199     EXPECT_BYTES_EQ(test_plain_text, output);
200   }
201 }
202
203 TEST(WebCryptoAesCbcTest, DecryptTruncatedCipherText) {
204   scoped_ptr<base::ListValue> tests;
205   ASSERT_TRUE(ReadJsonTestFileToList("aes_cbc.json", &tests));
206
207   for (size_t test_index = 0; test_index < tests->GetSize(); ++test_index) {
208     SCOPED_TRACE(test_index);
209     base::DictionaryValue* test;
210     ASSERT_TRUE(tests->GetDictionary(test_index, &test));
211
212     std::vector<uint8_t> test_key = GetBytesFromHexString(test, "key");
213     std::vector<uint8_t> test_iv = GetBytesFromHexString(test, "iv");
214     std::vector<uint8_t> test_cipher_text =
215         GetBytesFromHexString(test, "cipher_text");
216
217     blink::WebCryptoKey key = ImportSecretKeyFromRaw(
218         test_key,
219         CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
220         blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt);
221
222     std::vector<uint8_t> output;
223
224     const unsigned int kAesCbcBlockSize = 16;
225
226     // Decrypt with a padding error by stripping the last block. This also ends
227     // up testing decryption over empty cipher text.
228     if (test_cipher_text.size() >= kAesCbcBlockSize) {
229       EXPECT_EQ(Status::OperationError(),
230                 Decrypt(CreateAesCbcAlgorithm(test_iv),
231                         key,
232                         CryptoData(&test_cipher_text[0],
233                                    test_cipher_text.size() - kAesCbcBlockSize),
234                         &output));
235     }
236
237     // Decrypt cipher text which is not a multiple of block size by stripping
238     // a few bytes off the cipher text.
239     if (test_cipher_text.size() > 3) {
240       EXPECT_EQ(
241           Status::OperationError(),
242           Decrypt(CreateAesCbcAlgorithm(test_iv),
243                   key,
244                   CryptoData(&test_cipher_text[0], test_cipher_text.size() - 3),
245                   &output));
246     }
247   }
248 }
249
250 // TODO(eroman): Do this same test for AES-GCM, AES-KW, AES-CTR ?
251 TEST(WebCryptoAesCbcTest, GenerateKeyIsRandom) {
252   // Check key generation for each allowed key length.
253   std::vector<blink::WebCryptoAlgorithm> algorithm;
254   const unsigned short kKeyLength[] = {128, 256};
255   for (size_t key_length_i = 0; key_length_i < arraysize(kKeyLength);
256        ++key_length_i) {
257     blink::WebCryptoKey key;
258
259     std::vector<std::vector<uint8_t> > keys;
260     std::vector<uint8_t> key_bytes;
261
262     // Generate a small sample of keys.
263     for (int j = 0; j < 16; ++j) {
264       ASSERT_EQ(Status::Success(),
265                 GenerateSecretKey(
266                     CreateAesCbcKeyGenAlgorithm(kKeyLength[key_length_i]),
267                     true,
268                     0,
269                     &key));
270       EXPECT_TRUE(key.handle());
271       EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type());
272       ASSERT_EQ(Status::Success(),
273                 ExportKey(blink::WebCryptoKeyFormatRaw, key, &key_bytes));
274       EXPECT_EQ(key_bytes.size() * 8,
275                 key.algorithm().aesParams()->lengthBits());
276       keys.push_back(key_bytes);
277     }
278     // Ensure all entries in the key sample set are unique. This is a simplistic
279     // estimate of whether the generated keys appear random.
280     EXPECT_FALSE(CopiesExist(keys));
281   }
282 }
283
284 TEST(WebCryptoAesCbcTest, GenerateKeyBadLength) {
285   const unsigned short kKeyLen[] = {0, 127, 257};
286   blink::WebCryptoKey key;
287   for (size_t i = 0; i < arraysize(kKeyLen); ++i) {
288     SCOPED_TRACE(i);
289     EXPECT_EQ(Status::ErrorGenerateKeyLength(),
290               GenerateSecretKey(
291                   CreateAesCbcKeyGenAlgorithm(kKeyLen[i]), true, 0, &key));
292   }
293 }
294
295 // If key_ops is specified but empty, no key usages are allowed for the key.
296 TEST(WebCryptoAesCbcTest, ImportKeyJwkEmptyKeyOps) {
297   blink::WebCryptoKey key;
298   base::DictionaryValue dict;
299   dict.SetString("kty", "oct");
300   dict.SetBoolean("ext", false);
301   dict.SetString("k", "GADWrMRHwQfoNaXU5fZvTg==");
302   dict.Set("key_ops", new base::ListValue);  // Takes ownership.
303
304   EXPECT_EQ(
305       Status::Success(),
306       ImportKeyJwkFromDict(dict,
307                            CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
308                            false,
309                            0,
310                            &key));
311
312   EXPECT_EQ(0, key.usages());
313
314   // The JWK does not contain encrypt usages.
315   EXPECT_EQ(
316       Status::ErrorJwkKeyopsInconsistent(),
317       ImportKeyJwkFromDict(dict,
318                            CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
319                            false,
320                            blink::WebCryptoKeyUsageEncrypt,
321                            &key));
322
323   // The JWK does not contain sign usage (nor is it applicable).
324   EXPECT_EQ(
325       Status::ErrorCreateKeyBadUsages(),
326       ImportKeyJwkFromDict(dict,
327                            CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
328                            false,
329                            blink::WebCryptoKeyUsageSign,
330                            &key));
331 }
332
333 // If key_ops is missing, then any key usages can be specified.
334 TEST(WebCryptoAesCbcTest, ImportKeyJwkNoKeyOps) {
335   blink::WebCryptoKey key;
336   base::DictionaryValue dict;
337   dict.SetString("kty", "oct");
338   dict.SetString("k", "GADWrMRHwQfoNaXU5fZvTg==");
339
340   EXPECT_EQ(
341       Status::Success(),
342       ImportKeyJwkFromDict(dict,
343                            CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
344                            false,
345                            blink::WebCryptoKeyUsageEncrypt,
346                            &key));
347
348   EXPECT_EQ(blink::WebCryptoKeyUsageEncrypt, key.usages());
349
350   // The JWK does not contain sign usage (nor is it applicable).
351   EXPECT_EQ(
352       Status::ErrorCreateKeyBadUsages(),
353       ImportKeyJwkFromDict(dict,
354                            CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
355                            false,
356                            blink::WebCryptoKeyUsageVerify,
357                            &key));
358 }
359
360 TEST(WebCryptoAesCbcTest, ImportKeyJwkKeyOpsEncryptDecrypt) {
361   blink::WebCryptoKey key;
362   base::DictionaryValue dict;
363   dict.SetString("kty", "oct");
364   dict.SetString("k", "GADWrMRHwQfoNaXU5fZvTg==");
365   base::ListValue* key_ops = new base::ListValue;
366   dict.Set("key_ops", key_ops);  // Takes ownership.
367
368   key_ops->AppendString("encrypt");
369
370   EXPECT_EQ(
371       Status::Success(),
372       ImportKeyJwkFromDict(dict,
373                            CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
374                            false,
375                            blink::WebCryptoKeyUsageEncrypt,
376                            &key));
377
378   EXPECT_EQ(blink::WebCryptoKeyUsageEncrypt, key.usages());
379
380   key_ops->AppendString("decrypt");
381
382   EXPECT_EQ(
383       Status::Success(),
384       ImportKeyJwkFromDict(dict,
385                            CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
386                            false,
387                            blink::WebCryptoKeyUsageDecrypt,
388                            &key));
389
390   EXPECT_EQ(blink::WebCryptoKeyUsageDecrypt, key.usages());
391
392   EXPECT_EQ(
393       Status::Success(),
394       ImportKeyJwkFromDict(
395           dict,
396           CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
397           false,
398           blink::WebCryptoKeyUsageDecrypt | blink::WebCryptoKeyUsageEncrypt,
399           &key));
400
401   EXPECT_EQ(blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt,
402             key.usages());
403 }
404
405 // Tests that importing a JWK containing duplicate key_ops values fails.
406 TEST(WebCryptoAesCbcTest, ImportKeyJwkDuplicateKeyOps) {
407   blink::WebCryptoKey key;
408   base::DictionaryValue dict;
409   dict.SetString("kty", "oct");
410   dict.SetString("k", "GADWrMRHwQfoNaXU5fZvTg==");
411   // key_ops will be owned by |dict|.
412   base::ListValue* key_ops = new base::ListValue;
413   dict.Set("key_ops", key_ops);
414
415   // The "encrypt" operation appears twice.
416   key_ops->AppendString("encrypt");
417   key_ops->AppendString("decrypt");
418   key_ops->AppendString("encrypt");
419
420   EXPECT_EQ(Status::ErrorJwkDuplicateKeyOps(),
421             ImportKeyJwkFromDict(
422                 dict, CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc), false,
423                 0, &key));
424 }
425
426 // Tests that importing a JWK containing duplicate key_ops values fails.
427 TEST(WebCryptoAesCbcTest, ImportKeyJwkDuplicateUnrecognizedKeyOps) {
428   blink::WebCryptoKey key;
429   base::DictionaryValue dict;
430   dict.SetString("kty", "oct");
431   dict.SetString("k", "GADWrMRHwQfoNaXU5fZvTg==");
432   // key_ops will be owned by |dict|.
433   base::ListValue* key_ops = new base::ListValue;
434   dict.Set("key_ops", key_ops);
435
436   // The (unknown) "foopy" operation appears twice.
437   key_ops->AppendString("foopy");
438   key_ops->AppendString("decrypt");
439   key_ops->AppendString("foopy");
440
441   EXPECT_EQ(Status::ErrorJwkDuplicateKeyOps(),
442             ImportKeyJwkFromDict(
443                 dict, CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc), false,
444                 0, &key));
445 }
446
447 // Test failure if input usage is NOT a strict subset of the JWK usage.
448 TEST(WebCryptoAesCbcTest, ImportKeyJwkKeyOpsNotSuperset) {
449   blink::WebCryptoKey key;
450   base::DictionaryValue dict;
451   dict.SetString("kty", "oct");
452   dict.SetString("k", "GADWrMRHwQfoNaXU5fZvTg==");
453   base::ListValue* key_ops = new base::ListValue;
454   dict.Set("key_ops", key_ops);  // Takes ownership.
455
456   key_ops->AppendString("encrypt");
457
458   EXPECT_EQ(
459       Status::ErrorJwkKeyopsInconsistent(),
460       ImportKeyJwkFromDict(
461           dict,
462           CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
463           false,
464           blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt,
465           &key));
466 }
467
468 TEST(WebCryptoAesCbcTest, ImportKeyJwkUseEnc) {
469   blink::WebCryptoKey key;
470   base::DictionaryValue dict;
471   dict.SetString("kty", "oct");
472   dict.SetString("k", "GADWrMRHwQfoNaXU5fZvTg==");
473
474   // Test JWK composite use 'enc' usage
475   dict.SetString("alg", "A128CBC");
476   dict.SetString("use", "enc");
477   EXPECT_EQ(
478       Status::Success(),
479       ImportKeyJwkFromDict(dict,
480                            CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
481                            false,
482                            blink::WebCryptoKeyUsageDecrypt |
483                                blink::WebCryptoKeyUsageEncrypt |
484                                blink::WebCryptoKeyUsageWrapKey |
485                                blink::WebCryptoKeyUsageUnwrapKey,
486                            &key));
487   EXPECT_EQ(blink::WebCryptoKeyUsageDecrypt | blink::WebCryptoKeyUsageEncrypt |
488                 blink::WebCryptoKeyUsageWrapKey |
489                 blink::WebCryptoKeyUsageUnwrapKey,
490             key.usages());
491 }
492
493 TEST(WebCryptoAesCbcTest, ImportJwkInvalidJson) {
494   blink::WebCryptoKey key;
495   // Fail on empty JSON.
496   EXPECT_EQ(Status::ErrorImportEmptyKeyData(),
497             ImportKey(blink::WebCryptoKeyFormatJwk,
498                       CryptoData(MakeJsonVector("")),
499                       CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
500                       false,
501                       blink::WebCryptoKeyUsageEncrypt,
502                       &key));
503
504   // Fail on invalid JSON.
505   const std::vector<uint8_t> bad_json_vec = MakeJsonVector(
506       "{"
507       "\"kty\"         : \"oct\","
508       "\"alg\"         : \"HS256\","
509       "\"use\"         : ");
510   EXPECT_EQ(Status::ErrorJwkNotDictionary(),
511             ImportKey(blink::WebCryptoKeyFormatJwk,
512                       CryptoData(bad_json_vec),
513                       CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
514                       false,
515                       blink::WebCryptoKeyUsageEncrypt,
516                       &key));
517 }
518
519 // Fail on JWK alg present but incorrect (expecting A128CBC).
520 TEST(WebCryptoAesCbcTest, ImportJwkIncorrectAlg) {
521   blink::WebCryptoKey key;
522
523   base::DictionaryValue dict;
524   dict.SetString("kty", "oct");
525   dict.SetString("alg", "A127CBC");  // Not valid.
526   dict.SetString("k", "GADWrMRHwQfoNaXU5fZvTg==");
527
528   EXPECT_EQ(
529       Status::ErrorJwkAlgorithmInconsistent(),
530       ImportKeyJwkFromDict(dict,
531                            CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
532                            false,
533                            blink::WebCryptoKeyUsageEncrypt,
534                            &key));
535 }
536
537 // Fail on invalid kty.
538 TEST(WebCryptoAesCbcTest, ImportJwkInvalidKty) {
539   blink::WebCryptoKey key;
540
541   base::DictionaryValue dict;
542   dict.SetString("kty", "foo");
543   dict.SetString("k", "GADWrMRHwQfoNaXU5fZvTg==");
544   EXPECT_EQ(
545       Status::ErrorJwkUnexpectedKty("oct"),
546       ImportKeyJwkFromDict(dict,
547                            CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
548                            false,
549                            blink::WebCryptoKeyUsageEncrypt,
550                            &key));
551 }
552
553 // Fail on missing kty.
554 TEST(WebCryptoAesCbcTest, ImportJwkMissingKty) {
555   blink::WebCryptoKey key;
556
557   base::DictionaryValue dict;
558   dict.SetString("k", "GADWrMRHwQfoNaXU5fZvTg==");
559   EXPECT_EQ(
560       Status::ErrorJwkPropertyMissing("kty"),
561       ImportKeyJwkFromDict(dict,
562                            CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
563                            false,
564                            blink::WebCryptoKeyUsageEncrypt,
565                            &key));
566 }
567
568 // Fail on kty wrong type.
569 TEST(WebCryptoAesCbcTest, ImportJwkKtyWrongType) {
570   blink::WebCryptoKey key;
571
572   base::DictionaryValue dict;
573   dict.SetDouble("kty", 0.1);
574   dict.SetString("k", "GADWrMRHwQfoNaXU5fZvTg==");
575
576   EXPECT_EQ(
577       Status::ErrorJwkPropertyWrongType("kty", "string"),
578       ImportKeyJwkFromDict(dict,
579                            CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
580                            false,
581                            blink::WebCryptoKeyUsageEncrypt,
582                            &key));
583 }
584
585 // Fail on invalid use.
586 TEST(WebCryptoAesCbcTest, ImportJwkUnrecognizedUse) {
587   blink::WebCryptoKey key;
588
589   base::DictionaryValue dict;
590   dict.SetString("kty", "oct");
591   dict.SetString("use", "foo");
592   dict.SetString("k", "GADWrMRHwQfoNaXU5fZvTg==");
593
594   EXPECT_EQ(
595       Status::ErrorJwkUnrecognizedUse(),
596       ImportKeyJwkFromDict(dict,
597                            CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
598                            false,
599                            blink::WebCryptoKeyUsageEncrypt,
600                            &key));
601 }
602
603 // Fail on invalid use (wrong type).
604 TEST(WebCryptoAesCbcTest, ImportJwkUseWrongType) {
605   blink::WebCryptoKey key;
606
607   base::DictionaryValue dict;
608   dict.SetString("kty", "oct");
609   dict.SetBoolean("use", true);
610   dict.SetString("k", "GADWrMRHwQfoNaXU5fZvTg==");
611
612   EXPECT_EQ(
613       Status::ErrorJwkPropertyWrongType("use", "string"),
614       ImportKeyJwkFromDict(dict,
615                            CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
616                            false,
617                            blink::WebCryptoKeyUsageEncrypt,
618                            &key));
619 }
620
621 // Fail on invalid extractable (wrong type).
622 TEST(WebCryptoAesCbcTest, ImportJwkExtWrongType) {
623   blink::WebCryptoKey key;
624
625   base::DictionaryValue dict;
626   dict.SetString("kty", "oct");
627   dict.SetInteger("ext", 0);
628   dict.SetString("k", "GADWrMRHwQfoNaXU5fZvTg==");
629
630   EXPECT_EQ(
631       Status::ErrorJwkPropertyWrongType("ext", "boolean"),
632       ImportKeyJwkFromDict(dict,
633                            CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
634                            false,
635                            blink::WebCryptoKeyUsageEncrypt,
636                            &key));
637 }
638
639 // Fail on invalid key_ops (wrong type).
640 TEST(WebCryptoAesCbcTest, ImportJwkKeyOpsWrongType) {
641   blink::WebCryptoKey key;
642
643   base::DictionaryValue dict;
644   dict.SetString("kty", "oct");
645   dict.SetString("k", "GADWrMRHwQfoNaXU5fZvTg==");
646   dict.SetBoolean("key_ops", true);
647
648   EXPECT_EQ(
649       Status::ErrorJwkPropertyWrongType("key_ops", "list"),
650       ImportKeyJwkFromDict(dict,
651                            CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
652                            false,
653                            blink::WebCryptoKeyUsageEncrypt,
654                            &key));
655 }
656
657 // Fail on inconsistent key_ops - asking for "encrypt" however JWK contains
658 // only "foo".
659 TEST(WebCryptoAesCbcTest, ImportJwkKeyOpsLacksUsages) {
660   blink::WebCryptoKey key;
661
662   base::DictionaryValue dict;
663   dict.SetString("kty", "oct");
664   dict.SetString("k", "GADWrMRHwQfoNaXU5fZvTg==");
665
666   base::ListValue* key_ops = new base::ListValue;
667   // Note: the following call makes dict assume ownership of key_ops.
668   dict.Set("key_ops", key_ops);
669   key_ops->AppendString("foo");
670   EXPECT_EQ(
671       Status::ErrorJwkKeyopsInconsistent(),
672       ImportKeyJwkFromDict(dict,
673                            CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
674                            false,
675                            blink::WebCryptoKeyUsageEncrypt,
676                            &key));
677 }
678
679 // Import a JWK with unrecognized values for "key_ops".
680 TEST(WebCryptoAesCbcTest, ImportJwkUnrecognizedKeyOps) {
681   blink::WebCryptoKey key;
682   blink::WebCryptoAlgorithm algorithm =
683       CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc);
684   blink::WebCryptoKeyUsageMask usages = blink::WebCryptoKeyUsageEncrypt;
685
686   base::DictionaryValue dict;
687   dict.SetString("kty", "oct");
688   dict.SetString("alg", "A128CBC");
689   dict.SetString("use", "enc");
690   dict.SetBoolean("ext", false);
691   dict.SetString("k", "GADWrMRHwQfoNaXU5fZvTg==");
692
693   base::ListValue* key_ops = new base::ListValue;
694   dict.Set("key_ops", key_ops);
695   key_ops->AppendString("foo");
696   key_ops->AppendString("bar");
697   key_ops->AppendString("baz");
698   key_ops->AppendString("encrypt");
699   EXPECT_EQ(Status::Success(),
700             ImportKeyJwkFromDict(dict, algorithm, false, usages, &key));
701 }
702
703 // Import a JWK with a value in key_ops array that is not a string.
704 TEST(WebCryptoAesCbcTest, ImportJwkNonStringKeyOp) {
705   blink::WebCryptoKey key;
706   blink::WebCryptoAlgorithm algorithm =
707       CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc);
708   blink::WebCryptoKeyUsageMask usages = blink::WebCryptoKeyUsageEncrypt;
709
710   base::DictionaryValue dict;
711   dict.SetString("kty", "oct");
712   dict.SetString("alg", "A128CBC");
713   dict.SetString("use", "enc");
714   dict.SetBoolean("ext", false);
715   dict.SetString("k", "GADWrMRHwQfoNaXU5fZvTg==");
716
717   base::ListValue* key_ops = new base::ListValue;
718   dict.Set("key_ops", key_ops);
719   key_ops->AppendString("encrypt");
720   key_ops->AppendInteger(3);
721   EXPECT_EQ(Status::ErrorJwkPropertyWrongType("key_ops[1]", "string"),
722             ImportKeyJwkFromDict(dict, algorithm, false, usages, &key));
723 }
724
725 // Fail on missing k.
726 TEST(WebCryptoAesCbcTest, ImportJwkMissingK) {
727   blink::WebCryptoKey key;
728
729   base::DictionaryValue dict;
730   dict.SetString("kty", "oct");
731
732   EXPECT_EQ(
733       Status::ErrorJwkPropertyMissing("k"),
734       ImportKeyJwkFromDict(dict,
735                            CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
736                            false,
737                            blink::WebCryptoKeyUsageEncrypt,
738                            &key));
739 }
740
741 // Fail on bad b64 encoding for k.
742 TEST(WebCryptoAesCbcTest, ImportJwkBadB64ForK) {
743   blink::WebCryptoKey key;
744
745   base::DictionaryValue dict;
746   dict.SetString("kty", "oct");
747   dict.SetString("k", "Qk3f0DsytU8lfza2au #$% Htaw2xpop9GYyTuH0p5GghxTI=");
748   EXPECT_EQ(
749       Status::ErrorJwkBase64Decode("k"),
750       ImportKeyJwkFromDict(dict,
751                            CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
752                            false,
753                            blink::WebCryptoKeyUsageEncrypt,
754                            &key));
755 }
756
757 // Fail on empty k.
758 TEST(WebCryptoAesCbcTest, ImportJwkEmptyK) {
759   blink::WebCryptoKey key;
760
761   base::DictionaryValue dict;
762   dict.SetString("kty", "oct");
763   dict.SetString("k", "");
764
765   EXPECT_EQ(
766       Status::ErrorImportAesKeyLength(),
767       ImportKeyJwkFromDict(dict,
768                            CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
769                            false,
770                            blink::WebCryptoKeyUsageEncrypt,
771                            &key));
772 }
773
774 // Fail on empty k (with alg specified).
775 TEST(WebCryptoAesCbcTest, ImportJwkEmptyK2) {
776   blink::WebCryptoKey key;
777
778   base::DictionaryValue dict;
779   dict.SetString("kty", "oct");
780   dict.SetString("alg", "A128CBC");
781   dict.SetString("k", "");
782
783   EXPECT_EQ(
784       Status::ErrorJwkIncorrectKeyLength(),
785       ImportKeyJwkFromDict(dict,
786                            CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
787                            false,
788                            blink::WebCryptoKeyUsageEncrypt,
789                            &key));
790 }
791
792 // Fail on k actual length (120 bits) inconsistent with the embedded JWK alg
793 // value (128) for an AES key.
794 TEST(WebCryptoAesCbcTest, ImportJwkInconsistentKLength) {
795   blink::WebCryptoKey key;
796
797   base::DictionaryValue dict;
798   dict.SetString("kty", "oct");
799   dict.SetString("alg", "A128CBC");
800   dict.SetString("k", "AVj42h0Y5aqGtE3yluKL");
801   EXPECT_EQ(
802       Status::ErrorJwkIncorrectKeyLength(),
803       ImportKeyJwkFromDict(dict,
804                            CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
805                            false,
806                            blink::WebCryptoKeyUsageEncrypt,
807                            &key));
808 }
809
810 // Fail on k actual length (192 bits) inconsistent with the embedded JWK alg
811 // value (128) for an AES key.
812 TEST(WebCryptoAesCbcTest, ImportJwkInconsistentKLength2) {
813   blink::WebCryptoKey key;
814
815   base::DictionaryValue dict;
816   dict.SetString("kty", "oct");
817   dict.SetString("alg", "A128CBC");
818   dict.SetString("k", "dGhpcyAgaXMgIDI0ICBieXRlcyBsb25n");
819   EXPECT_EQ(
820       Status::ErrorJwkIncorrectKeyLength(),
821       ImportKeyJwkFromDict(dict,
822                            CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
823                            false,
824                            blink::WebCryptoKeyUsageEncrypt,
825                            &key));
826 }
827
828 TEST(WebCryptoAesCbcTest, ImportExportJwk) {
829   const blink::WebCryptoAlgorithm algorithm =
830       CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc);
831
832   // AES-CBC 128
833   ImportExportJwkSymmetricKey(
834       128,
835       algorithm,
836       blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt,
837       "A128CBC");
838
839   // AES-CBC 256
840   ImportExportJwkSymmetricKey(
841       256, algorithm, blink::WebCryptoKeyUsageDecrypt, "A256CBC");
842
843   // Large usage value
844   ImportExportJwkSymmetricKey(
845       256,
846       algorithm,
847       blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt |
848           blink::WebCryptoKeyUsageWrapKey | blink::WebCryptoKeyUsageUnwrapKey,
849       "A256CBC");
850 }
851
852 // AES 192-bit is not allowed: http://crbug.com/381829
853 TEST(WebCryptoAesCbcTest, ImportAesCbc192Raw) {
854   std::vector<uint8_t> key_raw(24, 0);
855   blink::WebCryptoKey key;
856   Status status = ImportKey(blink::WebCryptoKeyFormatRaw,
857                             CryptoData(key_raw),
858                             CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
859                             true,
860                             blink::WebCryptoKeyUsageEncrypt,
861                             &key);
862   ASSERT_EQ(Status::ErrorAes192BitUnsupported(), status);
863 }
864
865 // AES 192-bit is not allowed: http://crbug.com/381829
866 TEST(WebCryptoAesCbcTest, ImportAesCbc192Jwk) {
867   blink::WebCryptoKey key;
868
869   base::DictionaryValue dict;
870   dict.SetString("kty", "oct");
871   dict.SetString("alg", "A192CBC");
872   dict.SetString("k", "YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFh");
873
874   EXPECT_EQ(
875       Status::ErrorAes192BitUnsupported(),
876       ImportKeyJwkFromDict(dict,
877                            CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
878                            false,
879                            blink::WebCryptoKeyUsageEncrypt,
880                            &key));
881 }
882
883 // AES 192-bit is not allowed: http://crbug.com/381829
884 TEST(WebCryptoAesCbcTest, GenerateAesCbc192) {
885   blink::WebCryptoKey key;
886   Status status = GenerateSecretKey(CreateAesCbcKeyGenAlgorithm(192),
887                                     true,
888                                     blink::WebCryptoKeyUsageEncrypt,
889                                     &key);
890   ASSERT_EQ(Status::ErrorAes192BitUnsupported(), status);
891 }
892
893 // AES 192-bit is not allowed: http://crbug.com/381829
894 TEST(WebCryptoAesCbcTest, UnwrapAesCbc192) {
895   std::vector<uint8_t> wrapping_key_data(16, 0);
896   std::vector<uint8_t> wrapped_key = HexStringToBytes(
897       "1A07ACAB6C906E50883173C29441DB1DE91D34F45C435B5F99C822867FB3956F");
898
899   blink::WebCryptoKey wrapping_key =
900       ImportSecretKeyFromRaw(wrapping_key_data,
901                              CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw),
902                              blink::WebCryptoKeyUsageUnwrapKey);
903
904   blink::WebCryptoKey unwrapped_key;
905   ASSERT_EQ(Status::ErrorAes192BitUnsupported(),
906             UnwrapKey(blink::WebCryptoKeyFormatRaw,
907                       CryptoData(wrapped_key),
908                       wrapping_key,
909                       CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw),
910                       CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
911                       true,
912                       blink::WebCryptoKeyUsageEncrypt,
913                       &unwrapped_key));
914 }
915
916 // Try importing an AES-CBC key with unsupported key usages using raw
917 // format. AES-CBC keys support the following usages:
918 //   'encrypt', 'decrypt', 'wrapKey', 'unwrapKey'
919 TEST(WebCryptoAesCbcTest, ImportKeyBadUsage_Raw) {
920   const blink::WebCryptoAlgorithm algorithm =
921       CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc);
922
923   blink::WebCryptoKeyUsageMask bad_usages[] = {
924       blink::WebCryptoKeyUsageSign,
925       blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageDecrypt,
926       blink::WebCryptoKeyUsageDeriveBits,
927       blink::WebCryptoKeyUsageUnwrapKey | blink::WebCryptoKeyUsageVerify,
928   };
929
930   std::vector<uint8_t> key_bytes(16);
931
932   for (size_t i = 0; i < arraysize(bad_usages); ++i) {
933     SCOPED_TRACE(i);
934
935     blink::WebCryptoKey key;
936     ASSERT_EQ(Status::ErrorCreateKeyBadUsages(),
937               ImportKey(blink::WebCryptoKeyFormatRaw,
938                         CryptoData(key_bytes),
939                         algorithm,
940                         true,
941                         bad_usages[i],
942                         &key));
943   }
944 }
945
946 // Generate an AES-CBC key with invalid usages. AES-CBC supports:
947 //   'encrypt', 'decrypt', 'wrapKey', 'unwrapKey'
948 TEST(WebCryptoAesCbcTest, GenerateKeyBadUsages) {
949   blink::WebCryptoKeyUsageMask bad_usages[] = {
950       blink::WebCryptoKeyUsageSign, blink::WebCryptoKeyUsageVerify,
951       blink::WebCryptoKeyUsageDecrypt | blink::WebCryptoKeyUsageVerify,
952   };
953
954   for (size_t i = 0; i < arraysize(bad_usages); ++i) {
955     SCOPED_TRACE(i);
956
957     blink::WebCryptoKey key;
958
959     ASSERT_EQ(Status::ErrorCreateKeyBadUsages(),
960               GenerateSecretKey(
961                   CreateAesCbcKeyGenAlgorithm(128), true, bad_usages[i], &key));
962   }
963 }
964
965 // Generate an AES-CBC key and an RSA key pair. Use the AES-CBC key to wrap the
966 // key pair (using SPKI format for public key, PKCS8 format for private key).
967 // Then unwrap the wrapped key pair and verify that the key data is the same.
968 TEST(WebCryptoAesCbcTest, WrapUnwrapRoundtripSpkiPkcs8) {
969   if (!SupportsRsaPrivateKeyImport())
970     return;
971
972   // Generate the wrapping key.
973   blink::WebCryptoKey wrapping_key;
974   ASSERT_EQ(Status::Success(),
975             GenerateSecretKey(CreateAesCbcKeyGenAlgorithm(128),
976                               true,
977                               blink::WebCryptoKeyUsageWrapKey |
978                                   blink::WebCryptoKeyUsageUnwrapKey,
979                               &wrapping_key));
980
981   // Generate an RSA key pair to be wrapped.
982   const unsigned int modulus_length = 256;
983   const std::vector<uint8_t> public_exponent = HexStringToBytes("010001");
984
985   blink::WebCryptoKey public_key;
986   blink::WebCryptoKey private_key;
987   ASSERT_EQ(Status::Success(),
988             GenerateKeyPair(CreateRsaHashedKeyGenAlgorithm(
989                                 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
990                                 blink::WebCryptoAlgorithmIdSha256,
991                                 modulus_length,
992                                 public_exponent),
993                             true,
994                             0,
995                             &public_key,
996                             &private_key));
997
998   // Export key pair as SPKI + PKCS8
999   std::vector<uint8_t> public_key_spki;
1000   ASSERT_EQ(
1001       Status::Success(),
1002       ExportKey(blink::WebCryptoKeyFormatSpki, public_key, &public_key_spki));
1003
1004   std::vector<uint8_t> private_key_pkcs8;
1005   ASSERT_EQ(
1006       Status::Success(),
1007       ExportKey(
1008           blink::WebCryptoKeyFormatPkcs8, private_key, &private_key_pkcs8));
1009
1010   // Wrap the key pair.
1011   blink::WebCryptoAlgorithm wrap_algorithm =
1012       CreateAesCbcAlgorithm(std::vector<uint8_t>(16, 0));
1013
1014   std::vector<uint8_t> wrapped_public_key;
1015   ASSERT_EQ(Status::Success(),
1016             WrapKey(blink::WebCryptoKeyFormatSpki,
1017                     public_key,
1018                     wrapping_key,
1019                     wrap_algorithm,
1020                     &wrapped_public_key));
1021
1022   std::vector<uint8_t> wrapped_private_key;
1023   ASSERT_EQ(Status::Success(),
1024             WrapKey(blink::WebCryptoKeyFormatPkcs8,
1025                     private_key,
1026                     wrapping_key,
1027                     wrap_algorithm,
1028                     &wrapped_private_key));
1029
1030   // Unwrap the key pair.
1031   blink::WebCryptoAlgorithm rsa_import_algorithm =
1032       CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
1033                                      blink::WebCryptoAlgorithmIdSha256);
1034
1035   blink::WebCryptoKey unwrapped_public_key;
1036
1037   ASSERT_EQ(Status::Success(),
1038             UnwrapKey(blink::WebCryptoKeyFormatSpki,
1039                       CryptoData(wrapped_public_key),
1040                       wrapping_key,
1041                       wrap_algorithm,
1042                       rsa_import_algorithm,
1043                       true,
1044                       0,
1045                       &unwrapped_public_key));
1046
1047   blink::WebCryptoKey unwrapped_private_key;
1048
1049   ASSERT_EQ(Status::Success(),
1050             UnwrapKey(blink::WebCryptoKeyFormatPkcs8,
1051                       CryptoData(wrapped_private_key),
1052                       wrapping_key,
1053                       wrap_algorithm,
1054                       rsa_import_algorithm,
1055                       true,
1056                       0,
1057                       &unwrapped_private_key));
1058
1059   // Export unwrapped key pair as SPKI + PKCS8
1060   std::vector<uint8_t> unwrapped_public_key_spki;
1061   ASSERT_EQ(Status::Success(),
1062             ExportKey(blink::WebCryptoKeyFormatSpki,
1063                       unwrapped_public_key,
1064                       &unwrapped_public_key_spki));
1065
1066   std::vector<uint8_t> unwrapped_private_key_pkcs8;
1067   ASSERT_EQ(Status::Success(),
1068             ExportKey(blink::WebCryptoKeyFormatPkcs8,
1069                       unwrapped_private_key,
1070                       &unwrapped_private_key_pkcs8));
1071
1072   EXPECT_EQ(public_key_spki, unwrapped_public_key_spki);
1073   EXPECT_EQ(private_key_pkcs8, unwrapped_private_key_pkcs8);
1074
1075   EXPECT_NE(public_key_spki, wrapped_public_key);
1076   EXPECT_NE(private_key_pkcs8, wrapped_private_key);
1077 }
1078
1079 }  // namespace
1080
1081 }  // namespace webcrypto
1082
1083 }  // namespace content