OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "webcrypto_impl.h" | 5 #include "webcrypto_impl.h" |
6 | 6 |
7 #include "base/basictypes.h" | 7 #include "base/basictypes.h" |
| 8 #include "base/json/json_writer.h" |
8 #include "base/logging.h" | 9 #include "base/logging.h" |
9 #include "base/memory/ref_counted.h" | 10 #include "base/memory/ref_counted.h" |
10 #include "base/strings/string_number_conversions.h" | 11 #include "base/strings/string_number_conversions.h" |
11 #include "content/public/renderer/content_renderer_client.h" | 12 #include "content/public/renderer/content_renderer_client.h" |
12 #include "content/renderer/renderer_webkitplatformsupport_impl.h" | 13 #include "content/renderer/renderer_webkitplatformsupport_impl.h" |
13 #include "content/renderer/webcrypto/webcrypto_impl.h" | 14 #include "content/renderer/webcrypto/webcrypto_impl.h" |
| 15 #include "content/renderer/webcrypto/webcrypto_util.h" |
14 #include "testing/gtest/include/gtest/gtest.h" | 16 #include "testing/gtest/include/gtest/gtest.h" |
15 #include "third_party/WebKit/public/platform/WebArrayBuffer.h" | 17 #include "third_party/WebKit/public/platform/WebArrayBuffer.h" |
16 #include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h" | 18 #include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h" |
17 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" | 19 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" |
18 | 20 |
19 namespace { | 21 namespace { |
20 | 22 |
21 std::vector<uint8> HexStringToBytes(const std::string& hex) { | 23 std::vector<uint8> HexStringToBytes(const std::string& hex) { |
22 std::vector<uint8> bytes; | 24 std::vector<uint8> bytes; |
23 base::HexStringToBytes(hex, &bytes); | 25 base::HexStringToBytes(hex, &bytes); |
24 return bytes; | 26 return bytes; |
25 } | 27 } |
26 | 28 |
27 void ExpectArrayBufferMatchesHex(const std::string& expected_hex, | 29 void ExpectArrayBufferMatchesHex(const std::string& expected_hex, |
28 const WebKit::WebArrayBuffer& array_buffer) { | 30 const WebKit::WebArrayBuffer& array_buffer) { |
29 EXPECT_STRCASEEQ( | 31 EXPECT_STRCASEEQ( |
30 expected_hex.c_str(), | 32 expected_hex.c_str(), |
31 base::HexEncode( | 33 base::HexEncode( |
32 array_buffer.data(), array_buffer.byteLength()).c_str()); | 34 array_buffer.data(), array_buffer.byteLength()).c_str()); |
33 } | 35 } |
34 | 36 |
35 WebKit::WebCryptoAlgorithm CreateAlgorithm(WebKit::WebCryptoAlgorithmId id) { | 37 std::vector<uint8> MakeJsonVector(const std::string& json_string) { |
36 return WebKit::WebCryptoAlgorithm::adoptParamsAndCreate(id, NULL); | 38 return std::vector<uint8>(json_string.begin(), json_string.end()); |
37 } | 39 } |
38 | 40 |
39 WebKit::WebCryptoAlgorithm CreateHmacAlgorithm( | 41 std::vector<uint8> MakeJsonVector(const base::DictionaryValue& dict) { |
40 WebKit::WebCryptoAlgorithmId hashId) { | 42 std::string json; |
41 return WebKit::WebCryptoAlgorithm::adoptParamsAndCreate( | 43 base::JSONWriter::Write(&dict, &json); |
42 WebKit::WebCryptoAlgorithmIdHmac, | 44 return MakeJsonVector(json); |
43 new WebKit::WebCryptoHmacParams(CreateAlgorithm(hashId))); | |
44 } | 45 } |
45 | 46 |
46 WebKit::WebCryptoAlgorithm CreateHmacKeyAlgorithm( | 47 // Helper for ImportJwkBadJwk; restores JWK JSON dictionary to a good state |
47 WebKit::WebCryptoAlgorithmId hashId, | 48 void RestoreDictionaryForImportBadJwkTest(base::DictionaryValue* dict) { |
48 unsigned hash_length) { | 49 dict->Clear(); |
49 // hash_length < 0 means unspecified | 50 dict->SetString("kty", "oct"); |
50 return WebKit::WebCryptoAlgorithm::adoptParamsAndCreate( | 51 dict->SetString("alg", "HS256"); |
51 WebKit::WebCryptoAlgorithmIdHmac, | 52 dict->SetString("use", "sig"); |
52 new WebKit::WebCryptoHmacKeyParams(CreateAlgorithm(hashId), | 53 dict->SetBoolean("extractable", false); |
53 (hash_length != 0), | 54 dict->SetString("k", "Qk3f0DsytU8lfza2auHtaw2xpop9GYyTuH0p5GghxTI="); |
54 hash_length)); | |
55 } | |
56 | |
57 // Returns a pointer to the start of |data|, or NULL if it is empty. This is a | |
58 // convenience function for getting the pointer, and should not be used beyond | |
59 // the expected lifetime of |data|. | |
60 const uint8* Start(const std::vector<uint8>& data) { | |
61 if (data.empty()) | |
62 return NULL; | |
63 return &data[0]; | |
64 } | |
65 | |
66 WebKit::WebCryptoAlgorithm CreateAesCbcAlgorithm( | |
67 const std::vector<uint8>& iv) { | |
68 return WebKit::WebCryptoAlgorithm::adoptParamsAndCreate( | |
69 WebKit::WebCryptoAlgorithmIdAesCbc, | |
70 new WebKit::WebCryptoAesCbcParams(Start(iv), iv.size())); | |
71 } | |
72 | |
73 WebKit::WebCryptoAlgorithm CreateAesCbcAlgorithm( | |
74 unsigned short key_length_bits) { | |
75 return WebKit::WebCryptoAlgorithm::adoptParamsAndCreate( | |
76 WebKit::WebCryptoAlgorithmIdAesCbc, | |
77 new WebKit::WebCryptoAesKeyGenParams(key_length_bits)); | |
78 } | 55 } |
79 | 56 |
80 } // namespace | 57 } // namespace |
81 | 58 |
82 namespace content { | 59 namespace content { |
83 | 60 |
84 class WebCryptoImplTest : public testing::Test { | 61 class WebCryptoImplTest : public testing::Test { |
85 protected: | 62 protected: |
86 WebKit::WebCryptoKey ImportSecretKeyFromRawHexString( | 63 WebKit::WebCryptoKey ImportSecretKeyFromRawHexString( |
87 const std::string& key_hex, | 64 const std::string& key_hex, |
88 const WebKit::WebCryptoAlgorithm& algorithm, | 65 const WebKit::WebCryptoAlgorithm& algorithm, |
89 WebKit::WebCryptoKeyUsageMask usage) { | 66 WebKit::WebCryptoKeyUsageMask usage) { |
90 std::vector<uint8> key_raw = HexStringToBytes(key_hex); | 67 std::vector<uint8> key_raw = HexStringToBytes(key_hex); |
91 | 68 |
92 WebKit::WebCryptoKey key = WebCryptoImpl::NullKey(); | 69 WebKit::WebCryptoKey key = WebKit::WebCryptoKey::createNull(); |
93 bool extractable = true; | 70 bool extractable = true; |
94 EXPECT_TRUE(crypto_.ImportKeyInternal(WebKit::WebCryptoKeyFormatRaw, | 71 EXPECT_TRUE(crypto_.ImportKeyInternal(WebKit::WebCryptoKeyFormatRaw, |
95 Start(key_raw), | 72 Start(key_raw), |
96 key_raw.size(), | 73 key_raw.size(), |
97 algorithm, | 74 algorithm, |
98 extractable, | 75 extractable, |
99 usage, | 76 usage, |
100 &key)); | 77 &key)); |
101 | 78 |
102 EXPECT_EQ(WebKit::WebCryptoKeyTypeSecret, key.type()); | 79 EXPECT_EQ(WebKit::WebCryptoKeyTypeSecret, key.type()); |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
192 | 169 |
193 bool DecryptInternal( | 170 bool DecryptInternal( |
194 const WebKit::WebCryptoAlgorithm& algorithm, | 171 const WebKit::WebCryptoAlgorithm& algorithm, |
195 const WebKit::WebCryptoKey& key, | 172 const WebKit::WebCryptoKey& key, |
196 const std::vector<uint8>& data, | 173 const std::vector<uint8>& data, |
197 WebKit::WebArrayBuffer* buffer) { | 174 WebKit::WebArrayBuffer* buffer) { |
198 return crypto_.DecryptInternal( | 175 return crypto_.DecryptInternal( |
199 algorithm, key, Start(data), data.size(), buffer); | 176 algorithm, key, Start(data), data.size(), buffer); |
200 } | 177 } |
201 | 178 |
| 179 bool ImportKeyJwk( |
| 180 const std::vector<uint8>& key_data, |
| 181 const WebKit::WebCryptoAlgorithm& algorithm, |
| 182 bool extractable, |
| 183 WebKit::WebCryptoKeyUsageMask usage_mask, |
| 184 WebKit::WebCryptoKey* key) { |
| 185 return crypto_.ImportKeyJwk(Start(key_data), |
| 186 key_data.size(), |
| 187 algorithm, |
| 188 extractable, |
| 189 usage_mask, |
| 190 key); |
| 191 } |
| 192 |
202 private: | 193 private: |
203 WebCryptoImpl crypto_; | 194 WebCryptoImpl crypto_; |
204 }; | 195 }; |
205 | 196 |
206 TEST_F(WebCryptoImplTest, DigestSampleSets) { | 197 TEST_F(WebCryptoImplTest, DigestSampleSets) { |
207 // The results are stored here in hex format for readability. | 198 // The results are stored here in hex format for readability. |
208 // | 199 // |
209 // TODO(bryaneyler): Eventually, all these sample test sets should be replaced | 200 // TODO(bryaneyler): Eventually, all these sample test sets should be replaced |
210 // with the sets here: http://csrc.nist.gov/groups/STM/cavp/index.html#03 | 201 // with the sets here: http://csrc.nist.gov/groups/STM/cavp/index.html#03 |
211 // | 202 // |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
370 // mac | 361 // mac |
371 "4f1ee7cb36c58803a8721d4ac8c4cf8cae5d8832392eed2a96dc59694252801b", | 362 "4f1ee7cb36c58803a8721d4ac8c4cf8cae5d8832392eed2a96dc59694252801b", |
372 }, | 363 }, |
373 }; | 364 }; |
374 | 365 |
375 for (size_t test_index = 0; test_index < ARRAYSIZE_UNSAFE(kTests); | 366 for (size_t test_index = 0; test_index < ARRAYSIZE_UNSAFE(kTests); |
376 ++test_index) { | 367 ++test_index) { |
377 SCOPED_TRACE(test_index); | 368 SCOPED_TRACE(test_index); |
378 const TestCase& test = kTests[test_index]; | 369 const TestCase& test = kTests[test_index]; |
379 | 370 |
380 WebKit::WebCryptoAlgorithm algorithm = CreateHmacAlgorithm(test.algorithm); | 371 WebKit::WebCryptoAlgorithm algorithm = |
| 372 CreateHmacAlgorithmByHashId(test.algorithm); |
381 | 373 |
382 WebKit::WebCryptoKey key = ImportSecretKeyFromRawHexString( | 374 WebKit::WebCryptoKey key = ImportSecretKeyFromRawHexString( |
383 test.key, algorithm, WebKit::WebCryptoKeyUsageSign); | 375 test.key, algorithm, WebKit::WebCryptoKeyUsageSign); |
384 | 376 |
385 std::vector<uint8> message_raw = HexStringToBytes(test.message); | 377 std::vector<uint8> message_raw = HexStringToBytes(test.message); |
386 | 378 |
387 WebKit::WebArrayBuffer output; | 379 WebKit::WebArrayBuffer output; |
388 | 380 |
389 ASSERT_TRUE(SignInternal(algorithm, key, message_raw, &output)); | 381 ASSERT_TRUE(SignInternal(algorithm, key, message_raw, &output)); |
390 | 382 |
(...skipping 25 matching lines...) Expand all Loading... |
416 algorithm, | 408 algorithm, |
417 key, | 409 key, |
418 kLongSignature, | 410 kLongSignature, |
419 sizeof(kLongSignature), | 411 sizeof(kLongSignature), |
420 message_raw, | 412 message_raw, |
421 &signature_match)); | 413 &signature_match)); |
422 EXPECT_FALSE(signature_match); | 414 EXPECT_FALSE(signature_match); |
423 } | 415 } |
424 } | 416 } |
425 | 417 |
| 418 #if !defined(USE_OPENSSL) |
| 419 |
426 TEST_F(WebCryptoImplTest, AesCbcFailures) { | 420 TEST_F(WebCryptoImplTest, AesCbcFailures) { |
427 WebKit::WebCryptoKey key = ImportSecretKeyFromRawHexString( | 421 WebKit::WebCryptoKey key = ImportSecretKeyFromRawHexString( |
428 "2b7e151628aed2a6abf7158809cf4f3c", | 422 "2b7e151628aed2a6abf7158809cf4f3c", |
429 CreateAlgorithm(WebKit::WebCryptoAlgorithmIdAesCbc), | 423 CreateAlgorithm(WebKit::WebCryptoAlgorithmIdAesCbc), |
430 WebKit::WebCryptoKeyUsageEncrypt | WebKit::WebCryptoKeyUsageDecrypt); | 424 WebKit::WebCryptoKeyUsageEncrypt | WebKit::WebCryptoKeyUsageDecrypt); |
431 | 425 |
432 WebKit::WebArrayBuffer output; | 426 WebKit::WebArrayBuffer output; |
433 | 427 |
434 // Use an invalid |iv| (fewer than 16 bytes) | 428 // Use an invalid |iv| (fewer than 16 bytes) |
435 { | 429 { |
(...skipping 30 matching lines...) Expand all Loading... |
466 CreateAesCbcAlgorithm(iv), key, input, input_len, &output)); | 460 CreateAesCbcAlgorithm(iv), key, input, input_len, &output)); |
467 EXPECT_FALSE(DecryptInternal( | 461 EXPECT_FALSE(DecryptInternal( |
468 CreateAesCbcAlgorithm(iv), key, input, input_len, &output)); | 462 CreateAesCbcAlgorithm(iv), key, input, input_len, &output)); |
469 } | 463 } |
470 | 464 |
471 // Fail importing the key (too few bytes specified) | 465 // Fail importing the key (too few bytes specified) |
472 { | 466 { |
473 std::vector<uint8> key_raw(1); | 467 std::vector<uint8> key_raw(1); |
474 std::vector<uint8> iv(16); | 468 std::vector<uint8> iv(16); |
475 | 469 |
476 WebKit::WebCryptoKey key = WebCryptoImpl::NullKey(); | 470 WebKit::WebCryptoKey key = WebKit::WebCryptoKey::createNull(); |
477 EXPECT_FALSE(ImportKeyInternal(WebKit::WebCryptoKeyFormatRaw, | 471 EXPECT_FALSE(ImportKeyInternal(WebKit::WebCryptoKeyFormatRaw, |
478 key_raw, | 472 key_raw, |
479 CreateAesCbcAlgorithm(iv), | 473 CreateAesCbcAlgorithm(iv), |
480 WebKit::WebCryptoKeyUsageDecrypt, | 474 WebKit::WebCryptoKeyUsageDecrypt, |
481 &key)); | 475 &key)); |
482 } | 476 } |
483 } | 477 } |
484 | 478 |
485 TEST_F(WebCryptoImplTest, AesCbcSampleSets) { | 479 TEST_F(WebCryptoImplTest, AesCbcSampleSets) { |
486 struct TestCase { | 480 struct TestCase { |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
610 cipher_text.size() - 3, | 604 cipher_text.size() - 3, |
611 &output)); | 605 &output)); |
612 } | 606 } |
613 } | 607 } |
614 } | 608 } |
615 | 609 |
616 // TODO (padolph): Add test to verify generated symmetric keys appear random. | 610 // TODO (padolph): Add test to verify generated symmetric keys appear random. |
617 | 611 |
618 | 612 |
619 TEST_F(WebCryptoImplTest, GenerateKeyAes) { | 613 TEST_F(WebCryptoImplTest, GenerateKeyAes) { |
620 WebKit::WebCryptoKey key = WebCryptoImpl::NullKey(); | 614 WebKit::WebCryptoKey key = WebKit::WebCryptoKey::createNull(); |
621 ASSERT_TRUE(GenerateKeyInternal(CreateAesCbcAlgorithm(128), &key)); | 615 ASSERT_TRUE(GenerateKeyInternal(CreateAesCbcKeyGenAlgorithm(128), &key)); |
622 EXPECT_TRUE(key.handle()); | 616 EXPECT_TRUE(key.handle()); |
623 EXPECT_EQ(WebKit::WebCryptoKeyTypeSecret, key.type()); | 617 EXPECT_EQ(WebKit::WebCryptoKeyTypeSecret, key.type()); |
624 } | 618 } |
625 | 619 |
626 TEST_F(WebCryptoImplTest, GenerateKeyAesBadLength) { | 620 TEST_F(WebCryptoImplTest, GenerateKeyAesBadLength) { |
627 WebKit::WebCryptoKey key = WebCryptoImpl::NullKey(); | 621 WebKit::WebCryptoKey key = WebKit::WebCryptoKey::createNull(); |
628 EXPECT_FALSE(GenerateKeyInternal(CreateAesCbcAlgorithm(0), &key)); | 622 EXPECT_FALSE( |
629 EXPECT_FALSE(GenerateKeyInternal(CreateAesCbcAlgorithm(129), &key)); | 623 GenerateKeyInternal(CreateAesCbcKeyGenAlgorithm(0), &key)); |
| 624 EXPECT_FALSE( |
| 625 GenerateKeyInternal(CreateAesCbcKeyGenAlgorithm(0), &key)); |
| 626 EXPECT_FALSE( |
| 627 GenerateKeyInternal(CreateAesCbcKeyGenAlgorithm(129), &key)); |
630 } | 628 } |
631 | 629 |
| 630 |
632 TEST_F(WebCryptoImplTest, GenerateKeyHmac) { | 631 TEST_F(WebCryptoImplTest, GenerateKeyHmac) { |
633 WebKit::WebCryptoKey key = WebCryptoImpl::NullKey(); | 632 WebKit::WebCryptoKey key = WebKit::WebCryptoKey::createNull(); |
634 WebKit::WebCryptoAlgorithm algorithm = | 633 WebKit::WebCryptoAlgorithm algorithm = |
635 CreateHmacKeyAlgorithm(WebKit::WebCryptoAlgorithmIdSha1, 128); | 634 CreateHmacKeyGenAlgorithm(WebKit::WebCryptoAlgorithmIdSha1, 128); |
636 ASSERT_TRUE(GenerateKeyInternal(algorithm, &key)); | 635 ASSERT_TRUE(GenerateKeyInternal(algorithm, &key)); |
637 EXPECT_TRUE(key.handle()); | 636 EXPECT_TRUE(key.handle()); |
638 EXPECT_EQ(WebKit::WebCryptoKeyTypeSecret, key.type()); | 637 EXPECT_EQ(WebKit::WebCryptoKeyTypeSecret, key.type()); |
639 } | 638 } |
640 | 639 |
641 TEST_F(WebCryptoImplTest, GenerateKeyHmacNoLength) { | 640 TEST_F(WebCryptoImplTest, GenerateKeyHmacNoLength) { |
642 WebKit::WebCryptoKey key = WebCryptoImpl::NullKey(); | 641 WebKit::WebCryptoKey key = WebKit::WebCryptoKey::createNull(); |
643 WebKit::WebCryptoAlgorithm algorithm = | 642 WebKit::WebCryptoAlgorithm algorithm = |
644 CreateHmacKeyAlgorithm(WebKit::WebCryptoAlgorithmIdSha1, 0); | 643 CreateHmacKeyGenAlgorithm(WebKit::WebCryptoAlgorithmIdSha1, 0); |
645 ASSERT_TRUE(GenerateKeyInternal(algorithm, &key)); | 644 ASSERT_TRUE(GenerateKeyInternal(algorithm, &key)); |
646 EXPECT_TRUE(key.handle()); | 645 EXPECT_TRUE(key.handle()); |
647 EXPECT_EQ(WebKit::WebCryptoKeyTypeSecret, key.type()); | 646 EXPECT_EQ(WebKit::WebCryptoKeyTypeSecret, key.type()); |
648 } | 647 } |
649 | 648 |
650 TEST_F(WebCryptoImplTest, ImportSecretKeyNoAlgorithm) { | 649 TEST_F(WebCryptoImplTest, ImportSecretKeyNoAlgorithm) { |
651 WebKit::WebCryptoKey key = WebCryptoImpl::NullKey(); | 650 WebKit::WebCryptoKey key = WebKit::WebCryptoKey::createNull(); |
652 | 651 |
653 // This fails because the algorithm is null. | 652 // This fails because the algorithm is null. |
654 EXPECT_FALSE(ImportKeyInternal( | 653 EXPECT_FALSE(ImportKeyInternal( |
655 WebKit::WebCryptoKeyFormatRaw, | 654 WebKit::WebCryptoKeyFormatRaw, |
656 HexStringToBytes("00000000000000000000"), | 655 HexStringToBytes("00000000000000000000"), |
657 WebKit::WebCryptoAlgorithm::createNull(), | 656 WebKit::WebCryptoAlgorithm::createNull(), |
658 WebKit::WebCryptoKeyUsageSign, | 657 WebKit::WebCryptoKeyUsageSign, |
659 &key)); | 658 &key)); |
660 } | 659 } |
661 | 660 |
| 661 #endif //#if !defined(USE_OPENSSL) |
| 662 |
| 663 TEST_F(WebCryptoImplTest, ImportJwkBadJwk) { |
| 664 |
| 665 WebKit::WebCryptoKey key = WebKit::WebCryptoKey::createNull(); |
| 666 WebKit::WebCryptoAlgorithm algorithm = CreateHmacAlgorithmByDigestLen(256); |
| 667 WebKit::WebCryptoKeyUsageMask usage_mask = WebKit::WebCryptoKeyUsageSign; |
| 668 |
| 669 // Baseline pass: each test below breaks a single item, so we start with a |
| 670 // passing case to make sure each failure is caused by the isolated break. |
| 671 // Each breaking subtest below resets the dictionary to this passing case when |
| 672 // complete. |
| 673 base::DictionaryValue dict; |
| 674 RestoreDictionaryForImportBadJwkTest(&dict); |
| 675 std::vector<uint8> json_vec = MakeJsonVector(dict); |
| 676 EXPECT_TRUE(ImportKeyJwk(json_vec, algorithm, false, usage_mask, &key)); |
| 677 |
| 678 // Fail on empty JSON. |
| 679 EXPECT_FALSE(ImportKeyJwk( |
| 680 MakeJsonVector(""), algorithm, false, usage_mask, &key)); |
| 681 |
| 682 // Fail on invalid JSON. |
| 683 const std::vector<uint8> bad_json_vec = MakeJsonVector( |
| 684 "{" |
| 685 "\"kty\" : \"oct\"," |
| 686 "\"alg\" : \"HS256\"," |
| 687 "\"use\" : " |
| 688 ); |
| 689 EXPECT_FALSE(ImportKeyJwk(bad_json_vec, algorithm, false, usage_mask, &key)); |
| 690 |
| 691 // Fail on JWK alg present but unrecognized. |
| 692 dict.SetString("alg", "foo"); |
| 693 json_vec = MakeJsonVector(dict); |
| 694 EXPECT_FALSE(ImportKeyJwk(json_vec, algorithm, false, usage_mask, &key)); |
| 695 RestoreDictionaryForImportBadJwkTest(&dict); |
| 696 |
| 697 // Fail on both JWK and input algorithm missing. |
| 698 dict.Remove("alg", NULL); |
| 699 json_vec = MakeJsonVector(dict); |
| 700 EXPECT_FALSE(ImportKeyJwk(json_vec, |
| 701 WebKit::WebCryptoAlgorithm::createNull(), |
| 702 false, |
| 703 usage_mask, |
| 704 &key)); |
| 705 RestoreDictionaryForImportBadJwkTest(&dict); |
| 706 |
| 707 // Fail on invalid kty. |
| 708 dict.SetString("kty", "foo"); |
| 709 json_vec = MakeJsonVector(dict); |
| 710 EXPECT_FALSE(ImportKeyJwk(json_vec, algorithm, false, usage_mask, &key)); |
| 711 RestoreDictionaryForImportBadJwkTest(&dict); |
| 712 |
| 713 // Fail on missing kty. |
| 714 dict.Remove("kty", NULL); |
| 715 json_vec = MakeJsonVector(dict); |
| 716 EXPECT_FALSE(ImportKeyJwk(json_vec, algorithm, false, usage_mask, &key)); |
| 717 RestoreDictionaryForImportBadJwkTest(&dict); |
| 718 |
| 719 // Fail on invalid use. |
| 720 dict.SetString("use", "foo"); |
| 721 json_vec = MakeJsonVector(dict); |
| 722 EXPECT_FALSE(ImportKeyJwk(json_vec, algorithm, false, usage_mask, &key)); |
| 723 RestoreDictionaryForImportBadJwkTest(&dict); |
| 724 |
| 725 // Fail on missing k when kty = "oct". |
| 726 dict.Remove("k", NULL); |
| 727 json_vec = MakeJsonVector(dict); |
| 728 EXPECT_FALSE(ImportKeyJwk(json_vec, algorithm, false, usage_mask, &key)); |
| 729 RestoreDictionaryForImportBadJwkTest(&dict); |
| 730 |
| 731 // Fail on bad b64 encoding for k. |
| 732 dict.SetString("k", "Qk3f0DsytU8lfza2au #$% Htaw2xpop9GYyTuH0p5GghxTI="); |
| 733 json_vec = MakeJsonVector(dict); |
| 734 EXPECT_FALSE(ImportKeyJwk(json_vec, algorithm, false, usage_mask, &key)); |
| 735 RestoreDictionaryForImportBadJwkTest(&dict); |
| 736 |
| 737 // Fail on empty k. |
| 738 dict.SetString("k", ""); |
| 739 json_vec = MakeJsonVector(dict); |
| 740 EXPECT_FALSE(ImportKeyJwk(json_vec, algorithm, false, usage_mask, &key)); |
| 741 RestoreDictionaryForImportBadJwkTest(&dict); |
| 742 |
| 743 // TODO(padolph) RSA public key bad data: |
| 744 // Missing n or e when kty = "RSA" |
| 745 // Bad encoding for n or e |
| 746 // Size check on n?? |
| 747 // Value check on e?? |
| 748 } |
| 749 |
| 750 TEST_F(WebCryptoImplTest, ImportJwkInputInconsistent) { |
| 751 // The Web Crypto spec says that if a JWK value is present, but is |
| 752 // inconsistent with the input value, the operation must fail. |
| 753 |
| 754 // Consistency rules when JWK value is not present: Inputs should be used. |
| 755 WebKit::WebCryptoKey key = WebKit::WebCryptoKey::createNull(); |
| 756 bool extractable = true; |
| 757 WebKit::WebCryptoAlgorithm algorithm = |
| 758 CreateHmacAlgorithmByHashId(WebKit::WebCryptoAlgorithmIdSha256); |
| 759 WebKit::WebCryptoKeyUsageMask usage_mask = WebKit::WebCryptoKeyUsageVerify; |
| 760 base::DictionaryValue dict; |
| 761 dict.SetString("kty", "oct"); |
| 762 dict.SetString("k", "l3nZEgZCeX8XRwJdWyK3rGB8qwjhdY8vOkbIvh4lxTuMao9Y_--hdg"); |
| 763 std::vector<uint8> json_vec = MakeJsonVector(dict); |
| 764 EXPECT_TRUE(ImportKeyJwk(json_vec, algorithm, extractable, usage_mask, &key)); |
| 765 EXPECT_TRUE(key.handle()); |
| 766 EXPECT_EQ(WebKit::WebCryptoKeyTypeSecret, key.type()); |
| 767 EXPECT_EQ(extractable, key.extractable()); |
| 768 EXPECT_EQ(WebKit::WebCryptoAlgorithmIdHmac, key.algorithm().id()); |
| 769 EXPECT_EQ(WebKit::WebCryptoAlgorithmIdSha256, |
| 770 key.algorithm().hmacParams()->hash().id()); |
| 771 EXPECT_EQ(WebKit::WebCryptoKeyUsageVerify, key.usages()); |
| 772 key = WebKit::WebCryptoKey::createNull(); |
| 773 |
| 774 // Consistency rules when JWK value exists: Fail if inconsistency is found. |
| 775 // Happy path: all input values are consistent with the JWK values |
| 776 dict.Clear(); |
| 777 dict.SetString("kty", "oct"); |
| 778 dict.SetString("alg", "HS256"); |
| 779 dict.SetString("use", "sig"); |
| 780 dict.SetBoolean("extractable", true); |
| 781 dict.SetString("k", "l3nZEgZCeX8XRwJdWyK3rGB8qwjhdY8vOkbIvh4lxTuMao9Y_--hdg"); |
| 782 json_vec = MakeJsonVector(dict); |
| 783 EXPECT_TRUE(ImportKeyJwk( |
| 784 json_vec, algorithm, extractable, usage_mask, &key)); |
| 785 |
| 786 // Fail: Input extractable (false) is inconsistent with JWK value (true). |
| 787 EXPECT_FALSE( |
| 788 ImportKeyJwk(json_vec, algorithm, false, usage_mask, &key)); |
| 789 |
| 790 // Fail: Input algorithm (AES-CBC) is inconsistent with JWK value |
| 791 // (HMAC SHA256). |
| 792 EXPECT_FALSE(ImportKeyJwk(json_vec, |
| 793 CreateAlgorithm(WebKit::WebCryptoAlgorithmIdAesCbc), |
| 794 extractable, |
| 795 usage_mask, |
| 796 &key)); |
| 797 |
| 798 // Fail: Input algorithm (HMAC SHA1) is inconsistent with JWK value |
| 799 // (HMAC SHA256). |
| 800 EXPECT_FALSE(ImportKeyJwk( |
| 801 json_vec, |
| 802 CreateHmacAlgorithmByHashId(WebKit::WebCryptoAlgorithmIdSha1), |
| 803 extractable, |
| 804 usage_mask, |
| 805 &key)); |
| 806 |
| 807 // Pass: JWK alg valid but input algorithm isNull: use JWK algorithm value. |
| 808 EXPECT_TRUE(ImportKeyJwk(json_vec, |
| 809 WebKit::WebCryptoAlgorithm::createNull(), |
| 810 extractable, |
| 811 usage_mask, |
| 812 &key)); |
| 813 EXPECT_EQ(WebKit::WebCryptoAlgorithmIdHmac, algorithm.id()); |
| 814 |
| 815 // Pass: JWK alg missing but input algorithm specified: use input value |
| 816 dict.Remove("alg", NULL); |
| 817 EXPECT_TRUE(ImportKeyJwk( |
| 818 MakeJsonVector(dict), |
| 819 CreateHmacAlgorithmByHashId(WebKit::WebCryptoAlgorithmIdSha256), |
| 820 extractable, |
| 821 usage_mask, |
| 822 &key)); |
| 823 EXPECT_EQ(WebKit::WebCryptoAlgorithmIdHmac, algorithm.id()); |
| 824 dict.SetString("alg", "HS256"); |
| 825 |
| 826 // Fail: Input usage_mask (encrypt) is not a subset of the JWK value |
| 827 // (sign|verify) |
| 828 EXPECT_FALSE(ImportKeyJwk(json_vec, |
| 829 algorithm, |
| 830 extractable, |
| 831 WebKit::WebCryptoKeyUsageEncrypt, |
| 832 &key)); |
| 833 |
| 834 // Fail: Input usage_mask (encrypt|sign|verify) is not a subset of the JWK |
| 835 // value (sign|verify) |
| 836 usage_mask = WebKit::WebCryptoKeyUsageEncrypt | |
| 837 WebKit::WebCryptoKeyUsageSign | WebKit::WebCryptoKeyUsageVerify; |
| 838 EXPECT_FALSE(ImportKeyJwk( |
| 839 json_vec, algorithm, extractable, usage_mask, &key)); |
| 840 usage_mask = WebKit::WebCryptoKeyUsageSign | WebKit::WebCryptoKeyUsageVerify; |
| 841 } |
| 842 |
| 843 TEST_F(WebCryptoImplTest, ImportJwkHappy) { |
| 844 |
| 845 // This test verifies the happy path of JWK import, including the application |
| 846 // of the imported key material. |
| 847 |
| 848 WebKit::WebCryptoKey key = WebKit::WebCryptoKey::createNull(); |
| 849 bool extractable = false; |
| 850 WebKit::WebCryptoAlgorithm algorithm = |
| 851 CreateHmacAlgorithmByHashId(WebKit::WebCryptoAlgorithmIdSha256); |
| 852 WebKit::WebCryptoKeyUsageMask usage_mask = WebKit::WebCryptoKeyUsageSign; |
| 853 |
| 854 // Import a symmetric key JWK and HMAC-SHA256 sign() |
| 855 // Uses the first SHA256 test vector from the HMAC sample set above. |
| 856 |
| 857 base::DictionaryValue dict; |
| 858 dict.SetString("kty", "oct"); |
| 859 dict.SetString("alg", "HS256"); |
| 860 dict.SetString("use", "sig"); |
| 861 dict.SetBoolean("extractable", false); |
| 862 dict.SetString("k", "l3nZEgZCeX8XRwJdWyK3rGB8qwjhdY8vOkbIvh4lxTuMao9Y_--hdg"); |
| 863 std::vector<uint8> json_vec = MakeJsonVector(dict); |
| 864 |
| 865 ASSERT_TRUE(ImportKeyJwk( |
| 866 json_vec, algorithm, extractable, usage_mask, &key)); |
| 867 |
| 868 const std::vector<uint8> message_raw = HexStringToBytes( |
| 869 "b1689c2591eaf3c9e66070f8a77954ffb81749f1b00346f9dfe0b2ee905dcc288baf4a" |
| 870 "92de3f4001dd9f44c468c3d07d6c6ee82faceafc97c2fc0fc0601719d2dcd0aa2aec92" |
| 871 "d1b0ae933c65eb06a03c9c935c2bad0459810241347ab87e9f11adb30415424c6c7f5f" |
| 872 "22a003b8ab8de54f6ded0e3ab9245fa79568451dfa258e"); |
| 873 |
| 874 WebKit::WebArrayBuffer output; |
| 875 |
| 876 ASSERT_TRUE(SignInternal(algorithm, key, message_raw, &output)); |
| 877 |
| 878 const std::string mac_raw = |
| 879 "769f00d3e6a6cc1fb426a14a4f76c6462e6149726e0dee0ec0cf97a16605ac8b"; |
| 880 |
| 881 ExpectArrayBufferMatchesHex(mac_raw, output); |
| 882 |
| 883 // TODO(padolph) |
| 884 // Import an RSA public key JWK and use it |
| 885 } |
| 886 |
662 } // namespace content | 887 } // namespace content |
OLD | NEW |