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.
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"
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()));
28 blink::WebCryptoAlgorithm CreateAesCbcKeyGenAlgorithm(
29 unsigned short key_length_bits) {
30 return CreateAesKeyGenAlgorithm(blink::WebCryptoAlgorithmIdAesCbc,
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);
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);
49 TEST(WebCryptoAesCbcTest, IvTooSmall) {
50 std::vector<uint8_t> output;
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),
60 EXPECT_EQ(Status::ErrorIncorrectSizeAesCbcIv(),
61 Decrypt(CreateAesCbcAlgorithm(iv),
67 TEST(WebCryptoAesCbcTest, IvTooLarge) {
68 std::vector<uint8_t> output;
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),
78 EXPECT_EQ(Status::ErrorIncorrectSizeAesCbcIv(),
79 Decrypt(CreateAesCbcAlgorithm(iv),
85 TEST(WebCryptoAesCbcTest, InputTooLarge) {
86 std::vector<uint8_t> output;
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
91 std::vector<uint8_t> iv(16);
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
96 CryptoData input(&iv[0], INT_MAX - 3);
99 Status::ErrorDataTooLarge(),
100 Encrypt(CreateAesCbcAlgorithm(iv), GetTestAesCbcKey(), input, &output));
102 Status::ErrorDataTooLarge(),
103 Decrypt(CreateAesCbcAlgorithm(iv), GetTestAesCbcKey(), input, &output));
106 TEST(WebCryptoAesCbcTest, KeyTooSmall) {
107 std::vector<uint8_t> output;
109 // Fail importing the key (too few bytes specified)
110 std::vector<uint8_t> key_raw(1);
111 std::vector<uint8_t> iv(16);
113 blink::WebCryptoKey key;
114 EXPECT_EQ(Status::ErrorImportAesKeyLength(),
115 ImportKey(blink::WebCryptoKeyFormatRaw,
117 CreateAesCbcAlgorithm(iv),
119 blink::WebCryptoKeyUsageEncrypt,
123 TEST(WebCryptoAesCbcTest, ExportKeyUnsupportedFormat) {
124 std::vector<uint8_t> output;
126 // Fail exporting the key in SPKI and PKCS#8 formats (not allowed for secret
129 Status::ErrorUnsupportedExportKeyFormat(),
130 ExportKey(blink::WebCryptoKeyFormatSpki, GetTestAesCbcKey(), &output));
132 Status::ErrorUnsupportedExportKeyFormat(),
133 ExportKey(blink::WebCryptoKeyFormatPkcs8, GetTestAesCbcKey(), &output));
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),
143 blink::WebCryptoKeyUsageEncrypt,
145 ASSERT_EQ(Status::ErrorUnsupportedImportKeyFormat(),
146 ImportKey(blink::WebCryptoKeyFormatPkcs8,
147 CryptoData(HexStringToBytes(kPublicKeySpkiDerHex)),
148 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
150 blink::WebCryptoKeyUsageEncrypt,
154 TEST(WebCryptoAesCbcTest, KnownAnswerEncryptDecrypt) {
155 scoped_ptr<base::ListValue> tests;
156 ASSERT_TRUE(ReadJsonTestFileToList("aes_cbc.json", &tests));
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));
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");
170 blink::WebCryptoKey key = ImportSecretKeyFromRaw(
172 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
173 blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt);
175 EXPECT_EQ(test_key.size() * 8, key.algorithm().aesParams()->lengthBits());
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);
183 std::vector<uint8_t> output;
186 EXPECT_EQ(Status::Success(),
187 Encrypt(CreateAesCbcAlgorithm(test_iv),
189 CryptoData(test_plain_text),
191 EXPECT_BYTES_EQ(test_cipher_text, output);
194 EXPECT_EQ(Status::Success(),
195 Decrypt(CreateAesCbcAlgorithm(test_iv),
197 CryptoData(test_cipher_text),
199 EXPECT_BYTES_EQ(test_plain_text, output);
203 TEST(WebCryptoAesCbcTest, DecryptTruncatedCipherText) {
204 scoped_ptr<base::ListValue> tests;
205 ASSERT_TRUE(ReadJsonTestFileToList("aes_cbc.json", &tests));
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));
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");
217 blink::WebCryptoKey key = ImportSecretKeyFromRaw(
219 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
220 blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt);
222 std::vector<uint8_t> output;
224 const unsigned int kAesCbcBlockSize = 16;
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),
232 CryptoData(&test_cipher_text[0],
233 test_cipher_text.size() - kAesCbcBlockSize),
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) {
241 Status::OperationError(),
242 Decrypt(CreateAesCbcAlgorithm(test_iv),
244 CryptoData(&test_cipher_text[0], test_cipher_text.size() - 3),
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);
257 blink::WebCryptoKey key;
259 std::vector<std::vector<uint8_t> > keys;
260 std::vector<uint8_t> key_bytes;
262 // Generate a small sample of keys.
263 for (int j = 0; j < 16; ++j) {
264 ASSERT_EQ(Status::Success(),
266 CreateAesCbcKeyGenAlgorithm(kKeyLength[key_length_i]),
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);
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));
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) {
289 EXPECT_EQ(Status::ErrorGenerateKeyLength(),
291 CreateAesCbcKeyGenAlgorithm(kKeyLen[i]), true, 0, &key));
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.
306 ImportKeyJwkFromDict(dict,
307 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
312 EXPECT_EQ(0, key.usages());
314 // The JWK does not contain encrypt usages.
316 Status::ErrorJwkKeyopsInconsistent(),
317 ImportKeyJwkFromDict(dict,
318 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
320 blink::WebCryptoKeyUsageEncrypt,
323 // The JWK does not contain sign usage (nor is it applicable).
325 Status::ErrorCreateKeyBadUsages(),
326 ImportKeyJwkFromDict(dict,
327 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
329 blink::WebCryptoKeyUsageSign,
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==");
342 ImportKeyJwkFromDict(dict,
343 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
345 blink::WebCryptoKeyUsageEncrypt,
348 EXPECT_EQ(blink::WebCryptoKeyUsageEncrypt, key.usages());
350 // The JWK does not contain sign usage (nor is it applicable).
352 Status::ErrorCreateKeyBadUsages(),
353 ImportKeyJwkFromDict(dict,
354 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
356 blink::WebCryptoKeyUsageVerify,
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.
368 key_ops->AppendString("encrypt");
372 ImportKeyJwkFromDict(dict,
373 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
375 blink::WebCryptoKeyUsageEncrypt,
378 EXPECT_EQ(blink::WebCryptoKeyUsageEncrypt, key.usages());
380 key_ops->AppendString("decrypt");
384 ImportKeyJwkFromDict(dict,
385 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
387 blink::WebCryptoKeyUsageDecrypt,
390 EXPECT_EQ(blink::WebCryptoKeyUsageDecrypt, key.usages());
394 ImportKeyJwkFromDict(
396 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
398 blink::WebCryptoKeyUsageDecrypt | blink::WebCryptoKeyUsageEncrypt,
401 EXPECT_EQ(blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt,
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);
415 // The "encrypt" operation appears twice.
416 key_ops->AppendString("encrypt");
417 key_ops->AppendString("decrypt");
418 key_ops->AppendString("encrypt");
420 EXPECT_EQ(Status::ErrorJwkDuplicateKeyOps(),
421 ImportKeyJwkFromDict(
422 dict, CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc), false,
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);
436 // The (unknown) "foopy" operation appears twice.
437 key_ops->AppendString("foopy");
438 key_ops->AppendString("decrypt");
439 key_ops->AppendString("foopy");
441 EXPECT_EQ(Status::ErrorJwkDuplicateKeyOps(),
442 ImportKeyJwkFromDict(
443 dict, CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc), false,
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.
456 key_ops->AppendString("encrypt");
459 Status::ErrorJwkKeyopsInconsistent(),
460 ImportKeyJwkFromDict(
462 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
464 blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt,
468 TEST(WebCryptoAesCbcTest, ImportKeyJwkUseEnc) {
469 blink::WebCryptoKey key;
470 base::DictionaryValue dict;
471 dict.SetString("kty", "oct");
472 dict.SetString("k", "GADWrMRHwQfoNaXU5fZvTg==");
474 // Test JWK composite use 'enc' usage
475 dict.SetString("alg", "A128CBC");
476 dict.SetString("use", "enc");
479 ImportKeyJwkFromDict(dict,
480 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
482 blink::WebCryptoKeyUsageDecrypt |
483 blink::WebCryptoKeyUsageEncrypt |
484 blink::WebCryptoKeyUsageWrapKey |
485 blink::WebCryptoKeyUsageUnwrapKey,
487 EXPECT_EQ(blink::WebCryptoKeyUsageDecrypt | blink::WebCryptoKeyUsageEncrypt |
488 blink::WebCryptoKeyUsageWrapKey |
489 blink::WebCryptoKeyUsageUnwrapKey,
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),
501 blink::WebCryptoKeyUsageEncrypt,
504 // Fail on invalid JSON.
505 const std::vector<uint8_t> bad_json_vec = MakeJsonVector(
508 "\"alg\" : \"HS256\","
510 EXPECT_EQ(Status::ErrorJwkNotDictionary(),
511 ImportKey(blink::WebCryptoKeyFormatJwk,
512 CryptoData(bad_json_vec),
513 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
515 blink::WebCryptoKeyUsageEncrypt,
519 // Fail on JWK alg present but incorrect (expecting A128CBC).
520 TEST(WebCryptoAesCbcTest, ImportJwkIncorrectAlg) {
521 blink::WebCryptoKey key;
523 base::DictionaryValue dict;
524 dict.SetString("kty", "oct");
525 dict.SetString("alg", "A127CBC"); // Not valid.
526 dict.SetString("k", "GADWrMRHwQfoNaXU5fZvTg==");
529 Status::ErrorJwkAlgorithmInconsistent(),
530 ImportKeyJwkFromDict(dict,
531 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
533 blink::WebCryptoKeyUsageEncrypt,
537 // Fail on invalid kty.
538 TEST(WebCryptoAesCbcTest, ImportJwkInvalidKty) {
539 blink::WebCryptoKey key;
541 base::DictionaryValue dict;
542 dict.SetString("kty", "foo");
543 dict.SetString("k", "GADWrMRHwQfoNaXU5fZvTg==");
545 Status::ErrorJwkUnexpectedKty("oct"),
546 ImportKeyJwkFromDict(dict,
547 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
549 blink::WebCryptoKeyUsageEncrypt,
553 // Fail on missing kty.
554 TEST(WebCryptoAesCbcTest, ImportJwkMissingKty) {
555 blink::WebCryptoKey key;
557 base::DictionaryValue dict;
558 dict.SetString("k", "GADWrMRHwQfoNaXU5fZvTg==");
560 Status::ErrorJwkPropertyMissing("kty"),
561 ImportKeyJwkFromDict(dict,
562 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
564 blink::WebCryptoKeyUsageEncrypt,
568 // Fail on kty wrong type.
569 TEST(WebCryptoAesCbcTest, ImportJwkKtyWrongType) {
570 blink::WebCryptoKey key;
572 base::DictionaryValue dict;
573 dict.SetDouble("kty", 0.1);
574 dict.SetString("k", "GADWrMRHwQfoNaXU5fZvTg==");
577 Status::ErrorJwkPropertyWrongType("kty", "string"),
578 ImportKeyJwkFromDict(dict,
579 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
581 blink::WebCryptoKeyUsageEncrypt,
585 // Fail on invalid use.
586 TEST(WebCryptoAesCbcTest, ImportJwkUnrecognizedUse) {
587 blink::WebCryptoKey key;
589 base::DictionaryValue dict;
590 dict.SetString("kty", "oct");
591 dict.SetString("use", "foo");
592 dict.SetString("k", "GADWrMRHwQfoNaXU5fZvTg==");
595 Status::ErrorJwkUnrecognizedUse(),
596 ImportKeyJwkFromDict(dict,
597 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
599 blink::WebCryptoKeyUsageEncrypt,
603 // Fail on invalid use (wrong type).
604 TEST(WebCryptoAesCbcTest, ImportJwkUseWrongType) {
605 blink::WebCryptoKey key;
607 base::DictionaryValue dict;
608 dict.SetString("kty", "oct");
609 dict.SetBoolean("use", true);
610 dict.SetString("k", "GADWrMRHwQfoNaXU5fZvTg==");
613 Status::ErrorJwkPropertyWrongType("use", "string"),
614 ImportKeyJwkFromDict(dict,
615 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
617 blink::WebCryptoKeyUsageEncrypt,
621 // Fail on invalid extractable (wrong type).
622 TEST(WebCryptoAesCbcTest, ImportJwkExtWrongType) {
623 blink::WebCryptoKey key;
625 base::DictionaryValue dict;
626 dict.SetString("kty", "oct");
627 dict.SetInteger("ext", 0);
628 dict.SetString("k", "GADWrMRHwQfoNaXU5fZvTg==");
631 Status::ErrorJwkPropertyWrongType("ext", "boolean"),
632 ImportKeyJwkFromDict(dict,
633 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
635 blink::WebCryptoKeyUsageEncrypt,
639 // Fail on invalid key_ops (wrong type).
640 TEST(WebCryptoAesCbcTest, ImportJwkKeyOpsWrongType) {
641 blink::WebCryptoKey key;
643 base::DictionaryValue dict;
644 dict.SetString("kty", "oct");
645 dict.SetString("k", "GADWrMRHwQfoNaXU5fZvTg==");
646 dict.SetBoolean("key_ops", true);
649 Status::ErrorJwkPropertyWrongType("key_ops", "list"),
650 ImportKeyJwkFromDict(dict,
651 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
653 blink::WebCryptoKeyUsageEncrypt,
657 // Fail on inconsistent key_ops - asking for "encrypt" however JWK contains
659 TEST(WebCryptoAesCbcTest, ImportJwkKeyOpsLacksUsages) {
660 blink::WebCryptoKey key;
662 base::DictionaryValue dict;
663 dict.SetString("kty", "oct");
664 dict.SetString("k", "GADWrMRHwQfoNaXU5fZvTg==");
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");
671 Status::ErrorJwkKeyopsInconsistent(),
672 ImportKeyJwkFromDict(dict,
673 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
675 blink::WebCryptoKeyUsageEncrypt,
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;
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==");
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));
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;
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==");
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));
725 // Fail on missing k.
726 TEST(WebCryptoAesCbcTest, ImportJwkMissingK) {
727 blink::WebCryptoKey key;
729 base::DictionaryValue dict;
730 dict.SetString("kty", "oct");
733 Status::ErrorJwkPropertyMissing("k"),
734 ImportKeyJwkFromDict(dict,
735 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
737 blink::WebCryptoKeyUsageEncrypt,
741 // Fail on bad b64 encoding for k.
742 TEST(WebCryptoAesCbcTest, ImportJwkBadB64ForK) {
743 blink::WebCryptoKey key;
745 base::DictionaryValue dict;
746 dict.SetString("kty", "oct");
747 dict.SetString("k", "Qk3f0DsytU8lfza2au #$% Htaw2xpop9GYyTuH0p5GghxTI=");
749 Status::ErrorJwkBase64Decode("k"),
750 ImportKeyJwkFromDict(dict,
751 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
753 blink::WebCryptoKeyUsageEncrypt,
758 TEST(WebCryptoAesCbcTest, ImportJwkEmptyK) {
759 blink::WebCryptoKey key;
761 base::DictionaryValue dict;
762 dict.SetString("kty", "oct");
763 dict.SetString("k", "");
766 Status::ErrorImportAesKeyLength(),
767 ImportKeyJwkFromDict(dict,
768 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
770 blink::WebCryptoKeyUsageEncrypt,
774 // Fail on empty k (with alg specified).
775 TEST(WebCryptoAesCbcTest, ImportJwkEmptyK2) {
776 blink::WebCryptoKey key;
778 base::DictionaryValue dict;
779 dict.SetString("kty", "oct");
780 dict.SetString("alg", "A128CBC");
781 dict.SetString("k", "");
784 Status::ErrorJwkIncorrectKeyLength(),
785 ImportKeyJwkFromDict(dict,
786 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
788 blink::WebCryptoKeyUsageEncrypt,
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;
797 base::DictionaryValue dict;
798 dict.SetString("kty", "oct");
799 dict.SetString("alg", "A128CBC");
800 dict.SetString("k", "AVj42h0Y5aqGtE3yluKL");
802 Status::ErrorJwkIncorrectKeyLength(),
803 ImportKeyJwkFromDict(dict,
804 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
806 blink::WebCryptoKeyUsageEncrypt,
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;
815 base::DictionaryValue dict;
816 dict.SetString("kty", "oct");
817 dict.SetString("alg", "A128CBC");
818 dict.SetString("k", "dGhpcyAgaXMgIDI0ICBieXRlcyBsb25n");
820 Status::ErrorJwkIncorrectKeyLength(),
821 ImportKeyJwkFromDict(dict,
822 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
824 blink::WebCryptoKeyUsageEncrypt,
828 TEST(WebCryptoAesCbcTest, ImportExportJwk) {
829 const blink::WebCryptoAlgorithm algorithm =
830 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc);
833 ImportExportJwkSymmetricKey(
836 blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt,
840 ImportExportJwkSymmetricKey(
841 256, algorithm, blink::WebCryptoKeyUsageDecrypt, "A256CBC");
844 ImportExportJwkSymmetricKey(
847 blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt |
848 blink::WebCryptoKeyUsageWrapKey | blink::WebCryptoKeyUsageUnwrapKey,
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,
858 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
860 blink::WebCryptoKeyUsageEncrypt,
862 ASSERT_EQ(Status::ErrorAes192BitUnsupported(), status);
865 // AES 192-bit is not allowed: http://crbug.com/381829
866 TEST(WebCryptoAesCbcTest, ImportAesCbc192Jwk) {
867 blink::WebCryptoKey key;
869 base::DictionaryValue dict;
870 dict.SetString("kty", "oct");
871 dict.SetString("alg", "A192CBC");
872 dict.SetString("k", "YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFh");
875 Status::ErrorAes192BitUnsupported(),
876 ImportKeyJwkFromDict(dict,
877 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
879 blink::WebCryptoKeyUsageEncrypt,
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),
888 blink::WebCryptoKeyUsageEncrypt,
890 ASSERT_EQ(Status::ErrorAes192BitUnsupported(), status);
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");
899 blink::WebCryptoKey wrapping_key =
900 ImportSecretKeyFromRaw(wrapping_key_data,
901 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw),
902 blink::WebCryptoKeyUsageUnwrapKey);
904 blink::WebCryptoKey unwrapped_key;
905 ASSERT_EQ(Status::ErrorAes192BitUnsupported(),
906 UnwrapKey(blink::WebCryptoKeyFormatRaw,
907 CryptoData(wrapped_key),
909 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw),
910 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
912 blink::WebCryptoKeyUsageEncrypt,
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);
923 blink::WebCryptoKeyUsageMask bad_usages[] = {
924 blink::WebCryptoKeyUsageSign,
925 blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageDecrypt,
926 blink::WebCryptoKeyUsageDeriveBits,
927 blink::WebCryptoKeyUsageUnwrapKey | blink::WebCryptoKeyUsageVerify,
930 std::vector<uint8_t> key_bytes(16);
932 for (size_t i = 0; i < arraysize(bad_usages); ++i) {
935 blink::WebCryptoKey key;
936 ASSERT_EQ(Status::ErrorCreateKeyBadUsages(),
937 ImportKey(blink::WebCryptoKeyFormatRaw,
938 CryptoData(key_bytes),
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,
954 for (size_t i = 0; i < arraysize(bad_usages); ++i) {
957 blink::WebCryptoKey key;
959 ASSERT_EQ(Status::ErrorCreateKeyBadUsages(),
961 CreateAesCbcKeyGenAlgorithm(128), true, bad_usages[i], &key));
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())
972 // Generate the wrapping key.
973 blink::WebCryptoKey wrapping_key;
974 ASSERT_EQ(Status::Success(),
975 GenerateSecretKey(CreateAesCbcKeyGenAlgorithm(128),
977 blink::WebCryptoKeyUsageWrapKey |
978 blink::WebCryptoKeyUsageUnwrapKey,
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");
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,
998 // Export key pair as SPKI + PKCS8
999 std::vector<uint8_t> public_key_spki;
1002 ExportKey(blink::WebCryptoKeyFormatSpki, public_key, &public_key_spki));
1004 std::vector<uint8_t> private_key_pkcs8;
1008 blink::WebCryptoKeyFormatPkcs8, private_key, &private_key_pkcs8));
1010 // Wrap the key pair.
1011 blink::WebCryptoAlgorithm wrap_algorithm =
1012 CreateAesCbcAlgorithm(std::vector<uint8_t>(16, 0));
1014 std::vector<uint8_t> wrapped_public_key;
1015 ASSERT_EQ(Status::Success(),
1016 WrapKey(blink::WebCryptoKeyFormatSpki,
1020 &wrapped_public_key));
1022 std::vector<uint8_t> wrapped_private_key;
1023 ASSERT_EQ(Status::Success(),
1024 WrapKey(blink::WebCryptoKeyFormatPkcs8,
1028 &wrapped_private_key));
1030 // Unwrap the key pair.
1031 blink::WebCryptoAlgorithm rsa_import_algorithm =
1032 CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
1033 blink::WebCryptoAlgorithmIdSha256);
1035 blink::WebCryptoKey unwrapped_public_key;
1037 ASSERT_EQ(Status::Success(),
1038 UnwrapKey(blink::WebCryptoKeyFormatSpki,
1039 CryptoData(wrapped_public_key),
1042 rsa_import_algorithm,
1045 &unwrapped_public_key));
1047 blink::WebCryptoKey unwrapped_private_key;
1049 ASSERT_EQ(Status::Success(),
1050 UnwrapKey(blink::WebCryptoKeyFormatPkcs8,
1051 CryptoData(wrapped_private_key),
1054 rsa_import_algorithm,
1057 &unwrapped_private_key));
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));
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));
1072 EXPECT_EQ(public_key_spki, unwrapped_public_key_spki);
1073 EXPECT_EQ(private_key_pkcs8, unwrapped_private_key_pkcs8);
1075 EXPECT_NE(public_key_spki, wrapped_public_key);
1076 EXPECT_NE(private_key_pkcs8, wrapped_private_key);
1081 } // namespace webcrypto
1083 } // namespace content