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

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: add more testing, fix minor bug, and add support for OpenSSL 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 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
91 algorithm_id == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 || 91 algorithm_id == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 ||
92 algorithm_id == blink::WebCryptoAlgorithmIdRsaOaep); 92 algorithm_id == blink::WebCryptoAlgorithmIdRsaOaep);
93 return blink::WebCryptoAlgorithm::adoptParamsAndCreate( 93 return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
94 algorithm_id, 94 algorithm_id,
95 new blink::WebCryptoRsaKeyGenParams( 95 new blink::WebCryptoRsaKeyGenParams(
96 modulus_length, Start(public_exponent), public_exponent.size())); 96 modulus_length, Start(public_exponent), public_exponent.size()));
97 } 97 }
98 98
99 #endif // #if !defined(USE_OPENSSL) 99 #endif // #if !defined(USE_OPENSSL)
100 100
101 // MIT HAKMEM Bit Count for 8-bit Unsigned Char
102 int BitCount8(unsigned char b) {
103 b = (b & 0x55u) + ((b >> 1) & 0x55u);
104 b = (b & 0x33u) + ((b >> 2) & 0x33u);
105 b = (b & 0x0fu) + ((b >> 4) & 0x0fu);
106 return (b);
107 }
108
109 // Use a binary entropy calculation to check whether the input data appears
110 // random. See http://en.wikipedia.org/wiki/Binary_entropy.
111 void ExpectDataAppearsRandom(const blink::WebArrayBuffer& key_bytes) {
112 DCHECK(key_bytes.data());
113 DCHECK(key_bytes.byteLength());
114 int n_set_bits = 0;
115 unsigned char* data_ptr = static_cast<unsigned char*>(key_bytes.data());
116 unsigned char* const data_ptr_end = data_ptr + key_bytes.byteLength();
117 while (data_ptr < data_ptr_end) {
118 n_set_bits += BitCount8(*data_ptr++);
119 }
120 // Binary entropy is calculated as -p * log2(p) - (1 - p) * log2(1 - p), where
121 // p is the percentage of set bits in the input data. This function has a
122 // maximum of 1.0 at p = 0.5. Arbitrarily say the input data is random if the
123 // calculated entropy is > 0.75, which solves to 0.2145 ~< p ~< 0.7855.
eroman 2013/12/04 19:04:00 Doesn't this mean that truly random buffers will f
padolph 2013/12/04 22:22:13 No, the math does not work that way. However, I re
124 double p = static_cast<double>(n_set_bits) / (key_bytes.byteLength() * 8);
125 EXPECT_GT(p, 0.2145);
126 EXPECT_LT(p, 0.7855);
127 }
128
101 } // namespace 129 } // namespace
102 130
103 namespace content { 131 namespace content {
104 132
105 class WebCryptoImplTest : public testing::Test { 133 class WebCryptoImplTest : public testing::Test {
106 protected: 134 protected:
107 blink::WebCryptoKey ImportSecretKeyFromRawHexString( 135 blink::WebCryptoKey ImportSecretKeyFromRawHexString(
108 const std::string& key_hex, 136 const std::string& key_hex,
109 const blink::WebCryptoAlgorithm& algorithm, 137 const blink::WebCryptoAlgorithm& algorithm,
110 blink::WebCryptoKeyUsageMask usage) { 138 blink::WebCryptoKeyUsageMask usage) {
(...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after
414 for (size_t test_index = 0; test_index < ARRAYSIZE_UNSAFE(kTests); 442 for (size_t test_index = 0; test_index < ARRAYSIZE_UNSAFE(kTests);
415 ++test_index) { 443 ++test_index) {
416 SCOPED_TRACE(test_index); 444 SCOPED_TRACE(test_index);
417 const TestCase& test = kTests[test_index]; 445 const TestCase& test = kTests[test_index];
418 446
419 blink::WebCryptoAlgorithm algorithm = CreateHmacAlgorithm(test.algorithm); 447 blink::WebCryptoAlgorithm algorithm = CreateHmacAlgorithm(test.algorithm);
420 448
421 blink::WebCryptoKey key = ImportSecretKeyFromRawHexString( 449 blink::WebCryptoKey key = ImportSecretKeyFromRawHexString(
422 test.key, algorithm, blink::WebCryptoKeyUsageSign); 450 test.key, algorithm, blink::WebCryptoKeyUsageSign);
423 451
452 // Verify exported raw key is identical to the imported data
453 blink::WebArrayBuffer raw_key;
454 EXPECT_TRUE(ExportKeyInternal(blink::WebCryptoKeyFormatRaw, key, &raw_key));
455 ExpectArrayBufferMatchesHex(test.key, raw_key);
456
424 std::vector<uint8> message_raw = HexStringToBytes(test.message); 457 std::vector<uint8> message_raw = HexStringToBytes(test.message);
425 458
426 blink::WebArrayBuffer output; 459 blink::WebArrayBuffer output;
427 460
428 ASSERT_TRUE(SignInternal(algorithm, key, message_raw, &output)); 461 ASSERT_TRUE(SignInternal(algorithm, key, message_raw, &output));
429 462
430 ExpectArrayBufferMatchesHex(test.mac, output); 463 ExpectArrayBufferMatchesHex(test.mac, output);
431 464
432 bool signature_match = false; 465 bool signature_match = false;
433 EXPECT_TRUE(VerifySignatureInternal( 466 EXPECT_TRUE(VerifySignatureInternal(
(...skipping 22 matching lines...) Expand all
456 key, 489 key,
457 kLongSignature, 490 kLongSignature,
458 sizeof(kLongSignature), 491 sizeof(kLongSignature),
459 message_raw, 492 message_raw,
460 &signature_match)); 493 &signature_match));
461 EXPECT_FALSE(signature_match); 494 EXPECT_FALSE(signature_match);
462 } 495 }
463 } 496 }
464 497
465 TEST_F(WebCryptoImplTest, AesCbcFailures) { 498 TEST_F(WebCryptoImplTest, AesCbcFailures) {
499 const std::string key_hex = "2b7e151628aed2a6abf7158809cf4f3c";
466 blink::WebCryptoKey key = ImportSecretKeyFromRawHexString( 500 blink::WebCryptoKey key = ImportSecretKeyFromRawHexString(
467 "2b7e151628aed2a6abf7158809cf4f3c", 501 key_hex,
468 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc), 502 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
469 blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt); 503 blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt);
470 504
505 // Verify exported raw key is identical to the imported data
506 blink::WebArrayBuffer raw_key;
507 EXPECT_TRUE(ExportKeyInternal(blink::WebCryptoKeyFormatRaw, key, &raw_key));
508 ExpectArrayBufferMatchesHex(key_hex, raw_key);
509
471 blink::WebArrayBuffer output; 510 blink::WebArrayBuffer output;
472 511
473 // Use an invalid |iv| (fewer than 16 bytes) 512 // Use an invalid |iv| (fewer than 16 bytes)
474 { 513 {
475 std::vector<uint8> input(32); 514 std::vector<uint8> input(32);
476 std::vector<uint8> iv; 515 std::vector<uint8> iv;
477 EXPECT_FALSE( 516 EXPECT_FALSE(
478 EncryptInternal(CreateAesCbcAlgorithm(iv), key, input, &output)); 517 EncryptInternal(CreateAesCbcAlgorithm(iv), key, input, &output));
479 EXPECT_FALSE( 518 EXPECT_FALSE(
480 DecryptInternal(CreateAesCbcAlgorithm(iv), key, input, &output)); 519 DecryptInternal(CreateAesCbcAlgorithm(iv), key, input, &output));
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
514 553
515 blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); 554 blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
516 EXPECT_FALSE(ImportKeyInternal(blink::WebCryptoKeyFormatRaw, 555 EXPECT_FALSE(ImportKeyInternal(blink::WebCryptoKeyFormatRaw,
517 key_raw, 556 key_raw,
518 CreateAesCbcAlgorithm(iv), 557 CreateAesCbcAlgorithm(iv),
519 true, 558 true,
520 blink::WebCryptoKeyUsageEncrypt, 559 blink::WebCryptoKeyUsageEncrypt,
521 &key)); 560 &key));
522 } 561 }
523 562
524 // Fail exporting the key in SPKI format (SPKI export not allowed for secret 563 // Fail exporting the key in SPKI and PKCS#8 formats (not allowed for secret
525 // keys) 564 // keys).
526 EXPECT_FALSE(ExportKeyInternal(blink::WebCryptoKeyFormatSpki, key, &output)); 565 EXPECT_FALSE(ExportKeyInternal(blink::WebCryptoKeyFormatSpki, key, &output));
566 EXPECT_FALSE(ExportKeyInternal(blink::WebCryptoKeyFormatPkcs8, key, &output));
527 } 567 }
528 568
529 TEST_F(WebCryptoImplTest, AesCbcSampleSets) { 569 TEST_F(WebCryptoImplTest, AesCbcSampleSets) {
530 struct TestCase { 570 struct TestCase {
531 const char* key; 571 const char* key;
532 const char* iv; 572 const char* iv;
533 const char* plain_text; 573 const char* plain_text;
534 const char* cipher_text; 574 const char* cipher_text;
535 }; 575 };
536 576
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
606 646
607 for (size_t index = 0; index < ARRAYSIZE_UNSAFE(kTests); index++) { 647 for (size_t index = 0; index < ARRAYSIZE_UNSAFE(kTests); index++) {
608 SCOPED_TRACE(index); 648 SCOPED_TRACE(index);
609 const TestCase& test = kTests[index]; 649 const TestCase& test = kTests[index];
610 650
611 blink::WebCryptoKey key = ImportSecretKeyFromRawHexString( 651 blink::WebCryptoKey key = ImportSecretKeyFromRawHexString(
612 test.key, 652 test.key,
613 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc), 653 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
614 blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt); 654 blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt);
615 655
656 // Verify exported raw key is identical to the imported data
657 blink::WebArrayBuffer raw_key;
658 EXPECT_TRUE(ExportKeyInternal(blink::WebCryptoKeyFormatRaw, key, &raw_key));
659 ExpectArrayBufferMatchesHex(test.key, raw_key);
660
616 std::vector<uint8> plain_text = HexStringToBytes(test.plain_text); 661 std::vector<uint8> plain_text = HexStringToBytes(test.plain_text);
617 std::vector<uint8> iv = HexStringToBytes(test.iv); 662 std::vector<uint8> iv = HexStringToBytes(test.iv);
618 663
619 blink::WebArrayBuffer output; 664 blink::WebArrayBuffer output;
620 665
621 // Test encryption. 666 // Test encryption.
622 EXPECT_TRUE(EncryptInternal(CreateAesCbcAlgorithm(iv), 667 EXPECT_TRUE(EncryptInternal(CreateAesCbcAlgorithm(iv),
623 key, 668 key,
624 plain_text, 669 plain_text,
625 &output)); 670 &output));
(...skipping 24 matching lines...) Expand all
650 if (cipher_text.size() > 3) { 695 if (cipher_text.size() > 3) {
651 EXPECT_FALSE(DecryptInternal(CreateAesCbcAlgorithm(iv), 696 EXPECT_FALSE(DecryptInternal(CreateAesCbcAlgorithm(iv),
652 key, 697 key,
653 &cipher_text[0], 698 &cipher_text[0],
654 cipher_text.size() - 3, 699 cipher_text.size() - 3,
655 &output)); 700 &output));
656 } 701 }
657 } 702 }
658 } 703 }
659 704
660 // TODO(padolph): Add test to verify generated symmetric keys appear random.
661
662 TEST_F(WebCryptoImplTest, GenerateKeyAes) { 705 TEST_F(WebCryptoImplTest, GenerateKeyAes) {
663 blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); 706 blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
664 ASSERT_TRUE(GenerateKeyInternal(CreateAesCbcAlgorithm(128), &key)); 707 ASSERT_TRUE(GenerateKeyInternal(CreateAesCbcAlgorithm(128), &key));
665 EXPECT_TRUE(key.handle()); 708 EXPECT_TRUE(key.handle());
666 EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type()); 709 EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type());
710 blink::WebArrayBuffer key_bytes;
711 ASSERT_TRUE(ExportKeyInternal(blink::WebCryptoKeyFormatRaw, key, &key_bytes));
712 ExpectDataAppearsRandom(key_bytes);
667 } 713 }
668 714
669 TEST_F(WebCryptoImplTest, GenerateKeyAesBadLength) { 715 TEST_F(WebCryptoImplTest, GenerateKeyAesBadLength) {
670 blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); 716 blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
671 EXPECT_FALSE(GenerateKeyInternal(CreateAesCbcAlgorithm(0), &key)); 717 EXPECT_FALSE(GenerateKeyInternal(CreateAesCbcAlgorithm(0), &key));
672 EXPECT_FALSE(GenerateKeyInternal(CreateAesCbcAlgorithm(129), &key)); 718 EXPECT_FALSE(GenerateKeyInternal(CreateAesCbcAlgorithm(129), &key));
673 } 719 }
674 720
675 TEST_F(WebCryptoImplTest, GenerateKeyHmac) { 721 TEST_F(WebCryptoImplTest, GenerateKeyHmac) {
676 blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); 722 blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
677 blink::WebCryptoAlgorithm algorithm = 723 blink::WebCryptoAlgorithm algorithm =
678 CreateHmacKeyAlgorithm(blink::WebCryptoAlgorithmIdSha1, 128); 724 CreateHmacKeyAlgorithm(blink::WebCryptoAlgorithmIdSha1, 128);
679 ASSERT_TRUE(GenerateKeyInternal(algorithm, &key)); 725 ASSERT_TRUE(GenerateKeyInternal(algorithm, &key));
680 EXPECT_FALSE(key.isNull()); 726 EXPECT_FALSE(key.isNull());
681 EXPECT_TRUE(key.handle()); 727 EXPECT_TRUE(key.handle());
682 EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type()); 728 EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type());
729 blink::WebArrayBuffer key_bytes;
730 ASSERT_TRUE(ExportKeyInternal(blink::WebCryptoKeyFormatRaw, key, &key_bytes));
731 ExpectDataAppearsRandom(key_bytes);
683 } 732 }
684 733
685 TEST_F(WebCryptoImplTest, GenerateKeyHmacNoLength) { 734 TEST_F(WebCryptoImplTest, GenerateKeyHmacNoLength) {
686 blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); 735 blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
687 blink::WebCryptoAlgorithm algorithm = 736 blink::WebCryptoAlgorithm algorithm =
688 CreateHmacKeyAlgorithm(blink::WebCryptoAlgorithmIdSha1, 0); 737 CreateHmacKeyAlgorithm(blink::WebCryptoAlgorithmIdSha1, 0);
689 ASSERT_TRUE(GenerateKeyInternal(algorithm, &key)); 738 ASSERT_TRUE(GenerateKeyInternal(algorithm, &key));
690 EXPECT_TRUE(key.handle()); 739 EXPECT_TRUE(key.handle());
691 EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type()); 740 EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type());
692 } 741 }
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
773 true, 822 true,
774 blink::WebCryptoKeyUsageEncrypt, 823 blink::WebCryptoKeyUsageEncrypt,
775 &key)); 824 &key));
776 825
777 // Passing case: Export a previously imported RSA public key in SPKI format 826 // Passing case: Export a previously imported RSA public key in SPKI format
778 // and compare to original data. 827 // and compare to original data.
779 blink::WebArrayBuffer output; 828 blink::WebArrayBuffer output;
780 ASSERT_TRUE(ExportKeyInternal(blink::WebCryptoKeyFormatSpki, key, &output)); 829 ASSERT_TRUE(ExportKeyInternal(blink::WebCryptoKeyFormatSpki, key, &output));
781 ExpectArrayBufferMatchesHex(hex_rsa_spki_der, output); 830 ExpectArrayBufferMatchesHex(hex_rsa_spki_der, output);
782 831
832 // Failing case: Try to export a previously imported RSA public key in raw
833 // format (not allowed for a public key).
834 EXPECT_FALSE(ExportKeyInternal(blink::WebCryptoKeyFormatRaw, key, &output));
835
783 // Failing case: Try to export a non-extractable key 836 // Failing case: Try to export a non-extractable key
784 ASSERT_TRUE(ImportKeyInternal( 837 ASSERT_TRUE(ImportKeyInternal(
785 blink::WebCryptoKeyFormatSpki, 838 blink::WebCryptoKeyFormatSpki,
786 HexStringToBytes(hex_rsa_spki_der), 839 HexStringToBytes(hex_rsa_spki_der),
787 CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5), 840 CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5),
788 false, 841 false,
789 blink::WebCryptoKeyUsageEncrypt, 842 blink::WebCryptoKeyUsageEncrypt,
790 &key)); 843 &key));
791 EXPECT_TRUE(key.handle()); 844 EXPECT_TRUE(key.handle());
792 EXPECT_FALSE(key.extractable()); 845 EXPECT_FALSE(key.extractable());
(...skipping 445 matching lines...) Expand 10 before | Expand all | Expand 10 after
1238 private_key, 1291 private_key,
1239 reinterpret_cast<const unsigned char*>(encrypted_data.data()), 1292 reinterpret_cast<const unsigned char*>(encrypted_data.data()),
1240 encrypted_data.byteLength(), 1293 encrypted_data.byteLength(),
1241 &decrypted_data)); 1294 &decrypted_data));
1242 ExpectArrayBufferMatchesHex(message_hex_str, decrypted_data); 1295 ExpectArrayBufferMatchesHex(message_hex_str, decrypted_data);
1243 } 1296 }
1244 1297
1245 #endif // #if !defined(USE_OPENSSL) 1298 #endif // #if !defined(USE_OPENSSL)
1246 1299
1247 } // namespace content 1300 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698