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 #include "third_party/WebKit/public/platform/WebCryptoKey.h" | 20 #include "third_party/WebKit/public/platform/WebCryptoKey.h" |
19 | 21 |
| 22 namespace content { |
| 23 |
20 namespace { | 24 namespace { |
21 | 25 |
22 std::vector<uint8> HexStringToBytes(const std::string& hex) { | 26 std::vector<uint8> HexStringToBytes(const std::string& hex) { |
23 std::vector<uint8> bytes; | 27 std::vector<uint8> bytes; |
24 base::HexStringToBytes(hex, &bytes); | 28 base::HexStringToBytes(hex, &bytes); |
25 return bytes; | 29 return bytes; |
26 } | 30 } |
27 | 31 |
28 void ExpectArrayBufferMatchesHex(const std::string& expected_hex, | 32 void ExpectArrayBufferMatchesHex(const std::string& expected_hex, |
29 const WebKit::WebArrayBuffer& array_buffer) { | 33 const WebKit::WebArrayBuffer& array_buffer) { |
30 EXPECT_STRCASEEQ( | 34 EXPECT_STRCASEEQ( |
31 expected_hex.c_str(), | 35 expected_hex.c_str(), |
32 base::HexEncode( | 36 base::HexEncode( |
33 array_buffer.data(), array_buffer.byteLength()).c_str()); | 37 array_buffer.data(), array_buffer.byteLength()).c_str()); |
34 } | 38 } |
35 | 39 |
36 WebKit::WebCryptoAlgorithm CreateAlgorithm(WebKit::WebCryptoAlgorithmId id) { | 40 std::vector<uint8> MakeJsonVector(const std::string& json_string) { |
37 return WebKit::WebCryptoAlgorithm::adoptParamsAndCreate(id, NULL); | 41 return std::vector<uint8>(json_string.begin(), json_string.end()); |
38 } | 42 } |
39 | 43 |
40 WebKit::WebCryptoAlgorithm CreateHmacAlgorithm( | 44 std::vector<uint8> MakeJsonVector(const base::DictionaryValue& dict) { |
41 WebKit::WebCryptoAlgorithmId hashId) { | 45 std::string json; |
42 return WebKit::WebCryptoAlgorithm::adoptParamsAndCreate( | 46 base::JSONWriter::Write(&dict, &json); |
43 WebKit::WebCryptoAlgorithmIdHmac, | 47 return MakeJsonVector(json); |
44 new WebKit::WebCryptoHmacParams(CreateAlgorithm(hashId))); | |
45 } | 48 } |
46 | 49 |
47 WebKit::WebCryptoAlgorithm CreateHmacKeyAlgorithm( | 50 // Helper for ImportJwkBadJwk; restores JWK JSON dictionary to a good state |
48 WebKit::WebCryptoAlgorithmId hashId, | 51 void RestoreDictionaryForImportBadJwkTest(base::DictionaryValue* dict) { |
49 unsigned hash_length) { | 52 dict->Clear(); |
50 // hash_length < 0 means unspecified | 53 dict->SetString("kty", "oct"); |
51 return WebKit::WebCryptoAlgorithm::adoptParamsAndCreate( | 54 dict->SetString("alg", "A128CBC"); |
52 WebKit::WebCryptoAlgorithmIdHmac, | 55 dict->SetString("use", "enc"); |
53 new WebKit::WebCryptoHmacKeyParams(CreateAlgorithm(hashId), | 56 dict->SetBoolean("extractable", false); |
54 (hash_length != 0), | 57 dict->SetString("k", "GADWrMRHwQfoNaXU5fZvTg=="); |
55 hash_length)); | |
56 } | |
57 | |
58 // Returns a pointer to the start of |data|, or NULL if it is empty. This is a | |
59 // convenience function for getting the pointer, and should not be used beyond | |
60 // the expected lifetime of |data|. | |
61 const uint8* Start(const std::vector<uint8>& data) { | |
62 if (data.empty()) | |
63 return NULL; | |
64 return &data[0]; | |
65 } | |
66 | |
67 WebKit::WebCryptoAlgorithm CreateAesCbcAlgorithm( | |
68 const std::vector<uint8>& iv) { | |
69 return WebKit::WebCryptoAlgorithm::adoptParamsAndCreate( | |
70 WebKit::WebCryptoAlgorithmIdAesCbc, | |
71 new WebKit::WebCryptoAesCbcParams(Start(iv), iv.size())); | |
72 } | |
73 | |
74 WebKit::WebCryptoAlgorithm CreateAesCbcAlgorithm( | |
75 unsigned short key_length_bits) { | |
76 return WebKit::WebCryptoAlgorithm::adoptParamsAndCreate( | |
77 WebKit::WebCryptoAlgorithmIdAesCbc, | |
78 new WebKit::WebCryptoAesKeyGenParams(key_length_bits)); | |
79 } | 58 } |
80 | 59 |
81 WebKit::WebCryptoAlgorithm CreateRsaAlgorithm( | 60 WebKit::WebCryptoAlgorithm CreateRsaAlgorithm( |
82 WebKit::WebCryptoAlgorithmId algorithm_id, | 61 WebKit::WebCryptoAlgorithmId algorithm_id, |
83 unsigned modulus_length, | 62 unsigned modulus_length, |
84 const std::vector<uint8>& public_exponent) { | 63 const std::vector<uint8>& public_exponent) { |
85 DCHECK(algorithm_id == WebKit::WebCryptoAlgorithmIdRsaEsPkcs1v1_5 || | 64 DCHECK(algorithm_id == WebKit::WebCryptoAlgorithmIdRsaEsPkcs1v1_5 || |
86 algorithm_id == WebKit::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 || | 65 algorithm_id == WebKit::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 || |
87 algorithm_id == WebKit::WebCryptoAlgorithmIdRsaOaep); | 66 algorithm_id == WebKit::WebCryptoAlgorithmIdRsaOaep); |
88 return WebKit::WebCryptoAlgorithm::adoptParamsAndCreate( | 67 return WebKit::WebCryptoAlgorithm::adoptParamsAndCreate( |
89 algorithm_id, | 68 algorithm_id, |
90 new WebKit::WebCryptoRsaKeyGenParams( | 69 new WebKit::WebCryptoRsaKeyGenParams( |
91 modulus_length, Start(public_exponent), public_exponent.size())); | 70 modulus_length, |
| 71 Start(public_exponent), |
| 72 public_exponent.size())); |
92 } | 73 } |
93 | 74 |
94 } // namespace | 75 } // namespace |
95 | 76 |
96 namespace content { | |
97 | |
98 class WebCryptoImplTest : public testing::Test { | 77 class WebCryptoImplTest : public testing::Test { |
99 protected: | 78 protected: |
100 WebKit::WebCryptoKey ImportSecretKeyFromRawHexString( | 79 WebKit::WebCryptoKey ImportSecretKeyFromRawHexString( |
101 const std::string& key_hex, | 80 const std::string& key_hex, |
102 const WebKit::WebCryptoAlgorithm& algorithm, | 81 const WebKit::WebCryptoAlgorithm& algorithm, |
103 WebKit::WebCryptoKeyUsageMask usage) { | 82 WebKit::WebCryptoKeyUsageMask usage) { |
104 std::vector<uint8> key_raw = HexStringToBytes(key_hex); | 83 std::vector<uint8> key_raw = HexStringToBytes(key_hex); |
105 | 84 |
106 WebKit::WebCryptoKey key = WebKit::WebCryptoKey::createNull(); | 85 WebKit::WebCryptoKey key = WebKit::WebCryptoKey::createNull(); |
107 bool extractable = true; | 86 bool extractable = true; |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
216 | 195 |
217 bool DecryptInternal( | 196 bool DecryptInternal( |
218 const WebKit::WebCryptoAlgorithm& algorithm, | 197 const WebKit::WebCryptoAlgorithm& algorithm, |
219 const WebKit::WebCryptoKey& key, | 198 const WebKit::WebCryptoKey& key, |
220 const std::vector<uint8>& data, | 199 const std::vector<uint8>& data, |
221 WebKit::WebArrayBuffer* buffer) { | 200 WebKit::WebArrayBuffer* buffer) { |
222 return crypto_.DecryptInternal( | 201 return crypto_.DecryptInternal( |
223 algorithm, key, Start(data), data.size(), buffer); | 202 algorithm, key, Start(data), data.size(), buffer); |
224 } | 203 } |
225 | 204 |
| 205 bool ImportKeyJwk( |
| 206 const std::vector<uint8>& key_data, |
| 207 const WebKit::WebCryptoAlgorithm& algorithm, |
| 208 bool extractable, |
| 209 WebKit::WebCryptoKeyUsageMask usage_mask, |
| 210 WebKit::WebCryptoKey* key) { |
| 211 return crypto_.ImportKeyJwk(Start(key_data), |
| 212 key_data.size(), |
| 213 algorithm, |
| 214 extractable, |
| 215 usage_mask, |
| 216 key); |
| 217 } |
| 218 |
226 private: | 219 private: |
227 WebCryptoImpl crypto_; | 220 WebCryptoImpl crypto_; |
228 }; | 221 }; |
229 | 222 |
230 TEST_F(WebCryptoImplTest, DigestSampleSets) { | 223 TEST_F(WebCryptoImplTest, DigestSampleSets) { |
231 // The results are stored here in hex format for readability. | 224 // The results are stored here in hex format for readability. |
232 // | 225 // |
233 // TODO(bryaneyler): Eventually, all these sample test sets should be replaced | 226 // TODO(bryaneyler): Eventually, all these sample test sets should be replaced |
234 // with the sets here: http://csrc.nist.gov/groups/STM/cavp/index.html#03 | 227 // with the sets here: http://csrc.nist.gov/groups/STM/cavp/index.html#03 |
235 // | 228 // |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
394 // mac | 387 // mac |
395 "4f1ee7cb36c58803a8721d4ac8c4cf8cae5d8832392eed2a96dc59694252801b", | 388 "4f1ee7cb36c58803a8721d4ac8c4cf8cae5d8832392eed2a96dc59694252801b", |
396 }, | 389 }, |
397 }; | 390 }; |
398 | 391 |
399 for (size_t test_index = 0; test_index < ARRAYSIZE_UNSAFE(kTests); | 392 for (size_t test_index = 0; test_index < ARRAYSIZE_UNSAFE(kTests); |
400 ++test_index) { | 393 ++test_index) { |
401 SCOPED_TRACE(test_index); | 394 SCOPED_TRACE(test_index); |
402 const TestCase& test = kTests[test_index]; | 395 const TestCase& test = kTests[test_index]; |
403 | 396 |
404 WebKit::WebCryptoAlgorithm algorithm = CreateHmacAlgorithm(test.algorithm); | 397 WebKit::WebCryptoAlgorithm algorithm = |
| 398 CreateHmacAlgorithmByHashId(test.algorithm); |
405 | 399 |
406 WebKit::WebCryptoKey key = ImportSecretKeyFromRawHexString( | 400 WebKit::WebCryptoKey key = ImportSecretKeyFromRawHexString( |
407 test.key, algorithm, WebKit::WebCryptoKeyUsageSign); | 401 test.key, algorithm, WebKit::WebCryptoKeyUsageSign); |
408 | 402 |
409 std::vector<uint8> message_raw = HexStringToBytes(test.message); | 403 std::vector<uint8> message_raw = HexStringToBytes(test.message); |
410 | 404 |
411 WebKit::WebArrayBuffer output; | 405 WebKit::WebArrayBuffer output; |
412 | 406 |
413 ASSERT_TRUE(SignInternal(algorithm, key, message_raw, &output)); | 407 ASSERT_TRUE(SignInternal(algorithm, key, message_raw, &output)); |
414 | 408 |
(...skipping 25 matching lines...) Expand all Loading... |
440 algorithm, | 434 algorithm, |
441 key, | 435 key, |
442 kLongSignature, | 436 kLongSignature, |
443 sizeof(kLongSignature), | 437 sizeof(kLongSignature), |
444 message_raw, | 438 message_raw, |
445 &signature_match)); | 439 &signature_match)); |
446 EXPECT_FALSE(signature_match); | 440 EXPECT_FALSE(signature_match); |
447 } | 441 } |
448 } | 442 } |
449 | 443 |
| 444 #if !defined(USE_OPENSSL) |
| 445 |
450 TEST_F(WebCryptoImplTest, AesCbcFailures) { | 446 TEST_F(WebCryptoImplTest, AesCbcFailures) { |
451 WebKit::WebCryptoKey key = ImportSecretKeyFromRawHexString( | 447 WebKit::WebCryptoKey key = ImportSecretKeyFromRawHexString( |
452 "2b7e151628aed2a6abf7158809cf4f3c", | 448 "2b7e151628aed2a6abf7158809cf4f3c", |
453 CreateAlgorithm(WebKit::WebCryptoAlgorithmIdAesCbc), | 449 CreateAlgorithm(WebKit::WebCryptoAlgorithmIdAesCbc), |
454 WebKit::WebCryptoKeyUsageEncrypt | WebKit::WebCryptoKeyUsageDecrypt); | 450 WebKit::WebCryptoKeyUsageEncrypt | WebKit::WebCryptoKeyUsageDecrypt); |
455 | 451 |
456 WebKit::WebArrayBuffer output; | 452 WebKit::WebArrayBuffer output; |
457 | 453 |
458 // Use an invalid |iv| (fewer than 16 bytes) | 454 // Use an invalid |iv| (fewer than 16 bytes) |
459 { | 455 { |
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
635 &output)); | 631 &output)); |
636 } | 632 } |
637 } | 633 } |
638 } | 634 } |
639 | 635 |
640 // TODO (padolph): Add test to verify generated symmetric keys appear random. | 636 // TODO (padolph): Add test to verify generated symmetric keys appear random. |
641 | 637 |
642 | 638 |
643 TEST_F(WebCryptoImplTest, GenerateKeyAes) { | 639 TEST_F(WebCryptoImplTest, GenerateKeyAes) { |
644 WebKit::WebCryptoKey key = WebKit::WebCryptoKey::createNull(); | 640 WebKit::WebCryptoKey key = WebKit::WebCryptoKey::createNull(); |
645 ASSERT_TRUE(GenerateKeyInternal(CreateAesCbcAlgorithm(128), &key)); | 641 ASSERT_TRUE(GenerateKeyInternal(CreateAesCbcKeyGenAlgorithm(128), &key)); |
646 EXPECT_TRUE(key.handle()); | 642 EXPECT_TRUE(key.handle()); |
647 EXPECT_EQ(WebKit::WebCryptoKeyTypeSecret, key.type()); | 643 EXPECT_EQ(WebKit::WebCryptoKeyTypeSecret, key.type()); |
648 } | 644 } |
649 | 645 |
650 TEST_F(WebCryptoImplTest, GenerateKeyAesBadLength) { | 646 TEST_F(WebCryptoImplTest, GenerateKeyAesBadLength) { |
651 WebKit::WebCryptoKey key = WebKit::WebCryptoKey::createNull(); | 647 WebKit::WebCryptoKey key = WebKit::WebCryptoKey::createNull(); |
652 EXPECT_FALSE(GenerateKeyInternal(CreateAesCbcAlgorithm(0), &key)); | 648 EXPECT_FALSE( |
653 EXPECT_FALSE(GenerateKeyInternal(CreateAesCbcAlgorithm(129), &key)); | 649 GenerateKeyInternal(CreateAesCbcKeyGenAlgorithm(0), &key)); |
| 650 EXPECT_FALSE( |
| 651 GenerateKeyInternal(CreateAesCbcKeyGenAlgorithm(0), &key)); |
| 652 EXPECT_FALSE( |
| 653 GenerateKeyInternal(CreateAesCbcKeyGenAlgorithm(129), &key)); |
654 } | 654 } |
655 | 655 |
| 656 |
656 TEST_F(WebCryptoImplTest, GenerateKeyHmac) { | 657 TEST_F(WebCryptoImplTest, GenerateKeyHmac) { |
657 WebKit::WebCryptoKey key = WebKit::WebCryptoKey::createNull(); | 658 WebKit::WebCryptoKey key = WebKit::WebCryptoKey::createNull(); |
658 WebKit::WebCryptoAlgorithm algorithm = | 659 WebKit::WebCryptoAlgorithm algorithm = |
659 CreateHmacKeyAlgorithm(WebKit::WebCryptoAlgorithmIdSha1, 128); | 660 CreateHmacKeyGenAlgorithm(WebKit::WebCryptoAlgorithmIdSha1, 128); |
660 ASSERT_TRUE(GenerateKeyInternal(algorithm, &key)); | 661 ASSERT_TRUE(GenerateKeyInternal(algorithm, &key)); |
661 EXPECT_TRUE(key.handle()); | 662 EXPECT_TRUE(key.handle()); |
662 EXPECT_EQ(WebKit::WebCryptoKeyTypeSecret, key.type()); | 663 EXPECT_EQ(WebKit::WebCryptoKeyTypeSecret, key.type()); |
663 } | 664 } |
664 | 665 |
665 TEST_F(WebCryptoImplTest, GenerateKeyHmacNoLength) { | 666 TEST_F(WebCryptoImplTest, GenerateKeyHmacNoLength) { |
666 WebKit::WebCryptoKey key = WebKit::WebCryptoKey::createNull(); | 667 WebKit::WebCryptoKey key = WebKit::WebCryptoKey::createNull(); |
667 WebKit::WebCryptoAlgorithm algorithm = | 668 WebKit::WebCryptoAlgorithm algorithm = |
668 CreateHmacKeyAlgorithm(WebKit::WebCryptoAlgorithmIdSha1, 0); | 669 CreateHmacKeyGenAlgorithm(WebKit::WebCryptoAlgorithmIdSha1, 0); |
669 ASSERT_TRUE(GenerateKeyInternal(algorithm, &key)); | 670 ASSERT_TRUE(GenerateKeyInternal(algorithm, &key)); |
670 EXPECT_TRUE(key.handle()); | 671 EXPECT_TRUE(key.handle()); |
671 EXPECT_EQ(WebKit::WebCryptoKeyTypeSecret, key.type()); | 672 EXPECT_EQ(WebKit::WebCryptoKeyTypeSecret, key.type()); |
672 } | 673 } |
673 | 674 |
674 TEST_F(WebCryptoImplTest, ImportSecretKeyNoAlgorithm) { | 675 TEST_F(WebCryptoImplTest, ImportSecretKeyNoAlgorithm) { |
675 WebKit::WebCryptoKey key = WebKit::WebCryptoKey::createNull(); | 676 WebKit::WebCryptoKey key = WebKit::WebCryptoKey::createNull(); |
676 | 677 |
677 // This fails because the algorithm is null. | 678 // This fails because the algorithm is null. |
678 EXPECT_FALSE(ImportKeyInternal( | 679 EXPECT_FALSE(ImportKeyInternal( |
679 WebKit::WebCryptoKeyFormatRaw, | 680 WebKit::WebCryptoKeyFormatRaw, |
680 HexStringToBytes("00000000000000000000"), | 681 HexStringToBytes("00000000000000000000"), |
681 WebKit::WebCryptoAlgorithm::createNull(), | 682 WebKit::WebCryptoAlgorithm::createNull(), |
682 WebKit::WebCryptoKeyUsageSign, | 683 WebKit::WebCryptoKeyUsageSign, |
683 &key)); | 684 &key)); |
684 } | 685 } |
685 | 686 |
| 687 #endif //#if !defined(USE_OPENSSL) |
| 688 |
| 689 TEST_F(WebCryptoImplTest, ImportJwkBadJwk) { |
| 690 |
| 691 WebKit::WebCryptoKey key = WebKit::WebCryptoKey::createNull(); |
| 692 WebKit::WebCryptoAlgorithm algorithm = |
| 693 CreateAlgorithm(WebKit::WebCryptoAlgorithmIdAesCbc); |
| 694 WebKit::WebCryptoKeyUsageMask usage_mask = WebKit::WebCryptoKeyUsageEncrypt; |
| 695 |
| 696 // Baseline pass: each test below breaks a single item, so we start with a |
| 697 // passing case to make sure each failure is caused by the isolated break. |
| 698 // Each breaking subtest below resets the dictionary to this passing case when |
| 699 // complete. |
| 700 base::DictionaryValue dict; |
| 701 RestoreDictionaryForImportBadJwkTest(&dict); |
| 702 std::vector<uint8> json_vec = MakeJsonVector(dict); |
| 703 EXPECT_TRUE(ImportKeyJwk(json_vec, algorithm, false, usage_mask, &key)); |
| 704 |
| 705 // Fail on empty JSON. |
| 706 EXPECT_FALSE(ImportKeyJwk( |
| 707 MakeJsonVector(""), algorithm, false, usage_mask, &key)); |
| 708 |
| 709 // Fail on invalid JSON. |
| 710 const std::vector<uint8> bad_json_vec = MakeJsonVector( |
| 711 "{" |
| 712 "\"kty\" : \"oct\"," |
| 713 "\"alg\" : \"HS256\"," |
| 714 "\"use\" : " |
| 715 ); |
| 716 EXPECT_FALSE(ImportKeyJwk(bad_json_vec, algorithm, false, usage_mask, &key)); |
| 717 |
| 718 // Fail on JWK alg present but unrecognized. |
| 719 dict.SetString("alg", "A127CBC"); |
| 720 json_vec = MakeJsonVector(dict); |
| 721 EXPECT_FALSE(ImportKeyJwk(json_vec, algorithm, false, usage_mask, &key)); |
| 722 RestoreDictionaryForImportBadJwkTest(&dict); |
| 723 |
| 724 // Fail on both JWK and input algorithm missing. |
| 725 dict.Remove("alg", NULL); |
| 726 json_vec = MakeJsonVector(dict); |
| 727 EXPECT_FALSE(ImportKeyJwk(json_vec, |
| 728 WebKit::WebCryptoAlgorithm::createNull(), |
| 729 false, |
| 730 usage_mask, |
| 731 &key)); |
| 732 RestoreDictionaryForImportBadJwkTest(&dict); |
| 733 |
| 734 // Fail on invalid kty. |
| 735 dict.SetString("kty", "foo"); |
| 736 json_vec = MakeJsonVector(dict); |
| 737 EXPECT_FALSE(ImportKeyJwk(json_vec, algorithm, false, usage_mask, &key)); |
| 738 RestoreDictionaryForImportBadJwkTest(&dict); |
| 739 |
| 740 // Fail on missing kty. |
| 741 dict.Remove("kty", NULL); |
| 742 json_vec = MakeJsonVector(dict); |
| 743 EXPECT_FALSE(ImportKeyJwk(json_vec, algorithm, false, usage_mask, &key)); |
| 744 RestoreDictionaryForImportBadJwkTest(&dict); |
| 745 |
| 746 // Fail on invalid use. |
| 747 dict.SetString("use", "foo"); |
| 748 json_vec = MakeJsonVector(dict); |
| 749 EXPECT_FALSE(ImportKeyJwk(json_vec, algorithm, false, usage_mask, &key)); |
| 750 RestoreDictionaryForImportBadJwkTest(&dict); |
| 751 |
| 752 // Fail on missing k when kty = "oct". |
| 753 dict.Remove("k", NULL); |
| 754 json_vec = MakeJsonVector(dict); |
| 755 EXPECT_FALSE(ImportKeyJwk(json_vec, algorithm, false, usage_mask, &key)); |
| 756 RestoreDictionaryForImportBadJwkTest(&dict); |
| 757 |
| 758 // Fail on bad b64 encoding for k. |
| 759 dict.SetString("k", "Qk3f0DsytU8lfza2au #$% Htaw2xpop9GYyTuH0p5GghxTI="); |
| 760 json_vec = MakeJsonVector(dict); |
| 761 EXPECT_FALSE(ImportKeyJwk(json_vec, algorithm, false, usage_mask, &key)); |
| 762 RestoreDictionaryForImportBadJwkTest(&dict); |
| 763 |
| 764 // Fail on empty k. |
| 765 dict.SetString("k", ""); |
| 766 json_vec = MakeJsonVector(dict); |
| 767 EXPECT_FALSE(ImportKeyJwk(json_vec, algorithm, false, usage_mask, &key)); |
| 768 RestoreDictionaryForImportBadJwkTest(&dict); |
| 769 |
| 770 // Fail on k actual length (120 bits) inconsistent with the embedded JWK alg |
| 771 // value (128) for an AES key. |
| 772 dict.SetString("k", "AVj42h0Y5aqGtE3yluKL"); |
| 773 json_vec = MakeJsonVector(dict); |
| 774 EXPECT_FALSE(ImportKeyJwk(json_vec, algorithm, false, usage_mask, &key)); |
| 775 RestoreDictionaryForImportBadJwkTest(&dict); |
| 776 |
| 777 // TODO(padolph) RSA public key bad data: |
| 778 // Missing n or e when kty = "RSA" |
| 779 // Bad encoding for n or e |
| 780 // Size check on n?? |
| 781 // Value check on e?? |
| 782 } |
| 783 |
| 784 TEST_F(WebCryptoImplTest, ImportJwkInputConsistency) { |
| 785 // The Web Crypto spec says that if a JWK value is present, but is |
| 786 // inconsistent with the input value, the operation must fail. |
| 787 |
| 788 // Consistency rules when JWK value is not present: Inputs should be used. |
| 789 WebKit::WebCryptoKey key = WebKit::WebCryptoKey::createNull(); |
| 790 bool extractable = false; |
| 791 WebKit::WebCryptoAlgorithm algorithm = |
| 792 CreateHmacAlgorithmByHashId(WebKit::WebCryptoAlgorithmIdSha256); |
| 793 WebKit::WebCryptoKeyUsageMask usage_mask = WebKit::WebCryptoKeyUsageVerify; |
| 794 base::DictionaryValue dict; |
| 795 dict.SetString("kty", "oct"); |
| 796 dict.SetString("k", "l3nZEgZCeX8XRwJdWyK3rGB8qwjhdY8vOkbIvh4lxTuMao9Y_--hdg"); |
| 797 std::vector<uint8> json_vec = MakeJsonVector(dict); |
| 798 EXPECT_TRUE(ImportKeyJwk(json_vec, algorithm, extractable, usage_mask, &key)); |
| 799 EXPECT_TRUE(key.handle()); |
| 800 EXPECT_EQ(WebKit::WebCryptoKeyTypeSecret, key.type()); |
| 801 EXPECT_EQ(extractable, key.extractable()); |
| 802 EXPECT_EQ(WebKit::WebCryptoAlgorithmIdHmac, key.algorithm().id()); |
| 803 EXPECT_EQ(WebKit::WebCryptoAlgorithmIdSha256, |
| 804 key.algorithm().hmacParams()->hash().id()); |
| 805 EXPECT_EQ(WebKit::WebCryptoKeyUsageVerify, key.usages()); |
| 806 key = WebKit::WebCryptoKey::createNull(); |
| 807 |
| 808 // Consistency rules when JWK value exists: Fail if inconsistency is found. |
| 809 |
| 810 // Pass: All input values are consistent with the JWK values. |
| 811 dict.Clear(); |
| 812 dict.SetString("kty", "oct"); |
| 813 dict.SetString("alg", "HS256"); |
| 814 dict.SetString("use", "sig"); |
| 815 dict.SetBoolean("extractable", false); |
| 816 dict.SetString("k", "l3nZEgZCeX8XRwJdWyK3rGB8qwjhdY8vOkbIvh4lxTuMao9Y_--hdg"); |
| 817 json_vec = MakeJsonVector(dict); |
| 818 EXPECT_TRUE(ImportKeyJwk( |
| 819 json_vec, algorithm, extractable, usage_mask, &key)); |
| 820 |
| 821 // Extractable cases: |
| 822 // 1. input=T, JWK=F ==> fail (inconsistent) |
| 823 // 4. input=F, JWK=F ==> pass, result extractable is F |
| 824 // 2. input=T, JWK=T ==> pass, result extractable is T |
| 825 // 3. input=F, JWK=T ==> pass, result extractable is F |
| 826 EXPECT_FALSE( |
| 827 ImportKeyJwk(json_vec, algorithm, true, usage_mask, &key)); |
| 828 EXPECT_TRUE( |
| 829 ImportKeyJwk(json_vec, algorithm, false, usage_mask, &key)); |
| 830 EXPECT_FALSE(key.extractable()); |
| 831 dict.SetBoolean("extractable", true); |
| 832 EXPECT_TRUE( |
| 833 ImportKeyJwk(MakeJsonVector(dict), algorithm, true, usage_mask, &key)); |
| 834 EXPECT_TRUE(key.extractable()); |
| 835 EXPECT_TRUE( |
| 836 ImportKeyJwk(MakeJsonVector(dict), algorithm, false, usage_mask, &key)); |
| 837 EXPECT_FALSE(key.extractable()); |
| 838 dict.SetBoolean("extractable", true); // restore previous value |
| 839 |
| 840 // Fail: Input algorithm (AES-CBC) is inconsistent with JWK value |
| 841 // (HMAC SHA256). |
| 842 EXPECT_FALSE(ImportKeyJwk(json_vec, |
| 843 CreateAlgorithm(WebKit::WebCryptoAlgorithmIdAesCbc), |
| 844 extractable, |
| 845 usage_mask, |
| 846 &key)); |
| 847 |
| 848 // Fail: Input algorithm (HMAC SHA1) is inconsistent with JWK value |
| 849 // (HMAC SHA256). |
| 850 EXPECT_FALSE(ImportKeyJwk( |
| 851 json_vec, |
| 852 CreateHmacAlgorithmByHashId(WebKit::WebCryptoAlgorithmIdSha1), |
| 853 extractable, |
| 854 usage_mask, |
| 855 &key)); |
| 856 |
| 857 // Pass: JWK alg valid but input algorithm isNull: use JWK algorithm value. |
| 858 EXPECT_TRUE(ImportKeyJwk(json_vec, |
| 859 WebKit::WebCryptoAlgorithm::createNull(), |
| 860 extractable, |
| 861 usage_mask, |
| 862 &key)); |
| 863 EXPECT_EQ(WebKit::WebCryptoAlgorithmIdHmac, algorithm.id()); |
| 864 |
| 865 // Pass: JWK alg missing but input algorithm specified: use input value |
| 866 dict.Remove("alg", NULL); |
| 867 EXPECT_TRUE(ImportKeyJwk( |
| 868 MakeJsonVector(dict), |
| 869 CreateHmacAlgorithmByHashId(WebKit::WebCryptoAlgorithmIdSha256), |
| 870 extractable, |
| 871 usage_mask, |
| 872 &key)); |
| 873 EXPECT_EQ(WebKit::WebCryptoAlgorithmIdHmac, algorithm.id()); |
| 874 dict.SetString("alg", "HS256"); |
| 875 |
| 876 // Fail: Input usage_mask (encrypt) is not a subset of the JWK value |
| 877 // (sign|verify) |
| 878 EXPECT_FALSE(ImportKeyJwk(json_vec, |
| 879 algorithm, |
| 880 extractable, |
| 881 WebKit::WebCryptoKeyUsageEncrypt, |
| 882 &key)); |
| 883 |
| 884 // Fail: Input usage_mask (encrypt|sign|verify) is not a subset of the JWK |
| 885 // value (sign|verify) |
| 886 usage_mask = WebKit::WebCryptoKeyUsageEncrypt | |
| 887 WebKit::WebCryptoKeyUsageSign | WebKit::WebCryptoKeyUsageVerify; |
| 888 EXPECT_FALSE(ImportKeyJwk( |
| 889 json_vec, algorithm, extractable, usage_mask, &key)); |
| 890 usage_mask = WebKit::WebCryptoKeyUsageSign | WebKit::WebCryptoKeyUsageVerify; |
| 891 } |
| 892 |
| 893 TEST_F(WebCryptoImplTest, ImportJwkHappy) { |
| 894 |
| 895 // This test verifies the happy path of JWK import, including the application |
| 896 // of the imported key material. |
| 897 |
| 898 WebKit::WebCryptoKey key = WebKit::WebCryptoKey::createNull(); |
| 899 bool extractable = false; |
| 900 WebKit::WebCryptoAlgorithm algorithm = |
| 901 CreateHmacAlgorithmByHashId(WebKit::WebCryptoAlgorithmIdSha256); |
| 902 WebKit::WebCryptoKeyUsageMask usage_mask = WebKit::WebCryptoKeyUsageSign; |
| 903 |
| 904 // Import a symmetric key JWK and HMAC-SHA256 sign() |
| 905 // Uses the first SHA256 test vector from the HMAC sample set above. |
| 906 |
| 907 base::DictionaryValue dict; |
| 908 dict.SetString("kty", "oct"); |
| 909 dict.SetString("alg", "HS256"); |
| 910 dict.SetString("use", "sig"); |
| 911 dict.SetBoolean("extractable", false); |
| 912 dict.SetString("k", "l3nZEgZCeX8XRwJdWyK3rGB8qwjhdY8vOkbIvh4lxTuMao9Y_--hdg"); |
| 913 std::vector<uint8> json_vec = MakeJsonVector(dict); |
| 914 |
| 915 ASSERT_TRUE(ImportKeyJwk( |
| 916 json_vec, algorithm, extractable, usage_mask, &key)); |
| 917 |
| 918 const std::vector<uint8> message_raw = HexStringToBytes( |
| 919 "b1689c2591eaf3c9e66070f8a77954ffb81749f1b00346f9dfe0b2ee905dcc288baf4a" |
| 920 "92de3f4001dd9f44c468c3d07d6c6ee82faceafc97c2fc0fc0601719d2dcd0aa2aec92" |
| 921 "d1b0ae933c65eb06a03c9c935c2bad0459810241347ab87e9f11adb30415424c6c7f5f" |
| 922 "22a003b8ab8de54f6ded0e3ab9245fa79568451dfa258e"); |
| 923 |
| 924 WebKit::WebArrayBuffer output; |
| 925 |
| 926 ASSERT_TRUE(SignInternal(algorithm, key, message_raw, &output)); |
| 927 |
| 928 const std::string mac_raw = |
| 929 "769f00d3e6a6cc1fb426a14a4f76c6462e6149726e0dee0ec0cf97a16605ac8b"; |
| 930 |
| 931 ExpectArrayBufferMatchesHex(mac_raw, output); |
| 932 |
| 933 // TODO(padolph) |
| 934 // Import an RSA public key JWK and use it |
| 935 } |
| 936 |
686 #if !defined(USE_OPENSSL) | 937 #if !defined(USE_OPENSSL) |
687 | 938 |
688 TEST_F(WebCryptoImplTest, GenerateKeyPairRsa) { | 939 TEST_F(WebCryptoImplTest, GenerateKeyPairRsa) { |
689 | 940 |
690 // Note: using unrealistic short key lengths here to avoid bogging down tests. | 941 // Note: using unrealistic short key lengths here to avoid bogging down tests. |
691 | 942 |
692 // Successful WebCryptoAlgorithmIdRsaEsPkcs1v1_5 key generation. | 943 // Successful WebCryptoAlgorithmIdRsaEsPkcs1v1_5 key generation. |
693 const unsigned modulus_length = 256; | 944 const unsigned modulus_length = 256; |
694 const std::vector<uint8> public_exponent = HexStringToBytes("010001"); | 945 const std::vector<uint8> public_exponent = HexStringToBytes("010001"); |
695 WebKit::WebCryptoAlgorithm algorithm = | 946 WebKit::WebCryptoAlgorithm algorithm = |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
786 EXPECT_EQ(WebKit::WebCryptoKeyTypePrivate, private_key.type()); | 1037 EXPECT_EQ(WebKit::WebCryptoKeyTypePrivate, private_key.type()); |
787 EXPECT_EQ(extractable, public_key.extractable()); | 1038 EXPECT_EQ(extractable, public_key.extractable()); |
788 EXPECT_EQ(extractable, private_key.extractable()); | 1039 EXPECT_EQ(extractable, private_key.extractable()); |
789 EXPECT_EQ(usage_mask, public_key.usages()); | 1040 EXPECT_EQ(usage_mask, public_key.usages()); |
790 EXPECT_EQ(usage_mask, private_key.usages()); | 1041 EXPECT_EQ(usage_mask, private_key.usages()); |
791 } | 1042 } |
792 | 1043 |
793 #endif // #if !defined(USE_OPENSSL) | 1044 #endif // #if !defined(USE_OPENSSL) |
794 | 1045 |
795 } // namespace content | 1046 } // namespace content |
OLD | NEW |