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
= blink::WebCryptoKey::createNull();
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
= blink::WebCryptoKey::createNull();
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_UNSAFE(kKeyLength
);
257 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
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
= blink::WebCryptoKey::createNull();
287 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(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
= blink::WebCryptoKey::createNull();
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
= blink::WebCryptoKey::createNull();
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
= blink::WebCryptoKey::createNull();
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 // Test failure if input usage is NOT a strict subset of the JWK usage.
406 TEST(WebCryptoAesCbcTest
, ImportKeyJwkKeyOpsNotSuperset
) {
407 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
408 base::DictionaryValue dict
;
409 dict
.SetString("kty", "oct");
410 dict
.SetString("k", "GADWrMRHwQfoNaXU5fZvTg==");
411 base::ListValue
* key_ops
= new base::ListValue
;
412 dict
.Set("key_ops", key_ops
); // Takes ownership.
414 key_ops
->AppendString("encrypt");
417 Status::ErrorJwkKeyopsInconsistent(),
418 ImportKeyJwkFromDict(
420 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc
),
422 blink::WebCryptoKeyUsageEncrypt
| blink::WebCryptoKeyUsageDecrypt
,
426 TEST(WebCryptoAesCbcTest
, ImportKeyJwkUseEnc
) {
427 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
428 base::DictionaryValue dict
;
429 dict
.SetString("kty", "oct");
430 dict
.SetString("k", "GADWrMRHwQfoNaXU5fZvTg==");
432 // Test JWK composite use 'enc' usage
433 dict
.SetString("alg", "A128CBC");
434 dict
.SetString("use", "enc");
437 ImportKeyJwkFromDict(dict
,
438 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc
),
440 blink::WebCryptoKeyUsageDecrypt
|
441 blink::WebCryptoKeyUsageEncrypt
|
442 blink::WebCryptoKeyUsageWrapKey
|
443 blink::WebCryptoKeyUsageUnwrapKey
,
445 EXPECT_EQ(blink::WebCryptoKeyUsageDecrypt
| blink::WebCryptoKeyUsageEncrypt
|
446 blink::WebCryptoKeyUsageWrapKey
|
447 blink::WebCryptoKeyUsageUnwrapKey
,
451 TEST(WebCryptoAesCbcTest
, ImportJwkInvalidJson
) {
452 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
453 // Fail on empty JSON.
454 EXPECT_EQ(Status::ErrorImportEmptyKeyData(),
455 ImportKey(blink::WebCryptoKeyFormatJwk
,
456 CryptoData(MakeJsonVector("")),
457 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc
),
459 blink::WebCryptoKeyUsageEncrypt
,
462 // Fail on invalid JSON.
463 const std::vector
<uint8_t> bad_json_vec
= MakeJsonVector(
466 "\"alg\" : \"HS256\","
468 EXPECT_EQ(Status::ErrorJwkNotDictionary(),
469 ImportKey(blink::WebCryptoKeyFormatJwk
,
470 CryptoData(bad_json_vec
),
471 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc
),
473 blink::WebCryptoKeyUsageEncrypt
,
477 // Fail on JWK alg present but incorrect (expecting A128CBC).
478 TEST(WebCryptoAesCbcTest
, ImportJwkIncorrectAlg
) {
479 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
481 base::DictionaryValue dict
;
482 dict
.SetString("kty", "oct");
483 dict
.SetString("alg", "A127CBC"); // Not valid.
484 dict
.SetString("k", "GADWrMRHwQfoNaXU5fZvTg==");
487 Status::ErrorJwkAlgorithmInconsistent(),
488 ImportKeyJwkFromDict(dict
,
489 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc
),
491 blink::WebCryptoKeyUsageEncrypt
,
495 // Fail on invalid kty.
496 TEST(WebCryptoAesCbcTest
, ImportJwkInvalidKty
) {
497 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
499 base::DictionaryValue dict
;
500 dict
.SetString("kty", "foo");
501 dict
.SetString("k", "GADWrMRHwQfoNaXU5fZvTg==");
503 Status::ErrorJwkUnexpectedKty("oct"),
504 ImportKeyJwkFromDict(dict
,
505 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc
),
507 blink::WebCryptoKeyUsageEncrypt
,
511 // Fail on missing kty.
512 TEST(WebCryptoAesCbcTest
, ImportJwkMissingKty
) {
513 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
515 base::DictionaryValue dict
;
516 dict
.SetString("k", "GADWrMRHwQfoNaXU5fZvTg==");
518 Status::ErrorJwkPropertyMissing("kty"),
519 ImportKeyJwkFromDict(dict
,
520 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc
),
522 blink::WebCryptoKeyUsageEncrypt
,
526 // Fail on kty wrong type.
527 TEST(WebCryptoAesCbcTest
, ImportJwkKtyWrongType
) {
528 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
530 base::DictionaryValue dict
;
531 dict
.SetDouble("kty", 0.1);
532 dict
.SetString("k", "GADWrMRHwQfoNaXU5fZvTg==");
535 Status::ErrorJwkPropertyWrongType("kty", "string"),
536 ImportKeyJwkFromDict(dict
,
537 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc
),
539 blink::WebCryptoKeyUsageEncrypt
,
543 // Fail on invalid use.
544 TEST(WebCryptoAesCbcTest
, ImportJwkUnrecognizedUse
) {
545 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
547 base::DictionaryValue dict
;
548 dict
.SetString("kty", "oct");
549 dict
.SetString("use", "foo");
550 dict
.SetString("k", "GADWrMRHwQfoNaXU5fZvTg==");
553 Status::ErrorJwkUnrecognizedUse(),
554 ImportKeyJwkFromDict(dict
,
555 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc
),
557 blink::WebCryptoKeyUsageEncrypt
,
561 // Fail on invalid use (wrong type).
562 TEST(WebCryptoAesCbcTest
, ImportJwkUseWrongType
) {
563 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
565 base::DictionaryValue dict
;
566 dict
.SetString("kty", "oct");
567 dict
.SetBoolean("use", true);
568 dict
.SetString("k", "GADWrMRHwQfoNaXU5fZvTg==");
571 Status::ErrorJwkPropertyWrongType("use", "string"),
572 ImportKeyJwkFromDict(dict
,
573 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc
),
575 blink::WebCryptoKeyUsageEncrypt
,
579 // Fail on invalid extractable (wrong type).
580 TEST(WebCryptoAesCbcTest
, ImportJwkExtWrongType
) {
581 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
583 base::DictionaryValue dict
;
584 dict
.SetString("kty", "oct");
585 dict
.SetInteger("ext", 0);
586 dict
.SetString("k", "GADWrMRHwQfoNaXU5fZvTg==");
589 Status::ErrorJwkPropertyWrongType("ext", "boolean"),
590 ImportKeyJwkFromDict(dict
,
591 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc
),
593 blink::WebCryptoKeyUsageEncrypt
,
597 // Fail on invalid key_ops (wrong type).
598 TEST(WebCryptoAesCbcTest
, ImportJwkKeyOpsWrongType
) {
599 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
601 base::DictionaryValue dict
;
602 dict
.SetString("kty", "oct");
603 dict
.SetString("k", "GADWrMRHwQfoNaXU5fZvTg==");
604 dict
.SetBoolean("key_ops", true);
607 Status::ErrorJwkPropertyWrongType("key_ops", "list"),
608 ImportKeyJwkFromDict(dict
,
609 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc
),
611 blink::WebCryptoKeyUsageEncrypt
,
615 // Fail on inconsistent key_ops - asking for "encrypt" however JWK contains
617 TEST(WebCryptoAesCbcTest
, ImportJwkKeyOpsLacksUsages
) {
618 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
620 base::DictionaryValue dict
;
621 dict
.SetString("kty", "oct");
622 dict
.SetString("k", "GADWrMRHwQfoNaXU5fZvTg==");
624 base::ListValue
* key_ops
= new base::ListValue
;
625 // Note: the following call makes dict assume ownership of key_ops.
626 dict
.Set("key_ops", key_ops
);
627 key_ops
->AppendString("foo");
629 Status::ErrorJwkKeyopsInconsistent(),
630 ImportKeyJwkFromDict(dict
,
631 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc
),
633 blink::WebCryptoKeyUsageEncrypt
,
637 // Import a JWK with unrecognized values for "key_ops".
638 TEST(WebCryptoAesCbcTest
, ImportJwkUnrecognizedKeyOps
) {
639 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
640 blink::WebCryptoAlgorithm algorithm
=
641 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc
);
642 blink::WebCryptoKeyUsageMask usage_mask
= blink::WebCryptoKeyUsageEncrypt
;
644 base::DictionaryValue dict
;
645 dict
.SetString("kty", "oct");
646 dict
.SetString("alg", "A128CBC");
647 dict
.SetString("use", "enc");
648 dict
.SetBoolean("ext", false);
649 dict
.SetString("k", "GADWrMRHwQfoNaXU5fZvTg==");
651 base::ListValue
* key_ops
= new base::ListValue
;
652 dict
.Set("key_ops", key_ops
);
653 key_ops
->AppendString("foo");
654 key_ops
->AppendString("bar");
655 key_ops
->AppendString("baz");
656 key_ops
->AppendString("encrypt");
657 EXPECT_EQ(Status::Success(),
658 ImportKeyJwkFromDict(dict
, algorithm
, false, usage_mask
, &key
));
661 // Import a JWK with a value in key_ops array that is not a string.
662 TEST(WebCryptoAesCbcTest
, ImportJwkNonStringKeyOp
) {
663 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
664 blink::WebCryptoAlgorithm algorithm
=
665 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc
);
666 blink::WebCryptoKeyUsageMask usage_mask
= blink::WebCryptoKeyUsageEncrypt
;
668 base::DictionaryValue dict
;
669 dict
.SetString("kty", "oct");
670 dict
.SetString("alg", "A128CBC");
671 dict
.SetString("use", "enc");
672 dict
.SetBoolean("ext", false);
673 dict
.SetString("k", "GADWrMRHwQfoNaXU5fZvTg==");
675 base::ListValue
* key_ops
= new base::ListValue
;
676 dict
.Set("key_ops", key_ops
);
677 key_ops
->AppendString("encrypt");
678 key_ops
->AppendInteger(3);
679 EXPECT_EQ(Status::ErrorJwkPropertyWrongType("key_ops[1]", "string"),
680 ImportKeyJwkFromDict(dict
, algorithm
, false, usage_mask
, &key
));
683 // Fail on missing k.
684 TEST(WebCryptoAesCbcTest
, ImportJwkMissingK
) {
685 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
687 base::DictionaryValue dict
;
688 dict
.SetString("kty", "oct");
691 Status::ErrorJwkPropertyMissing("k"),
692 ImportKeyJwkFromDict(dict
,
693 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc
),
695 blink::WebCryptoKeyUsageEncrypt
,
699 // Fail on bad b64 encoding for k.
700 TEST(WebCryptoAesCbcTest
, ImportJwkBadB64ForK
) {
701 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
703 base::DictionaryValue dict
;
704 dict
.SetString("kty", "oct");
705 dict
.SetString("k", "Qk3f0DsytU8lfza2au #$% Htaw2xpop9GYyTuH0p5GghxTI=");
707 Status::ErrorJwkBase64Decode("k"),
708 ImportKeyJwkFromDict(dict
,
709 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc
),
711 blink::WebCryptoKeyUsageEncrypt
,
716 TEST(WebCryptoAesCbcTest
, ImportJwkEmptyK
) {
717 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
719 base::DictionaryValue dict
;
720 dict
.SetString("kty", "oct");
721 dict
.SetString("k", "");
724 Status::ErrorImportAesKeyLength(),
725 ImportKeyJwkFromDict(dict
,
726 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc
),
728 blink::WebCryptoKeyUsageEncrypt
,
732 // Fail on empty k (with alg specified).
733 TEST(WebCryptoAesCbcTest
, ImportJwkEmptyK2
) {
734 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
736 base::DictionaryValue dict
;
737 dict
.SetString("kty", "oct");
738 dict
.SetString("alg", "A128CBC");
739 dict
.SetString("k", "");
742 Status::ErrorJwkIncorrectKeyLength(),
743 ImportKeyJwkFromDict(dict
,
744 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc
),
746 blink::WebCryptoKeyUsageEncrypt
,
750 // Fail on k actual length (120 bits) inconsistent with the embedded JWK alg
751 // value (128) for an AES key.
752 TEST(WebCryptoAesCbcTest
, ImportJwkInconsistentKLength
) {
753 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
755 base::DictionaryValue dict
;
756 dict
.SetString("kty", "oct");
757 dict
.SetString("alg", "A128CBC");
758 dict
.SetString("k", "AVj42h0Y5aqGtE3yluKL");
760 Status::ErrorJwkIncorrectKeyLength(),
761 ImportKeyJwkFromDict(dict
,
762 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc
),
764 blink::WebCryptoKeyUsageEncrypt
,
768 // Fail on k actual length (192 bits) inconsistent with the embedded JWK alg
769 // value (128) for an AES key.
770 TEST(WebCryptoAesCbcTest
, ImportJwkInconsistentKLength2
) {
771 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
773 base::DictionaryValue dict
;
774 dict
.SetString("kty", "oct");
775 dict
.SetString("alg", "A128CBC");
776 dict
.SetString("k", "dGhpcyAgaXMgIDI0ICBieXRlcyBsb25n");
778 Status::ErrorJwkIncorrectKeyLength(),
779 ImportKeyJwkFromDict(dict
,
780 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc
),
782 blink::WebCryptoKeyUsageEncrypt
,
786 TEST(WebCryptoAesCbcTest
, ImportExportJwk
) {
787 const blink::WebCryptoAlgorithm algorithm
=
788 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc
);
791 ImportExportJwkSymmetricKey(
794 blink::WebCryptoKeyUsageEncrypt
| blink::WebCryptoKeyUsageDecrypt
,
798 ImportExportJwkSymmetricKey(
799 256, algorithm
, blink::WebCryptoKeyUsageDecrypt
, "A256CBC");
802 ImportExportJwkSymmetricKey(
805 blink::WebCryptoKeyUsageEncrypt
| blink::WebCryptoKeyUsageDecrypt
|
806 blink::WebCryptoKeyUsageWrapKey
| blink::WebCryptoKeyUsageUnwrapKey
,
810 // AES 192-bit is not allowed: http://crbug.com/381829
811 TEST(WebCryptoAesCbcTest
, ImportAesCbc192Raw
) {
812 std::vector
<uint8_t> key_raw(24, 0);
813 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
814 Status status
= ImportKey(blink::WebCryptoKeyFormatRaw
,
816 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc
),
818 blink::WebCryptoKeyUsageEncrypt
,
820 ASSERT_EQ(Status::ErrorAes192BitUnsupported(), status
);
823 // AES 192-bit is not allowed: http://crbug.com/381829
824 TEST(WebCryptoAesCbcTest
, ImportAesCbc192Jwk
) {
825 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
827 base::DictionaryValue dict
;
828 dict
.SetString("kty", "oct");
829 dict
.SetString("alg", "A192CBC");
830 dict
.SetString("k", "YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFh");
833 Status::ErrorAes192BitUnsupported(),
834 ImportKeyJwkFromDict(dict
,
835 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc
),
837 blink::WebCryptoKeyUsageEncrypt
,
841 // AES 192-bit is not allowed: http://crbug.com/381829
842 TEST(WebCryptoAesCbcTest
, GenerateAesCbc192
) {
843 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
844 Status status
= GenerateSecretKey(CreateAesCbcKeyGenAlgorithm(192),
846 blink::WebCryptoKeyUsageEncrypt
,
848 ASSERT_EQ(Status::ErrorAes192BitUnsupported(), status
);
851 // AES 192-bit is not allowed: http://crbug.com/381829
852 TEST(WebCryptoAesCbcTest
, UnwrapAesCbc192
) {
853 std::vector
<uint8_t> wrapping_key_data(16, 0);
854 std::vector
<uint8_t> wrapped_key
= HexStringToBytes(
855 "1A07ACAB6C906E50883173C29441DB1DE91D34F45C435B5F99C822867FB3956F");
857 blink::WebCryptoKey wrapping_key
=
858 ImportSecretKeyFromRaw(wrapping_key_data
,
859 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw
),
860 blink::WebCryptoKeyUsageUnwrapKey
);
862 blink::WebCryptoKey unwrapped_key
= blink::WebCryptoKey::createNull();
863 ASSERT_EQ(Status::ErrorAes192BitUnsupported(),
864 UnwrapKey(blink::WebCryptoKeyFormatRaw
,
865 CryptoData(wrapped_key
),
867 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw
),
868 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc
),
870 blink::WebCryptoKeyUsageEncrypt
,
874 // Try importing an AES-CBC key with unsupported key usages using raw
875 // format. AES-CBC keys support the following usages:
876 // 'encrypt', 'decrypt', 'wrapKey', 'unwrapKey'
877 TEST(WebCryptoAesCbcTest
, ImportKeyBadUsage_Raw
) {
878 const blink::WebCryptoAlgorithm algorithm
=
879 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc
);
881 blink::WebCryptoKeyUsageMask bad_usages
[] = {
882 blink::WebCryptoKeyUsageSign
,
883 blink::WebCryptoKeyUsageSign
| blink::WebCryptoKeyUsageDecrypt
,
884 blink::WebCryptoKeyUsageDeriveBits
,
885 blink::WebCryptoKeyUsageUnwrapKey
| blink::WebCryptoKeyUsageVerify
,
888 std::vector
<uint8_t> key_bytes(16);
890 for (size_t i
= 0; i
< arraysize(bad_usages
); ++i
) {
893 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
894 ASSERT_EQ(Status::ErrorCreateKeyBadUsages(),
895 ImportKey(blink::WebCryptoKeyFormatRaw
,
896 CryptoData(key_bytes
),
904 // Generate an AES-CBC key with invalid usages. AES-CBC supports:
905 // 'encrypt', 'decrypt', 'wrapKey', 'unwrapKey'
906 TEST(WebCryptoAesCbcTest
, GenerateKeyBadUsages
) {
907 blink::WebCryptoKeyUsageMask bad_usages
[] = {
908 blink::WebCryptoKeyUsageSign
, blink::WebCryptoKeyUsageVerify
,
909 blink::WebCryptoKeyUsageDecrypt
| blink::WebCryptoKeyUsageVerify
,
912 for (size_t i
= 0; i
< arraysize(bad_usages
); ++i
) {
915 blink::WebCryptoKey key
= blink::WebCryptoKey::createNull();
917 ASSERT_EQ(Status::ErrorCreateKeyBadUsages(),
919 CreateAesCbcKeyGenAlgorithm(128), true, bad_usages
[i
], &key
));
923 // Generate an AES-CBC key and an RSA key pair. Use the AES-CBC key to wrap the
924 // key pair (using SPKI format for public key, PKCS8 format for private key).
925 // Then unwrap the wrapped key pair and verify that the key data is the same.
926 TEST(WebCryptoAesCbcTest
, WrapUnwrapRoundtripSpkiPkcs8
) {
927 if (!SupportsRsaPrivateKeyImport())
930 // Generate the wrapping key.
931 blink::WebCryptoKey wrapping_key
= blink::WebCryptoKey::createNull();
932 ASSERT_EQ(Status::Success(),
933 GenerateSecretKey(CreateAesCbcKeyGenAlgorithm(128),
935 blink::WebCryptoKeyUsageWrapKey
|
936 blink::WebCryptoKeyUsageUnwrapKey
,
939 // Generate an RSA key pair to be wrapped.
940 const unsigned int modulus_length
= 256;
941 const std::vector
<uint8_t> public_exponent
= HexStringToBytes("010001");
943 blink::WebCryptoKey public_key
= blink::WebCryptoKey::createNull();
944 blink::WebCryptoKey private_key
= blink::WebCryptoKey::createNull();
945 ASSERT_EQ(Status::Success(),
946 GenerateKeyPair(CreateRsaHashedKeyGenAlgorithm(
947 blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
948 blink::WebCryptoAlgorithmIdSha256
,
956 // Export key pair as SPKI + PKCS8
957 std::vector
<uint8_t> public_key_spki
;
960 ExportKey(blink::WebCryptoKeyFormatSpki
, public_key
, &public_key_spki
));
962 std::vector
<uint8_t> private_key_pkcs8
;
966 blink::WebCryptoKeyFormatPkcs8
, private_key
, &private_key_pkcs8
));
968 // Wrap the key pair.
969 blink::WebCryptoAlgorithm wrap_algorithm
=
970 CreateAesCbcAlgorithm(std::vector
<uint8_t>(16, 0));
972 std::vector
<uint8_t> wrapped_public_key
;
973 ASSERT_EQ(Status::Success(),
974 WrapKey(blink::WebCryptoKeyFormatSpki
,
978 &wrapped_public_key
));
980 std::vector
<uint8_t> wrapped_private_key
;
981 ASSERT_EQ(Status::Success(),
982 WrapKey(blink::WebCryptoKeyFormatPkcs8
,
986 &wrapped_private_key
));
988 // Unwrap the key pair.
989 blink::WebCryptoAlgorithm rsa_import_algorithm
=
990 CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5
,
991 blink::WebCryptoAlgorithmIdSha256
);
993 blink::WebCryptoKey unwrapped_public_key
= blink::WebCryptoKey::createNull();
995 ASSERT_EQ(Status::Success(),
996 UnwrapKey(blink::WebCryptoKeyFormatSpki
,
997 CryptoData(wrapped_public_key
),
1000 rsa_import_algorithm
,
1003 &unwrapped_public_key
));
1005 blink::WebCryptoKey unwrapped_private_key
= blink::WebCryptoKey::createNull();
1007 ASSERT_EQ(Status::Success(),
1008 UnwrapKey(blink::WebCryptoKeyFormatPkcs8
,
1009 CryptoData(wrapped_private_key
),
1012 rsa_import_algorithm
,
1015 &unwrapped_private_key
));
1017 // Export unwrapped key pair as SPKI + PKCS8
1018 std::vector
<uint8_t> unwrapped_public_key_spki
;
1019 ASSERT_EQ(Status::Success(),
1020 ExportKey(blink::WebCryptoKeyFormatSpki
,
1021 unwrapped_public_key
,
1022 &unwrapped_public_key_spki
));
1024 std::vector
<uint8_t> unwrapped_private_key_pkcs8
;
1025 ASSERT_EQ(Status::Success(),
1026 ExportKey(blink::WebCryptoKeyFormatPkcs8
,
1027 unwrapped_private_key
,
1028 &unwrapped_private_key_pkcs8
));
1030 EXPECT_EQ(public_key_spki
, unwrapped_public_key_spki
);
1031 EXPECT_EQ(private_key_pkcs8
, unwrapped_private_key_pkcs8
);
1033 EXPECT_NE(public_key_spki
, wrapped_public_key
);
1034 EXPECT_NE(private_key_pkcs8
, wrapped_private_key
);
1039 } // namespace webcrypto
1041 } // namespace content