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 | |
46 WebKit::WebCryptoAlgorithm CreateHmacKeyAlgorithm( | |
47 WebKit::WebCryptoAlgorithmId hashId, | |
48 unsigned hash_length) { | |
49 // hash_length < 0 means unspecified | |
50 return WebKit::WebCryptoAlgorithm::adoptParamsAndCreate( | |
51 WebKit::WebCryptoAlgorithmIdHmac, | |
52 new WebKit::WebCryptoHmacKeyParams(CreateAlgorithm(hashId), | |
53 (hash_length != 0), | |
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 } | 45 } |
79 | 46 |
80 } // namespace | 47 } // namespace |
81 | 48 |
82 namespace content { | 49 namespace content { |
83 | 50 |
84 class WebCryptoImplTest : public testing::Test { | 51 class WebCryptoImplTest : public testing::Test { |
85 protected: | 52 protected: |
86 WebKit::WebCryptoKey ImportSecretKeyFromRawHexString( | 53 WebKit::WebCryptoKey ImportSecretKeyFromRawHexString( |
87 const std::string& key_hex, | 54 const std::string& key_hex, |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
194 | 161 |
195 bool DecryptInternal( | 162 bool DecryptInternal( |
196 const WebKit::WebCryptoAlgorithm& algorithm, | 163 const WebKit::WebCryptoAlgorithm& algorithm, |
197 const WebKit::WebCryptoKey& key, | 164 const WebKit::WebCryptoKey& key, |
198 const std::vector<uint8>& data, | 165 const std::vector<uint8>& data, |
199 WebKit::WebArrayBuffer* buffer) { | 166 WebKit::WebArrayBuffer* buffer) { |
200 return crypto_.DecryptInternal( | 167 return crypto_.DecryptInternal( |
201 algorithm, key, Start(data), data.size(), buffer); | 168 algorithm, key, Start(data), data.size(), buffer); |
202 } | 169 } |
203 | 170 |
171 bool ImportKeyJwk( | |
172 const std::vector<uint8>& key_data, | |
173 bool extractable, | |
174 const WebKit::WebCryptoAlgorithm& algorithm, | |
175 WebKit::WebCryptoKeyUsageMask usage_mask, | |
176 scoped_ptr<WebKit::WebCryptoKeyHandle>* handle, | |
177 WebKit::WebCryptoKeyType* type) { | |
178 return crypto_.ImportKeyJwk(Start(key_data), | |
179 key_data.size(), | |
180 extractable, | |
181 algorithm, | |
182 usage_mask, | |
183 handle, | |
184 type); | |
185 } | |
186 | |
204 private: | 187 private: |
205 WebCryptoImpl crypto_; | 188 WebCryptoImpl crypto_; |
206 }; | 189 }; |
207 | 190 |
208 TEST_F(WebCryptoImplTest, DigestSampleSets) { | 191 TEST_F(WebCryptoImplTest, DigestSampleSets) { |
209 // The results are stored here in hex format for readability. | 192 // The results are stored here in hex format for readability. |
210 // | 193 // |
211 // TODO(bryaneyler): Eventually, all these sample test sets should be replaced | 194 // TODO(bryaneyler): Eventually, all these sample test sets should be replaced |
212 // with the sets here: http://csrc.nist.gov/groups/STM/cavp/index.html#03 | 195 // with the sets here: http://csrc.nist.gov/groups/STM/cavp/index.html#03 |
213 // | 196 // |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
372 // mac | 355 // mac |
373 "4f1ee7cb36c58803a8721d4ac8c4cf8cae5d8832392eed2a96dc59694252801b", | 356 "4f1ee7cb36c58803a8721d4ac8c4cf8cae5d8832392eed2a96dc59694252801b", |
374 }, | 357 }, |
375 }; | 358 }; |
376 | 359 |
377 for (size_t test_index = 0; test_index < ARRAYSIZE_UNSAFE(kTests); | 360 for (size_t test_index = 0; test_index < ARRAYSIZE_UNSAFE(kTests); |
378 ++test_index) { | 361 ++test_index) { |
379 SCOPED_TRACE(test_index); | 362 SCOPED_TRACE(test_index); |
380 const TestCase& test = kTests[test_index]; | 363 const TestCase& test = kTests[test_index]; |
381 | 364 |
382 WebKit::WebCryptoAlgorithm algorithm = CreateHmacAlgorithm(test.algorithm); | 365 WebKit::WebCryptoAlgorithm algorithm = |
366 CreateHmacAlgorithmByHashId(test.algorithm); | |
383 | 367 |
384 WebKit::WebCryptoKey key = ImportSecretKeyFromRawHexString( | 368 WebKit::WebCryptoKey key = ImportSecretKeyFromRawHexString( |
385 test.key, algorithm, WebKit::WebCryptoKeyUsageSign); | 369 test.key, algorithm, WebKit::WebCryptoKeyUsageSign); |
386 | 370 |
387 std::vector<uint8> message_raw = HexStringToBytes(test.message); | 371 std::vector<uint8> message_raw = HexStringToBytes(test.message); |
388 | 372 |
389 WebKit::WebArrayBuffer output; | 373 WebKit::WebArrayBuffer output; |
390 | 374 |
391 ASSERT_TRUE(SignInternal(algorithm, key, message_raw, &output)); | 375 ASSERT_TRUE(SignInternal(algorithm, key, message_raw, &output)); |
392 | 376 |
(...skipping 25 matching lines...) Expand all Loading... | |
418 algorithm, | 402 algorithm, |
419 key, | 403 key, |
420 kLongSignature, | 404 kLongSignature, |
421 sizeof(kLongSignature), | 405 sizeof(kLongSignature), |
422 message_raw, | 406 message_raw, |
423 &signature_match)); | 407 &signature_match)); |
424 EXPECT_FALSE(signature_match); | 408 EXPECT_FALSE(signature_match); |
425 } | 409 } |
426 } | 410 } |
427 | 411 |
412 #if !defined(USE_OPENSSL) | |
413 | |
428 TEST_F(WebCryptoImplTest, AesCbcFailures) { | 414 TEST_F(WebCryptoImplTest, AesCbcFailures) { |
429 WebKit::WebCryptoKey key = ImportSecretKeyFromRawHexString( | 415 WebKit::WebCryptoKey key = ImportSecretKeyFromRawHexString( |
430 "2b7e151628aed2a6abf7158809cf4f3c", | 416 "2b7e151628aed2a6abf7158809cf4f3c", |
431 CreateAlgorithm(WebKit::WebCryptoAlgorithmIdAesCbc), | 417 CreateAlgorithm(WebKit::WebCryptoAlgorithmIdAesCbc), |
432 WebKit::WebCryptoKeyUsageEncrypt | WebKit::WebCryptoKeyUsageDecrypt); | 418 WebKit::WebCryptoKeyUsageEncrypt | WebKit::WebCryptoKeyUsageDecrypt); |
433 | 419 |
434 WebKit::WebArrayBuffer output; | 420 WebKit::WebArrayBuffer output; |
435 | 421 |
436 // Use an invalid |iv| (fewer than 16 bytes) | 422 // Use an invalid |iv| (fewer than 16 bytes) |
437 { | 423 { |
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
613 key, | 599 key, |
614 &cipher_text[0], | 600 &cipher_text[0], |
615 cipher_text.size() - 3, | 601 cipher_text.size() - 3, |
616 &output)); | 602 &output)); |
617 } | 603 } |
618 } | 604 } |
619 } | 605 } |
620 | 606 |
621 // TODO (padolph): Add test to verify generated symmetric keys appear random. | 607 // TODO (padolph): Add test to verify generated symmetric keys appear random. |
622 | 608 |
623 | |
624 TEST_F(WebCryptoImplTest, GenerateKeyAes) { | 609 TEST_F(WebCryptoImplTest, GenerateKeyAes) { |
625 scoped_ptr<WebKit::WebCryptoKeyHandle> result; | 610 scoped_ptr<WebKit::WebCryptoKeyHandle> result; |
626 WebKit::WebCryptoKeyType type = WebKit::WebCryptoKeyTypePublic; | 611 WebKit::WebCryptoKeyType type = WebKit::WebCryptoKeyTypePublic; |
627 ASSERT_TRUE(GenerateKeyInternal(CreateAesCbcAlgorithm(128), &result, &type)); | 612 ASSERT_TRUE( |
613 GenerateKeyInternal(CreateAesCbcKeyGenAlgorithm(128), &result, &type)); | |
628 EXPECT_TRUE(result); | 614 EXPECT_TRUE(result); |
629 EXPECT_EQ(type, WebKit::WebCryptoKeyTypeSecret); | 615 EXPECT_EQ(type, WebKit::WebCryptoKeyTypeSecret); |
630 } | 616 } |
631 | 617 |
632 TEST_F(WebCryptoImplTest, GenerateKeyAesBadLength) { | 618 TEST_F(WebCryptoImplTest, GenerateKeyAesBadLength) { |
633 scoped_ptr<WebKit::WebCryptoKeyHandle> result; | 619 scoped_ptr<WebKit::WebCryptoKeyHandle> result; |
634 WebKit::WebCryptoKeyType type = WebKit::WebCryptoKeyTypePublic; | 620 WebKit::WebCryptoKeyType type = WebKit::WebCryptoKeyTypePublic; |
635 EXPECT_FALSE(GenerateKeyInternal(CreateAesCbcAlgorithm(0), &result, &type)); | 621 EXPECT_FALSE( |
636 EXPECT_FALSE(GenerateKeyInternal(CreateAesCbcAlgorithm(129), &result, &type)); | 622 GenerateKeyInternal(CreateAesCbcKeyGenAlgorithm(0), &result, &type)); |
623 EXPECT_FALSE( | |
624 GenerateKeyInternal(CreateAesCbcKeyGenAlgorithm(129), &result, &type)); | |
637 } | 625 } |
638 | 626 |
627 | |
639 TEST_F(WebCryptoImplTest, GenerateKeyHmac) { | 628 TEST_F(WebCryptoImplTest, GenerateKeyHmac) { |
640 scoped_ptr<WebKit::WebCryptoKeyHandle> result; | 629 scoped_ptr<WebKit::WebCryptoKeyHandle> result; |
641 WebKit::WebCryptoKeyType type = WebKit::WebCryptoKeyTypePublic; | 630 WebKit::WebCryptoKeyType type = WebKit::WebCryptoKeyTypePublic; |
642 WebKit::WebCryptoAlgorithm algorithm = | 631 WebKit::WebCryptoAlgorithm algorithm = |
643 CreateHmacKeyAlgorithm(WebKit::WebCryptoAlgorithmIdSha1, 128); | 632 CreateHmacKeyGenAlgorithm(WebKit::WebCryptoAlgorithmIdSha1, 128); |
644 ASSERT_TRUE(GenerateKeyInternal(algorithm, &result, &type)); | 633 ASSERT_TRUE(GenerateKeyInternal(algorithm, &result, &type)); |
645 EXPECT_TRUE(result); | 634 EXPECT_TRUE(result); |
646 EXPECT_EQ(type, WebKit::WebCryptoKeyTypeSecret); | 635 EXPECT_EQ(type, WebKit::WebCryptoKeyTypeSecret); |
647 } | 636 } |
648 | 637 |
649 TEST_F(WebCryptoImplTest, GenerateKeyHmacNoLength) { | 638 TEST_F(WebCryptoImplTest, GenerateKeyHmacNoLength) { |
650 scoped_ptr<WebKit::WebCryptoKeyHandle> result; | 639 scoped_ptr<WebKit::WebCryptoKeyHandle> result; |
651 WebKit::WebCryptoKeyType type = WebKit::WebCryptoKeyTypePublic; | 640 WebKit::WebCryptoKeyType type = WebKit::WebCryptoKeyTypePublic; |
652 WebKit::WebCryptoAlgorithm algorithm = | 641 WebKit::WebCryptoAlgorithm algorithm = |
653 CreateHmacKeyAlgorithm(WebKit::WebCryptoAlgorithmIdSha1, 0); | 642 CreateHmacKeyGenAlgorithm(WebKit::WebCryptoAlgorithmIdSha1, 0); |
654 ASSERT_TRUE(GenerateKeyInternal(algorithm, &result, &type)); | 643 ASSERT_TRUE(GenerateKeyInternal(algorithm, &result, &type)); |
655 EXPECT_TRUE(result); | 644 EXPECT_TRUE(result); |
656 EXPECT_EQ(type, WebKit::WebCryptoKeyTypeSecret); | 645 EXPECT_EQ(type, WebKit::WebCryptoKeyTypeSecret); |
657 } | 646 } |
658 | 647 |
648 #endif //#if !defined(USE_OPENSSL) | |
649 | |
650 TEST_F(WebCryptoImplTest, ImportJwkBadJwk) { | |
651 | |
652 WebKit::WebCryptoKeyType type = WebKit::WebCryptoKeyTypeSecret; | |
653 scoped_ptr<WebKit::WebCryptoKeyHandle> handle; | |
654 WebKit::WebCryptoAlgorithm algorithm = CreateHmacAlgorithmByKeyLen(256); | |
655 const bool extractable = false; | |
656 WebKit::WebCryptoKeyUsageMask usage_mask = WebKit::WebCryptoKeyUsageSign; | |
657 | |
658 // Baseline pass: each test below breaks a single item, so we start with a | |
659 // passing case to make sure each failure caused by the isolated break. Each | |
660 // breaking subtest below resets the dictionary to this passing case when | |
661 // complete. | |
662 const std::string key_val("oct"); | |
663 const std::string alg_val("HS256"); | |
664 const std::string use_val("sig"); | |
665 const std::string k_val("Qk3f0DsytU8lfza2auHtaw2xpop9GYyTuH0p5GghxTI="); | |
666 base::DictionaryValue dict; | |
667 dict.SetString("kty", key_val); | |
668 dict.SetString("alg", alg_val); | |
669 dict.SetString("use", use_val); | |
670 dict.SetBoolean("extractable", extractable); | |
671 dict.SetString("k", k_val); | |
672 std::vector<uint8> json_vec = MakeJsonVector(dict); | |
673 EXPECT_TRUE(ImportKeyJwk( | |
674 json_vec, extractable, algorithm, usage_mask, &handle, &type)); | |
675 | |
676 // Fail on empty JSON. | |
677 EXPECT_FALSE(ImportKeyJwk( | |
678 MakeJsonVector(""), extractable, algorithm, usage_mask, &handle, &type)); | |
679 | |
680 // Fail on invalid JSON. | |
681 const std::vector<uint8> bad_json_vec = MakeJsonVector( | |
682 "{" | |
683 "\"kty\" : \"oct\"," | |
684 "\"alg\" : \"HS256\"," | |
685 "\"use\" : " | |
686 ); | |
687 EXPECT_FALSE(ImportKeyJwk( | |
688 bad_json_vec, extractable, algorithm, usage_mask, &handle, &type)); | |
689 | |
690 // Fail on Null input algorithm. | |
691 EXPECT_FALSE(ImportKeyJwk(json_vec, | |
692 extractable, | |
693 WebKit::WebCryptoAlgorithm::createNull(), | |
694 usage_mask, | |
695 &handle, | |
696 &type)); | |
697 | |
698 // Fail on Null input handle pointer. | |
699 EXPECT_FALSE( | |
700 ImportKeyJwk(json_vec, extractable, algorithm, usage_mask, NULL, &type)); | |
701 | |
702 // Fail on Null input type pointer. | |
703 EXPECT_FALSE(ImportKeyJwk( | |
704 json_vec, extractable, algorithm, usage_mask, &handle, NULL)); | |
705 | |
706 // Fail on input algorithm mismatch. | |
707 EXPECT_FALSE(ImportKeyJwk(json_vec, | |
708 extractable, | |
709 CreateAlgorithm(WebKit::WebCryptoAlgorithmIdAesCbc), | |
710 usage_mask, | |
711 &handle, | |
712 &type)); | |
713 | |
714 // Fail on input algorithm mismatch (inner hash algorithm). | |
715 EXPECT_FALSE(ImportKeyJwk(json_vec, | |
716 extractable, | |
717 CreateHmacAlgorithmByKeyLen(512), | |
718 usage_mask, | |
719 &handle, | |
720 &type)); | |
721 | |
722 // Fail on invalid kty. | |
723 dict.SetString("kty", "foo"); | |
724 json_vec = MakeJsonVector(dict); | |
725 EXPECT_FALSE(ImportKeyJwk( | |
726 json_vec, extractable, algorithm, usage_mask, &handle, &type)); | |
727 dict.SetString("kty", key_val); | |
eroman
2013/10/29 03:03:46
I actually preferred the duplication of these cons
padolph
2013/10/29 22:57:01
Done.
| |
728 | |
729 // Fail on missing kty. | |
730 dict.Remove("kty", NULL); | |
731 json_vec = MakeJsonVector(dict); | |
732 EXPECT_FALSE(ImportKeyJwk( | |
733 json_vec, extractable, algorithm, usage_mask, &handle, &type)); | |
734 dict.SetString("kty", key_val); | |
735 | |
736 // Fail on invalid alg. | |
737 dict.SetString("alg", "foo"); | |
738 json_vec = MakeJsonVector(dict); | |
739 EXPECT_FALSE(ImportKeyJwk( | |
740 json_vec, extractable, algorithm, usage_mask, &handle, &type)); | |
741 dict.SetString("alg", alg_val); | |
742 | |
743 // Fail on invalid use. | |
744 dict.SetString("use", "foo"); | |
745 json_vec = MakeJsonVector(dict); | |
746 EXPECT_FALSE(ImportKeyJwk( | |
747 json_vec, extractable, algorithm, usage_mask, &handle, &type)); | |
748 dict.SetString("use", use_val); | |
749 | |
750 // Fail on missing k when kty = "oct". | |
751 dict.Remove("k", NULL); | |
752 json_vec = MakeJsonVector(dict); | |
753 EXPECT_FALSE(ImportKeyJwk( | |
754 json_vec, extractable, algorithm, usage_mask, &handle, &type)); | |
755 dict.SetString("k", k_val); | |
756 | |
757 // Fail on bad b64 encoding for k. | |
758 dict.SetString("k", "Qk3f0DsytU8lfza2au #$% Htaw2xpop9GYyTuH0p5GghxTI="); | |
759 json_vec = MakeJsonVector(dict); | |
760 EXPECT_FALSE(ImportKeyJwk( | |
761 json_vec, extractable, algorithm, usage_mask, &handle, &type)); | |
762 dict.SetString("k", k_val); | |
763 | |
764 // Fail on empty k. | |
765 dict.SetString("k", ""); | |
766 json_vec = MakeJsonVector(dict); | |
767 EXPECT_FALSE(ImportKeyJwk( | |
768 json_vec, extractable, algorithm, usage_mask, &handle, &type)); | |
769 dict.SetString("k", k_val); | |
770 | |
771 // TODO(padolph) RSA public key bad data: | |
772 // Missing n or e when kty = "RSA" | |
773 // Bad encoding for n or e | |
774 // Size check on n?? | |
775 // Value check on e?? | |
776 } | |
777 | |
778 TEST_F(WebCryptoImplTest, ImportJwkInputInconsistent) { | |
779 // The Web Crypto spec says that if a JWK value is present, but is | |
780 // inconsistent with the input value, the operation must fail. | |
781 | |
782 // Collision rules when JWK value is not present: Inputs should be unmodified. | |
783 scoped_ptr<WebKit::WebCryptoKeyHandle> handle; | |
784 WebKit::WebCryptoKeyType type = WebKit::WebCryptoKeyTypeSecret; | |
785 bool extractable = true; | |
786 WebKit::WebCryptoAlgorithm algorithm = | |
787 CreateHmacAlgorithmByHashId(WebKit::WebCryptoAlgorithmIdSha256); | |
788 WebKit::WebCryptoKeyUsageMask usage_mask = WebKit::WebCryptoKeyUsageVerify; | |
789 base::DictionaryValue dict; | |
790 dict.SetString("kty", "oct"); | |
791 dict.SetString("k", "l3nZEgZCeX8XRwJdWyK3rGB8qwjhdY8vOkbIvh4lxTuMao9Y_--hdg"); | |
792 std::vector<uint8> json_vec = MakeJsonVector(dict); | |
793 EXPECT_TRUE(ImportKeyJwk( | |
794 json_vec, extractable, algorithm, usage_mask, &handle, &type)); | |
795 EXPECT_TRUE(handle.get() != NULL); | |
796 EXPECT_EQ(WebKit::WebCryptoKeyTypeSecret, type); | |
797 EXPECT_TRUE(extractable); | |
798 EXPECT_EQ(WebKit::WebCryptoAlgorithmIdHmac, algorithm.id()); | |
799 EXPECT_EQ(WebKit::WebCryptoAlgorithmIdSha256, | |
800 algorithm.hmacParams()->hash().id()); | |
801 EXPECT_EQ(WebKit::WebCryptoKeyUsageVerify, usage_mask); | |
802 handle.reset(); | |
803 | |
804 // Collision rules when JWK value exists: Fail if inconsistency is found. | |
805 // Happy path: all input values are consistent with the JWK values | |
806 dict.Clear(); | |
807 dict.SetString("kty", "oct"); | |
808 dict.SetString("alg", "HS256"); | |
809 dict.SetString("use", "sig"); | |
810 dict.SetBoolean("extractable", true); | |
811 dict.SetString("k", "l3nZEgZCeX8XRwJdWyK3rGB8qwjhdY8vOkbIvh4lxTuMao9Y_--hdg"); | |
812 json_vec = MakeJsonVector(dict); | |
813 EXPECT_TRUE(ImportKeyJwk( | |
814 json_vec, extractable, algorithm, usage_mask, &handle, &type)); | |
815 | |
816 // Fail: Input type (public) is inconsistent with JWK value (secret). | |
817 type = WebKit::WebCryptoKeyTypePublic; | |
818 EXPECT_FALSE(ImportKeyJwk( | |
819 json_vec, extractable, algorithm, usage_mask, &handle, &type)); | |
820 type = WebKit::WebCryptoKeyTypeSecret; | |
821 | |
822 // Fail: Input extractable (false) is inconsistent with JWK value (true). | |
823 extractable = false; | |
824 EXPECT_FALSE(ImportKeyJwk( | |
825 json_vec, extractable, algorithm, usage_mask, &handle, &type)); | |
826 extractable = true; | |
827 | |
828 // Fail: Input algorithm (HMAC SHA1) is inconsistent with JWK value | |
829 // (HMAC SHA256). | |
830 algorithm = CreateHmacAlgorithmByHashId(WebKit::WebCryptoAlgorithmIdSha1); | |
831 EXPECT_FALSE(ImportKeyJwk( | |
832 json_vec, extractable, algorithm, usage_mask, &handle, &type)); | |
833 algorithm = CreateHmacAlgorithmByHashId(WebKit::WebCryptoAlgorithmIdSha256); | |
834 | |
835 // Fail: Input usage_mask (encrypt) is not a subset of the JWK value | |
836 // (sign|verify) | |
837 usage_mask = WebKit::WebCryptoKeyUsageEncrypt; | |
838 EXPECT_FALSE(ImportKeyJwk( | |
839 json_vec, extractable, algorithm, usage_mask, &handle, &type)); | |
840 usage_mask = WebKit::WebCryptoKeyUsageSign | WebKit::WebCryptoKeyUsageVerify; | |
841 | |
842 // Fail: Input usage_mask (encrypt|sign|verify) is not a subset of the JWK | |
843 // value (sign|verify) | |
844 usage_mask = WebKit::WebCryptoKeyUsageEncrypt | | |
845 WebKit::WebCryptoKeyUsageSign | WebKit::WebCryptoKeyUsageVerify; | |
846 EXPECT_FALSE(ImportKeyJwk( | |
847 json_vec, extractable, algorithm, usage_mask, &handle, &type)); | |
848 usage_mask = WebKit::WebCryptoKeyUsageSign | WebKit::WebCryptoKeyUsageVerify; | |
849 } | |
850 | |
851 TEST_F(WebCryptoImplTest, ImportJwkHappy) { | |
852 | |
853 // This test verifies the happy path of JWK import, including the application | |
854 // of the imported key material. | |
855 | |
856 scoped_ptr<WebKit::WebCryptoKeyHandle> handle; | |
857 WebKit::WebCryptoKeyType type = WebKit::WebCryptoKeyTypeSecret; | |
858 bool extractable = false; | |
859 WebKit::WebCryptoAlgorithm algorithm = | |
860 CreateHmacAlgorithmByHashId(WebKit::WebCryptoAlgorithmIdSha256); | |
861 WebKit::WebCryptoKeyUsageMask usage_mask = WebKit::WebCryptoKeyUsageSign; | |
862 | |
863 // Import a symmetric key JWK and HMAC-SHA256 sign() | |
864 // Uses the first SHA256 test vector from the HMAC sample set above. | |
865 | |
866 base::DictionaryValue dict; | |
867 dict.SetString("kty", "oct"); | |
868 dict.SetString("alg", "HS256"); | |
869 dict.SetString("use", "sig"); | |
870 dict.SetBoolean("extractable", false); | |
871 dict.SetString("k", "l3nZEgZCeX8XRwJdWyK3rGB8qwjhdY8vOkbIvh4lxTuMao9Y_--hdg"); | |
872 std::vector<uint8> json_vec = MakeJsonVector(dict); | |
873 | |
874 ASSERT_TRUE(ImportKeyJwk( | |
875 json_vec, extractable, algorithm, usage_mask, &handle, &type)); | |
876 | |
877 WebKit::WebCryptoKey key = WebKit::WebCryptoKey::create( | |
878 handle.release(), type, extractable, algorithm, usage_mask); | |
879 | |
880 const std::vector<uint8> message_raw = HexStringToBytes( | |
881 "b1689c2591eaf3c9e66070f8a77954ffb81749f1b00346f9dfe0b2ee905dcc288baf4a" | |
882 "92de3f4001dd9f44c468c3d07d6c6ee82faceafc97c2fc0fc0601719d2dcd0aa2aec92" | |
883 "d1b0ae933c65eb06a03c9c935c2bad0459810241347ab87e9f11adb30415424c6c7f5f" | |
884 "22a003b8ab8de54f6ded0e3ab9245fa79568451dfa258e"); | |
885 | |
886 WebKit::WebArrayBuffer output; | |
887 | |
888 ASSERT_TRUE(SignInternal(algorithm, key, message_raw, &output)); | |
889 | |
890 const std::string mac_raw = | |
891 "769f00d3e6a6cc1fb426a14a4f76c6462e6149726e0dee0ec0cf97a16605ac8b"; | |
892 | |
893 ExpectArrayBufferMatchesHex(mac_raw, output); | |
894 | |
895 // TODO(padolph) | |
896 // Import an RSA public key JWK and use it | |
897 } | |
898 | |
659 } // namespace content | 899 } // namespace content |
OLD | NEW |