Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / content / child / webcrypto / test / aes_cbc_unittest.cc
bloba0112c09f609bb0e4fdd3dd7dc2421bd3baf2610
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"
14 namespace content {
16 namespace webcrypto {
18 namespace {
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,
31 key_length_bits);
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);
46 return 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),
57 GetTestAesCbcKey(),
58 CryptoData(input),
59 &output));
60 EXPECT_EQ(Status::ErrorIncorrectSizeAesCbcIv(),
61 Decrypt(CreateAesCbcAlgorithm(iv),
62 GetTestAesCbcKey(),
63 CryptoData(input),
64 &output));
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),
75 GetTestAesCbcKey(),
76 CryptoData(input),
77 &output));
78 EXPECT_EQ(Status::ErrorIncorrectSizeAesCbcIv(),
79 Decrypt(CreateAesCbcAlgorithm(iv),
80 GetTestAesCbcKey(),
81 CryptoData(input),
82 &output));
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
90 // lengths.
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
95 // data.
96 CryptoData input(&iv[0], INT_MAX - 3);
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));
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,
116 CryptoData(key_raw),
117 CreateAesCbcAlgorithm(iv),
118 true,
119 blink::WebCryptoKeyUsageEncrypt,
120 &key));
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
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));
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),
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));
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(
171 test_key,
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;
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);
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);
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(
218 test_key,
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),
231 key,
232 CryptoData(&test_cipher_text[0],
233 test_cipher_text.size() - kAesCbcBlockSize),
234 &output));
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));
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);
256 ++key_length_i) {
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(),
265 GenerateSecretKey(
266 CreateAesCbcKeyGenAlgorithm(kKeyLength[key_length_i]),
267 true,
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);
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) {
288 SCOPED_TRACE(i);
289 EXPECT_EQ(Status::ErrorGenerateKeyLength(),
290 GenerateSecretKey(
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.
304 EXPECT_EQ(
305 Status::Success(),
306 ImportKeyJwkFromDict(dict,
307 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
308 false,
310 &key));
312 EXPECT_EQ(0, key.usages());
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));
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));
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==");
340 EXPECT_EQ(
341 Status::Success(),
342 ImportKeyJwkFromDict(dict,
343 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
344 false,
345 blink::WebCryptoKeyUsageEncrypt,
346 &key));
348 EXPECT_EQ(blink::WebCryptoKeyUsageEncrypt, key.usages());
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));
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");
370 EXPECT_EQ(
371 Status::Success(),
372 ImportKeyJwkFromDict(dict,
373 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
374 false,
375 blink::WebCryptoKeyUsageEncrypt,
376 &key));
378 EXPECT_EQ(blink::WebCryptoKeyUsageEncrypt, key.usages());
380 key_ops->AppendString("decrypt");
382 EXPECT_EQ(
383 Status::Success(),
384 ImportKeyJwkFromDict(dict,
385 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
386 false,
387 blink::WebCryptoKeyUsageDecrypt,
388 &key));
390 EXPECT_EQ(blink::WebCryptoKeyUsageDecrypt, key.usages());
392 EXPECT_EQ(
393 Status::Success(),
394 ImportKeyJwkFromDict(
395 dict,
396 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
397 false,
398 blink::WebCryptoKeyUsageDecrypt | blink::WebCryptoKeyUsageEncrypt,
399 &key));
401 EXPECT_EQ(blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt,
402 key.usages());
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");
416 EXPECT_EQ(
417 Status::ErrorJwkKeyopsInconsistent(),
418 ImportKeyJwkFromDict(
419 dict,
420 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
421 false,
422 blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt,
423 &key));
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");
435 EXPECT_EQ(
436 Status::Success(),
437 ImportKeyJwkFromDict(dict,
438 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
439 false,
440 blink::WebCryptoKeyUsageDecrypt |
441 blink::WebCryptoKeyUsageEncrypt |
442 blink::WebCryptoKeyUsageWrapKey |
443 blink::WebCryptoKeyUsageUnwrapKey,
444 &key));
445 EXPECT_EQ(blink::WebCryptoKeyUsageDecrypt | blink::WebCryptoKeyUsageEncrypt |
446 blink::WebCryptoKeyUsageWrapKey |
447 blink::WebCryptoKeyUsageUnwrapKey,
448 key.usages());
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),
458 false,
459 blink::WebCryptoKeyUsageEncrypt,
460 &key));
462 // Fail on invalid JSON.
463 const std::vector<uint8_t> bad_json_vec = MakeJsonVector(
465 "\"kty\" : \"oct\","
466 "\"alg\" : \"HS256\","
467 "\"use\" : ");
468 EXPECT_EQ(Status::ErrorJwkNotDictionary(),
469 ImportKey(blink::WebCryptoKeyFormatJwk,
470 CryptoData(bad_json_vec),
471 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
472 false,
473 blink::WebCryptoKeyUsageEncrypt,
474 &key));
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==");
486 EXPECT_EQ(
487 Status::ErrorJwkAlgorithmInconsistent(),
488 ImportKeyJwkFromDict(dict,
489 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
490 false,
491 blink::WebCryptoKeyUsageEncrypt,
492 &key));
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==");
502 EXPECT_EQ(
503 Status::ErrorJwkUnexpectedKty("oct"),
504 ImportKeyJwkFromDict(dict,
505 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
506 false,
507 blink::WebCryptoKeyUsageEncrypt,
508 &key));
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==");
517 EXPECT_EQ(
518 Status::ErrorJwkPropertyMissing("kty"),
519 ImportKeyJwkFromDict(dict,
520 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
521 false,
522 blink::WebCryptoKeyUsageEncrypt,
523 &key));
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==");
534 EXPECT_EQ(
535 Status::ErrorJwkPropertyWrongType("kty", "string"),
536 ImportKeyJwkFromDict(dict,
537 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
538 false,
539 blink::WebCryptoKeyUsageEncrypt,
540 &key));
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==");
552 EXPECT_EQ(
553 Status::ErrorJwkUnrecognizedUse(),
554 ImportKeyJwkFromDict(dict,
555 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
556 false,
557 blink::WebCryptoKeyUsageEncrypt,
558 &key));
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==");
570 EXPECT_EQ(
571 Status::ErrorJwkPropertyWrongType("use", "string"),
572 ImportKeyJwkFromDict(dict,
573 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
574 false,
575 blink::WebCryptoKeyUsageEncrypt,
576 &key));
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==");
588 EXPECT_EQ(
589 Status::ErrorJwkPropertyWrongType("ext", "boolean"),
590 ImportKeyJwkFromDict(dict,
591 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
592 false,
593 blink::WebCryptoKeyUsageEncrypt,
594 &key));
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);
606 EXPECT_EQ(
607 Status::ErrorJwkPropertyWrongType("key_ops", "list"),
608 ImportKeyJwkFromDict(dict,
609 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
610 false,
611 blink::WebCryptoKeyUsageEncrypt,
612 &key));
615 // Fail on inconsistent key_ops - asking for "encrypt" however JWK contains
616 // only "foo".
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");
628 EXPECT_EQ(
629 Status::ErrorJwkKeyopsInconsistent(),
630 ImportKeyJwkFromDict(dict,
631 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
632 false,
633 blink::WebCryptoKeyUsageEncrypt,
634 &key));
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");
690 EXPECT_EQ(
691 Status::ErrorJwkPropertyMissing("k"),
692 ImportKeyJwkFromDict(dict,
693 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
694 false,
695 blink::WebCryptoKeyUsageEncrypt,
696 &key));
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=");
706 EXPECT_EQ(
707 Status::ErrorJwkBase64Decode("k"),
708 ImportKeyJwkFromDict(dict,
709 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
710 false,
711 blink::WebCryptoKeyUsageEncrypt,
712 &key));
715 // Fail on empty k.
716 TEST(WebCryptoAesCbcTest, ImportJwkEmptyK) {
717 blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
719 base::DictionaryValue dict;
720 dict.SetString("kty", "oct");
721 dict.SetString("k", "");
723 EXPECT_EQ(
724 Status::ErrorImportAesKeyLength(),
725 ImportKeyJwkFromDict(dict,
726 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
727 false,
728 blink::WebCryptoKeyUsageEncrypt,
729 &key));
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", "");
741 EXPECT_EQ(
742 Status::ErrorJwkIncorrectKeyLength(),
743 ImportKeyJwkFromDict(dict,
744 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
745 false,
746 blink::WebCryptoKeyUsageEncrypt,
747 &key));
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");
759 EXPECT_EQ(
760 Status::ErrorJwkIncorrectKeyLength(),
761 ImportKeyJwkFromDict(dict,
762 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
763 false,
764 blink::WebCryptoKeyUsageEncrypt,
765 &key));
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");
777 EXPECT_EQ(
778 Status::ErrorJwkIncorrectKeyLength(),
779 ImportKeyJwkFromDict(dict,
780 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
781 false,
782 blink::WebCryptoKeyUsageEncrypt,
783 &key));
786 TEST(WebCryptoAesCbcTest, ImportExportJwk) {
787 const blink::WebCryptoAlgorithm algorithm =
788 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc);
790 // AES-CBC 128
791 ImportExportJwkSymmetricKey(
792 128,
793 algorithm,
794 blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt,
795 "A128CBC");
797 // AES-CBC 256
798 ImportExportJwkSymmetricKey(
799 256, algorithm, blink::WebCryptoKeyUsageDecrypt, "A256CBC");
801 // Large usage value
802 ImportExportJwkSymmetricKey(
803 256,
804 algorithm,
805 blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt |
806 blink::WebCryptoKeyUsageWrapKey | blink::WebCryptoKeyUsageUnwrapKey,
807 "A256CBC");
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,
815 CryptoData(key_raw),
816 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
817 true,
818 blink::WebCryptoKeyUsageEncrypt,
819 &key);
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");
832 EXPECT_EQ(
833 Status::ErrorAes192BitUnsupported(),
834 ImportKeyJwkFromDict(dict,
835 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
836 false,
837 blink::WebCryptoKeyUsageEncrypt,
838 &key));
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),
845 true,
846 blink::WebCryptoKeyUsageEncrypt,
847 &key);
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),
866 wrapping_key,
867 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw),
868 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
869 true,
870 blink::WebCryptoKeyUsageEncrypt,
871 &unwrapped_key));
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) {
891 SCOPED_TRACE(i);
893 blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
894 ASSERT_EQ(Status::ErrorCreateKeyBadUsages(),
895 ImportKey(blink::WebCryptoKeyFormatRaw,
896 CryptoData(key_bytes),
897 algorithm,
898 true,
899 bad_usages[i],
900 &key));
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) {
913 SCOPED_TRACE(i);
915 blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
917 ASSERT_EQ(Status::ErrorCreateKeyBadUsages(),
918 GenerateSecretKey(
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())
928 return;
930 // Generate the wrapping key.
931 blink::WebCryptoKey wrapping_key = blink::WebCryptoKey::createNull();
932 ASSERT_EQ(Status::Success(),
933 GenerateSecretKey(CreateAesCbcKeyGenAlgorithm(128),
934 true,
935 blink::WebCryptoKeyUsageWrapKey |
936 blink::WebCryptoKeyUsageUnwrapKey,
937 &wrapping_key));
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,
949 modulus_length,
950 public_exponent),
951 true,
953 &public_key,
954 &private_key));
956 // Export key pair as SPKI + PKCS8
957 std::vector<uint8_t> public_key_spki;
958 ASSERT_EQ(
959 Status::Success(),
960 ExportKey(blink::WebCryptoKeyFormatSpki, public_key, &public_key_spki));
962 std::vector<uint8_t> private_key_pkcs8;
963 ASSERT_EQ(
964 Status::Success(),
965 ExportKey(
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,
975 public_key,
976 wrapping_key,
977 wrap_algorithm,
978 &wrapped_public_key));
980 std::vector<uint8_t> wrapped_private_key;
981 ASSERT_EQ(Status::Success(),
982 WrapKey(blink::WebCryptoKeyFormatPkcs8,
983 private_key,
984 wrapping_key,
985 wrap_algorithm,
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),
998 wrapping_key,
999 wrap_algorithm,
1000 rsa_import_algorithm,
1001 true,
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),
1010 wrapping_key,
1011 wrap_algorithm,
1012 rsa_import_algorithm,
1013 true,
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);
1037 } // namespace
1039 } // namespace webcrypto
1041 } // namespace content