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

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

Issue 100593002: [webcrypto] Add symmetric key export for NSS and OpenSSL. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase Created 7 years 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 <algorithm> 7 #include <algorithm>
8 #include <string> 8 #include <string>
9 #include <vector> 9 #include <vector>
10 10
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
87 return blink::WebCryptoAlgorithm::adoptParamsAndCreate( 87 return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
88 algorithm_id, 88 algorithm_id,
89 new blink::WebCryptoRsaKeyGenParams( 89 new blink::WebCryptoRsaKeyGenParams(
90 modulus_length, 90 modulus_length,
91 webcrypto::Uint8VectorStart(public_exponent), 91 webcrypto::Uint8VectorStart(public_exponent),
92 public_exponent.size())); 92 public_exponent.size()));
93 } 93 }
94 94
95 #endif // #if !defined(USE_OPENSSL) 95 #endif // #if !defined(USE_OPENSSL)
96 96
97 // Determines if two ArrayBuffers have identical content.
98 bool ArrayBuffersEqual(
99 const blink::WebArrayBuffer& a,
100 const blink::WebArrayBuffer& b) {
101 if (a.byteLength() != b.byteLength())
102 return false;
103 const uint8* a_begin = static_cast<uint8*>(a.data());
104 const uint8* const a_end = a_begin + a.byteLength();
105 const uint8* b_begin = static_cast<uint8*>(b.data());
106 return std::equal(a_begin, a_end, b_begin);
eroman 2013/12/05 01:47:53 [no change necessary] My inclination would have be
padolph 2013/12/05 02:45:57 I'm sure std::equal optimizes down to memcmp in th
107 }
108
109 // Adapts ArrayBufferEqual() into a unary predicate for use with std::count_if
110 // in CopiesExist().
111 class ArrayBufferEqualTo {
112 public:
113 ArrayBufferEqualTo(const blink::WebArrayBuffer& b) : b_(b) {}
114 bool operator()(const blink::WebArrayBuffer& a) const {
115 return ArrayBuffersEqual(a, b_);
116 }
117
118 private:
119 const blink::WebArrayBuffer& b_;
120 };
121
122 // Given a vector of WebArrayBuffers, determines if there are any copies. Not
123 // the most efficient implementation, but the vector is expected to be small.
124 bool CopiesExist(std::vector<blink::WebArrayBuffer> bufs) {
125 for (std::vector<blink::WebArrayBuffer>::const_iterator it = bufs.begin();
eroman 2013/12/05 01:47:53 I much prefer the old-fashioned double-for-loop he
padolph 2013/12/05 02:45:57 I can't argue with that. 1/3 the lines and faster.
126 it != bufs.end();
127 ++it) {
128 if (std::count_if(bufs.begin(), bufs.end(), ArrayBufferEqualTo(*it)) != 1)
129 return true;
130 }
131 return false;
132 }
133
97 } // namespace 134 } // namespace
98 135
99 class WebCryptoImplTest : public testing::Test { 136 class WebCryptoImplTest : public testing::Test {
100 protected: 137 protected:
101 blink::WebCryptoKey ImportSecretKeyFromRawHexString( 138 blink::WebCryptoKey ImportSecretKeyFromRawHexString(
102 const std::string& key_hex, 139 const std::string& key_hex,
103 const blink::WebCryptoAlgorithm& algorithm, 140 const blink::WebCryptoAlgorithm& algorithm,
104 blink::WebCryptoKeyUsageMask usage) { 141 blink::WebCryptoKeyUsageMask usage) {
105 std::vector<uint8> key_raw = HexStringToBytes(key_hex); 142 std::vector<uint8> key_raw = HexStringToBytes(key_hex);
106 143
(...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after
425 ++test_index) { 462 ++test_index) {
426 SCOPED_TRACE(test_index); 463 SCOPED_TRACE(test_index);
427 const TestCase& test = kTests[test_index]; 464 const TestCase& test = kTests[test_index];
428 465
429 blink::WebCryptoAlgorithm algorithm = 466 blink::WebCryptoAlgorithm algorithm =
430 webcrypto::CreateHmacAlgorithmByHashId(test.algorithm); 467 webcrypto::CreateHmacAlgorithmByHashId(test.algorithm);
431 468
432 blink::WebCryptoKey key = ImportSecretKeyFromRawHexString( 469 blink::WebCryptoKey key = ImportSecretKeyFromRawHexString(
433 test.key, algorithm, blink::WebCryptoKeyUsageSign); 470 test.key, algorithm, blink::WebCryptoKeyUsageSign);
434 471
472 // Verify exported raw key is identical to the imported data
473 blink::WebArrayBuffer raw_key;
474 EXPECT_TRUE(ExportKeyInternal(blink::WebCryptoKeyFormatRaw, key, &raw_key));
475 ExpectArrayBufferMatchesHex(test.key, raw_key);
476
435 std::vector<uint8> message_raw = HexStringToBytes(test.message); 477 std::vector<uint8> message_raw = HexStringToBytes(test.message);
436 478
437 blink::WebArrayBuffer output; 479 blink::WebArrayBuffer output;
438 480
439 ASSERT_TRUE(SignInternal(algorithm, key, message_raw, &output)); 481 ASSERT_TRUE(SignInternal(algorithm, key, message_raw, &output));
440 482
441 ExpectArrayBufferMatchesHex(test.mac, output); 483 ExpectArrayBufferMatchesHex(test.mac, output);
442 484
443 bool signature_match = false; 485 bool signature_match = false;
444 EXPECT_TRUE(VerifySignatureInternal( 486 EXPECT_TRUE(VerifySignatureInternal(
(...skipping 24 matching lines...) Expand all
469 sizeof(kLongSignature), 511 sizeof(kLongSignature),
470 message_raw, 512 message_raw,
471 &signature_match)); 513 &signature_match));
472 EXPECT_FALSE(signature_match); 514 EXPECT_FALSE(signature_match);
473 } 515 }
474 } 516 }
475 517
476 #if !defined(USE_OPENSSL) 518 #if !defined(USE_OPENSSL)
477 519
478 TEST_F(WebCryptoImplTest, AesCbcFailures) { 520 TEST_F(WebCryptoImplTest, AesCbcFailures) {
521 const std::string key_hex = "2b7e151628aed2a6abf7158809cf4f3c";
479 blink::WebCryptoKey key = ImportSecretKeyFromRawHexString( 522 blink::WebCryptoKey key = ImportSecretKeyFromRawHexString(
480 "2b7e151628aed2a6abf7158809cf4f3c", 523 key_hex,
481 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc), 524 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
482 blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt); 525 blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt);
483 526
527 // Verify exported raw key is identical to the imported data
528 blink::WebArrayBuffer raw_key;
529 EXPECT_TRUE(ExportKeyInternal(blink::WebCryptoKeyFormatRaw, key, &raw_key));
530 ExpectArrayBufferMatchesHex(key_hex, raw_key);
531
484 blink::WebArrayBuffer output; 532 blink::WebArrayBuffer output;
485 533
486 // Use an invalid |iv| (fewer than 16 bytes) 534 // Use an invalid |iv| (fewer than 16 bytes)
487 { 535 {
488 std::vector<uint8> input(32); 536 std::vector<uint8> input(32);
489 std::vector<uint8> iv; 537 std::vector<uint8> iv;
490 EXPECT_FALSE(EncryptInternal( 538 EXPECT_FALSE(EncryptInternal(
491 webcrypto::CreateAesCbcAlgorithm(iv), key, input, &output)); 539 webcrypto::CreateAesCbcAlgorithm(iv), key, input, &output));
492 EXPECT_FALSE(DecryptInternal( 540 EXPECT_FALSE(DecryptInternal(
493 webcrypto::CreateAesCbcAlgorithm(iv), key, input, &output)); 541 webcrypto::CreateAesCbcAlgorithm(iv), key, input, &output));
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
527 575
528 blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); 576 blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
529 EXPECT_FALSE(ImportKeyInternal(blink::WebCryptoKeyFormatRaw, 577 EXPECT_FALSE(ImportKeyInternal(blink::WebCryptoKeyFormatRaw,
530 key_raw, 578 key_raw,
531 webcrypto::CreateAesCbcAlgorithm(iv), 579 webcrypto::CreateAesCbcAlgorithm(iv),
532 true, 580 true,
533 blink::WebCryptoKeyUsageEncrypt, 581 blink::WebCryptoKeyUsageEncrypt,
534 &key)); 582 &key));
535 } 583 }
536 584
537 // Fail exporting the key in SPKI format (SPKI export not allowed for secret 585 // Fail exporting the key in SPKI and PKCS#8 formats (not allowed for secret
538 // keys) 586 // keys).
539 EXPECT_FALSE(ExportKeyInternal(blink::WebCryptoKeyFormatSpki, key, &output)); 587 EXPECT_FALSE(ExportKeyInternal(blink::WebCryptoKeyFormatSpki, key, &output));
588 EXPECT_FALSE(ExportKeyInternal(blink::WebCryptoKeyFormatPkcs8, key, &output));
540 } 589 }
541 590
542 TEST_F(WebCryptoImplTest, AesCbcSampleSets) { 591 TEST_F(WebCryptoImplTest, AesCbcSampleSets) {
543 struct TestCase { 592 struct TestCase {
544 const char* key; 593 const char* key;
545 const char* iv; 594 const char* iv;
546 const char* plain_text; 595 const char* plain_text;
547 const char* cipher_text; 596 const char* cipher_text;
548 }; 597 };
549 598
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
619 668
620 for (size_t index = 0; index < ARRAYSIZE_UNSAFE(kTests); index++) { 669 for (size_t index = 0; index < ARRAYSIZE_UNSAFE(kTests); index++) {
621 SCOPED_TRACE(index); 670 SCOPED_TRACE(index);
622 const TestCase& test = kTests[index]; 671 const TestCase& test = kTests[index];
623 672
624 blink::WebCryptoKey key = ImportSecretKeyFromRawHexString( 673 blink::WebCryptoKey key = ImportSecretKeyFromRawHexString(
625 test.key, 674 test.key,
626 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc), 675 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
627 blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt); 676 blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt);
628 677
678 // Verify exported raw key is identical to the imported data
679 blink::WebArrayBuffer raw_key;
680 EXPECT_TRUE(ExportKeyInternal(blink::WebCryptoKeyFormatRaw, key, &raw_key));
681 ExpectArrayBufferMatchesHex(test.key, raw_key);
682
629 std::vector<uint8> plain_text = HexStringToBytes(test.plain_text); 683 std::vector<uint8> plain_text = HexStringToBytes(test.plain_text);
630 std::vector<uint8> iv = HexStringToBytes(test.iv); 684 std::vector<uint8> iv = HexStringToBytes(test.iv);
631 685
632 blink::WebArrayBuffer output; 686 blink::WebArrayBuffer output;
633 687
634 // Test encryption. 688 // Test encryption.
635 EXPECT_TRUE(EncryptInternal(webcrypto::CreateAesCbcAlgorithm(iv), 689 EXPECT_TRUE(EncryptInternal(webcrypto::CreateAesCbcAlgorithm(iv),
636 key, 690 key,
637 plain_text, 691 plain_text,
638 &output)); 692 &output));
(...skipping 24 matching lines...) Expand all
663 if (cipher_text.size() > 3) { 717 if (cipher_text.size() > 3) {
664 EXPECT_FALSE(DecryptInternal(webcrypto::CreateAesCbcAlgorithm(iv), 718 EXPECT_FALSE(DecryptInternal(webcrypto::CreateAesCbcAlgorithm(iv),
665 key, 719 key,
666 &cipher_text[0], 720 &cipher_text[0],
667 cipher_text.size() - 3, 721 cipher_text.size() - 3,
668 &output)); 722 &output));
669 } 723 }
670 } 724 }
671 } 725 }
672 726
673 // TODO(padolph): Add test to verify generated symmetric keys appear random.
674
675 TEST_F(WebCryptoImplTest, GenerateKeyAes) { 727 TEST_F(WebCryptoImplTest, GenerateKeyAes) {
676 blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); 728 // Generate a small sample of AES keys.
677 ASSERT_TRUE( 729 std::vector<blink::WebArrayBuffer> keys;
678 GenerateKeyInternal(webcrypto::CreateAesCbcKeyGenAlgorithm(128), &key)); 730 blink::WebArrayBuffer key_bytes;
679 EXPECT_TRUE(key.handle()); 731 for (int i = 0; i < 16; ++i) {
680 EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type()); 732 blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
733 ASSERT_TRUE(
734 GenerateKeyInternal(webcrypto::CreateAesCbcKeyGenAlgorithm(128), &key));
735 EXPECT_TRUE(key.handle());
736 EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type());
737 ASSERT_TRUE(
738 ExportKeyInternal(blink::WebCryptoKeyFormatRaw, key, &key_bytes));
739 keys.push_back(key_bytes);
740 }
741 // Ensure all entries in the key sample set are unique. This is a simplistic
742 // estimate of whether the generated keys appear random.
743 EXPECT_FALSE(CopiesExist(keys));
681 } 744 }
682 745
683 TEST_F(WebCryptoImplTest, GenerateKeyAesBadLength) { 746 TEST_F(WebCryptoImplTest, GenerateKeyAesBadLength) {
684 blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); 747 blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
685 EXPECT_FALSE( 748 EXPECT_FALSE(
686 GenerateKeyInternal(webcrypto::CreateAesCbcKeyGenAlgorithm(0), &key)); 749 GenerateKeyInternal(webcrypto::CreateAesCbcKeyGenAlgorithm(0), &key));
687 EXPECT_FALSE( 750 EXPECT_FALSE(
688 GenerateKeyInternal(webcrypto::CreateAesCbcKeyGenAlgorithm(0), &key)); 751 GenerateKeyInternal(webcrypto::CreateAesCbcKeyGenAlgorithm(0), &key));
689 EXPECT_FALSE( 752 EXPECT_FALSE(
690 GenerateKeyInternal(webcrypto::CreateAesCbcKeyGenAlgorithm(129), &key)); 753 GenerateKeyInternal(webcrypto::CreateAesCbcKeyGenAlgorithm(129), &key));
691 } 754 }
692 755
693 TEST_F(WebCryptoImplTest, GenerateKeyHmac) { 756 TEST_F(WebCryptoImplTest, GenerateKeyHmac) {
694 blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); 757 // Generate a small sample of HMAC keys.
695 blink::WebCryptoAlgorithm algorithm = webcrypto::CreateHmacKeyGenAlgorithm( 758 std::vector<blink::WebArrayBuffer> keys;
696 blink::WebCryptoAlgorithmIdSha1, 128); 759 for (int i = 0; i < 16; ++i) {
697 ASSERT_TRUE(GenerateKeyInternal(algorithm, &key)); 760 blink::WebArrayBuffer key_bytes;
698 EXPECT_FALSE(key.isNull()); 761 blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
699 EXPECT_TRUE(key.handle()); 762 blink::WebCryptoAlgorithm algorithm = webcrypto::CreateHmacKeyGenAlgorithm(
700 EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type()); 763 blink::WebCryptoAlgorithmIdSha1, 128);
764 ASSERT_TRUE(GenerateKeyInternal(algorithm, &key));
765 EXPECT_FALSE(key.isNull());
766 EXPECT_TRUE(key.handle());
767 EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type());
768 }
769 // Ensure all entries in the key sample set are unique. This is a simplistic
770 // estimate of whether the generated keys appear random.
771 EXPECT_FALSE(CopiesExist(keys));
701 } 772 }
702 773
703 TEST_F(WebCryptoImplTest, GenerateKeyHmacNoLength) { 774 TEST_F(WebCryptoImplTest, GenerateKeyHmacNoLength) {
704 blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); 775 blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
705 blink::WebCryptoAlgorithm algorithm = 776 blink::WebCryptoAlgorithm algorithm =
706 webcrypto::CreateHmacKeyGenAlgorithm(blink::WebCryptoAlgorithmIdSha1, 0); 777 webcrypto::CreateHmacKeyGenAlgorithm(blink::WebCryptoAlgorithmIdSha1, 0);
707 ASSERT_TRUE(GenerateKeyInternal(algorithm, &key)); 778 ASSERT_TRUE(GenerateKeyInternal(algorithm, &key));
708 EXPECT_TRUE(key.handle()); 779 EXPECT_TRUE(key.handle());
709 EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type()); 780 EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type());
710 } 781 }
(...skipping 401 matching lines...) Expand 10 before | Expand all | Expand 10 after
1112 true, 1183 true,
1113 blink::WebCryptoKeyUsageEncrypt, 1184 blink::WebCryptoKeyUsageEncrypt,
1114 &key)); 1185 &key));
1115 1186
1116 // Passing case: Export a previously imported RSA public key in SPKI format 1187 // Passing case: Export a previously imported RSA public key in SPKI format
1117 // and compare to original data. 1188 // and compare to original data.
1118 blink::WebArrayBuffer output; 1189 blink::WebArrayBuffer output;
1119 ASSERT_TRUE(ExportKeyInternal(blink::WebCryptoKeyFormatSpki, key, &output)); 1190 ASSERT_TRUE(ExportKeyInternal(blink::WebCryptoKeyFormatSpki, key, &output));
1120 ExpectArrayBufferMatchesHex(hex_rsa_spki_der, output); 1191 ExpectArrayBufferMatchesHex(hex_rsa_spki_der, output);
1121 1192
1193 // Failing case: Try to export a previously imported RSA public key in raw
1194 // format (not allowed for a public key).
1195 EXPECT_FALSE(ExportKeyInternal(blink::WebCryptoKeyFormatRaw, key, &output));
1196
1122 // Failing case: Try to export a non-extractable key 1197 // Failing case: Try to export a non-extractable key
1123 ASSERT_TRUE(ImportKeyInternal( 1198 ASSERT_TRUE(ImportKeyInternal(
1124 blink::WebCryptoKeyFormatSpki, 1199 blink::WebCryptoKeyFormatSpki,
1125 HexStringToBytes(hex_rsa_spki_der), 1200 HexStringToBytes(hex_rsa_spki_der),
1126 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5), 1201 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5),
1127 false, 1202 false,
1128 blink::WebCryptoKeyUsageEncrypt, 1203 blink::WebCryptoKeyUsageEncrypt,
1129 &key)); 1204 &key));
1130 EXPECT_TRUE(key.handle()); 1205 EXPECT_TRUE(key.handle());
1131 EXPECT_FALSE(key.extractable()); 1206 EXPECT_FALSE(key.extractable());
(...skipping 443 matching lines...) Expand 10 before | Expand all | Expand 10 after
1575 private_key, 1650 private_key,
1576 reinterpret_cast<const unsigned char*>(encrypted_data.data()), 1651 reinterpret_cast<const unsigned char*>(encrypted_data.data()),
1577 encrypted_data.byteLength(), 1652 encrypted_data.byteLength(),
1578 &decrypted_data)); 1653 &decrypted_data));
1579 ExpectArrayBufferMatchesHex(message_hex_str, decrypted_data); 1654 ExpectArrayBufferMatchesHex(message_hex_str, decrypted_data);
1580 } 1655 }
1581 1656
1582 #endif // #if !defined(USE_OPENSSL) 1657 #endif // #if !defined(USE_OPENSSL)
1583 1658
1584 } // namespace content 1659 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698