Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1105)

Side by Side Diff: content/renderer/webcrypto/webcrypto_impl_unittest.cc

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

Powered by Google App Engine
This is Rietveld 408576698