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 "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 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
85 algorithm_id == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 || | 85 algorithm_id == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 || |
86 algorithm_id == blink::WebCryptoAlgorithmIdRsaOaep); | 86 algorithm_id == blink::WebCryptoAlgorithmIdRsaOaep); |
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 // Determines if two ArrayBuffers have identical content. |
| 96 bool ArrayBuffersEqual( |
| 97 const blink::WebArrayBuffer& a, |
| 98 const blink::WebArrayBuffer& b) { |
| 99 return a.byteLength() == b.byteLength() && |
| 100 memcmp(a.data(), b.data(), a.byteLength()) == 0; |
| 101 } |
| 102 |
| 103 // Given a vector of WebArrayBuffers, determines if there are any copies. |
| 104 bool CopiesExist(std::vector<blink::WebArrayBuffer> bufs) { |
| 105 for (size_t i = 0; i < bufs.size(); ++i) { |
| 106 for (size_t j = i + 1; j < bufs.size(); ++j) { |
| 107 if (ArrayBuffersEqual(bufs[i], bufs[j])) |
| 108 return true; |
| 109 } |
| 110 } |
| 111 return false; |
| 112 } |
| 113 |
95 #endif // #if !defined(USE_OPENSSL) | 114 #endif // #if !defined(USE_OPENSSL) |
96 | 115 |
97 } // namespace | 116 } // namespace |
98 | 117 |
99 class WebCryptoImplTest : public testing::Test { | 118 class WebCryptoImplTest : public testing::Test { |
100 protected: | 119 protected: |
101 blink::WebCryptoKey ImportSecretKeyFromRawHexString( | 120 blink::WebCryptoKey ImportSecretKeyFromRawHexString( |
102 const std::string& key_hex, | 121 const std::string& key_hex, |
103 const blink::WebCryptoAlgorithm& algorithm, | 122 const blink::WebCryptoAlgorithm& algorithm, |
104 blink::WebCryptoKeyUsageMask usage) { | 123 blink::WebCryptoKeyUsageMask usage) { |
(...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
425 ++test_index) { | 444 ++test_index) { |
426 SCOPED_TRACE(test_index); | 445 SCOPED_TRACE(test_index); |
427 const TestCase& test = kTests[test_index]; | 446 const TestCase& test = kTests[test_index]; |
428 | 447 |
429 blink::WebCryptoAlgorithm algorithm = | 448 blink::WebCryptoAlgorithm algorithm = |
430 webcrypto::CreateHmacAlgorithmByHashId(test.algorithm); | 449 webcrypto::CreateHmacAlgorithmByHashId(test.algorithm); |
431 | 450 |
432 blink::WebCryptoKey key = ImportSecretKeyFromRawHexString( | 451 blink::WebCryptoKey key = ImportSecretKeyFromRawHexString( |
433 test.key, algorithm, blink::WebCryptoKeyUsageSign); | 452 test.key, algorithm, blink::WebCryptoKeyUsageSign); |
434 | 453 |
| 454 // Verify exported raw key is identical to the imported data |
| 455 blink::WebArrayBuffer raw_key; |
| 456 EXPECT_TRUE(ExportKeyInternal(blink::WebCryptoKeyFormatRaw, key, &raw_key)); |
| 457 ExpectArrayBufferMatchesHex(test.key, raw_key); |
| 458 |
435 std::vector<uint8> message_raw = HexStringToBytes(test.message); | 459 std::vector<uint8> message_raw = HexStringToBytes(test.message); |
436 | 460 |
437 blink::WebArrayBuffer output; | 461 blink::WebArrayBuffer output; |
438 | 462 |
439 ASSERT_TRUE(SignInternal(algorithm, key, message_raw, &output)); | 463 ASSERT_TRUE(SignInternal(algorithm, key, message_raw, &output)); |
440 | 464 |
441 ExpectArrayBufferMatchesHex(test.mac, output); | 465 ExpectArrayBufferMatchesHex(test.mac, output); |
442 | 466 |
443 bool signature_match = false; | 467 bool signature_match = false; |
444 EXPECT_TRUE(VerifySignatureInternal( | 468 EXPECT_TRUE(VerifySignatureInternal( |
(...skipping 24 matching lines...) Expand all Loading... |
469 sizeof(kLongSignature), | 493 sizeof(kLongSignature), |
470 message_raw, | 494 message_raw, |
471 &signature_match)); | 495 &signature_match)); |
472 EXPECT_FALSE(signature_match); | 496 EXPECT_FALSE(signature_match); |
473 } | 497 } |
474 } | 498 } |
475 | 499 |
476 #if !defined(USE_OPENSSL) | 500 #if !defined(USE_OPENSSL) |
477 | 501 |
478 TEST_F(WebCryptoImplTest, AesCbcFailures) { | 502 TEST_F(WebCryptoImplTest, AesCbcFailures) { |
| 503 const std::string key_hex = "2b7e151628aed2a6abf7158809cf4f3c"; |
479 blink::WebCryptoKey key = ImportSecretKeyFromRawHexString( | 504 blink::WebCryptoKey key = ImportSecretKeyFromRawHexString( |
480 "2b7e151628aed2a6abf7158809cf4f3c", | 505 key_hex, |
481 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc), | 506 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc), |
482 blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt); | 507 blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt); |
483 | 508 |
| 509 // Verify exported raw key is identical to the imported data |
| 510 blink::WebArrayBuffer raw_key; |
| 511 EXPECT_TRUE(ExportKeyInternal(blink::WebCryptoKeyFormatRaw, key, &raw_key)); |
| 512 ExpectArrayBufferMatchesHex(key_hex, raw_key); |
| 513 |
484 blink::WebArrayBuffer output; | 514 blink::WebArrayBuffer output; |
485 | 515 |
486 // Use an invalid |iv| (fewer than 16 bytes) | 516 // Use an invalid |iv| (fewer than 16 bytes) |
487 { | 517 { |
488 std::vector<uint8> input(32); | 518 std::vector<uint8> input(32); |
489 std::vector<uint8> iv; | 519 std::vector<uint8> iv; |
490 EXPECT_FALSE(EncryptInternal( | 520 EXPECT_FALSE(EncryptInternal( |
491 webcrypto::CreateAesCbcAlgorithm(iv), key, input, &output)); | 521 webcrypto::CreateAesCbcAlgorithm(iv), key, input, &output)); |
492 EXPECT_FALSE(DecryptInternal( | 522 EXPECT_FALSE(DecryptInternal( |
493 webcrypto::CreateAesCbcAlgorithm(iv), key, input, &output)); | 523 webcrypto::CreateAesCbcAlgorithm(iv), key, input, &output)); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
527 | 557 |
528 blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); | 558 blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); |
529 EXPECT_FALSE(ImportKeyInternal(blink::WebCryptoKeyFormatRaw, | 559 EXPECT_FALSE(ImportKeyInternal(blink::WebCryptoKeyFormatRaw, |
530 key_raw, | 560 key_raw, |
531 webcrypto::CreateAesCbcAlgorithm(iv), | 561 webcrypto::CreateAesCbcAlgorithm(iv), |
532 true, | 562 true, |
533 blink::WebCryptoKeyUsageEncrypt, | 563 blink::WebCryptoKeyUsageEncrypt, |
534 &key)); | 564 &key)); |
535 } | 565 } |
536 | 566 |
537 // Fail exporting the key in SPKI format (SPKI export not allowed for secret | 567 // Fail exporting the key in SPKI and PKCS#8 formats (not allowed for secret |
538 // keys) | 568 // keys). |
539 EXPECT_FALSE(ExportKeyInternal(blink::WebCryptoKeyFormatSpki, key, &output)); | 569 EXPECT_FALSE(ExportKeyInternal(blink::WebCryptoKeyFormatSpki, key, &output)); |
| 570 EXPECT_FALSE(ExportKeyInternal(blink::WebCryptoKeyFormatPkcs8, key, &output)); |
540 } | 571 } |
541 | 572 |
542 TEST_F(WebCryptoImplTest, AesCbcSampleSets) { | 573 TEST_F(WebCryptoImplTest, AesCbcSampleSets) { |
543 struct TestCase { | 574 struct TestCase { |
544 const char* key; | 575 const char* key; |
545 const char* iv; | 576 const char* iv; |
546 const char* plain_text; | 577 const char* plain_text; |
547 const char* cipher_text; | 578 const char* cipher_text; |
548 }; | 579 }; |
549 | 580 |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
619 | 650 |
620 for (size_t index = 0; index < ARRAYSIZE_UNSAFE(kTests); index++) { | 651 for (size_t index = 0; index < ARRAYSIZE_UNSAFE(kTests); index++) { |
621 SCOPED_TRACE(index); | 652 SCOPED_TRACE(index); |
622 const TestCase& test = kTests[index]; | 653 const TestCase& test = kTests[index]; |
623 | 654 |
624 blink::WebCryptoKey key = ImportSecretKeyFromRawHexString( | 655 blink::WebCryptoKey key = ImportSecretKeyFromRawHexString( |
625 test.key, | 656 test.key, |
626 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc), | 657 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc), |
627 blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt); | 658 blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt); |
628 | 659 |
| 660 // Verify exported raw key is identical to the imported data |
| 661 blink::WebArrayBuffer raw_key; |
| 662 EXPECT_TRUE(ExportKeyInternal(blink::WebCryptoKeyFormatRaw, key, &raw_key)); |
| 663 ExpectArrayBufferMatchesHex(test.key, raw_key); |
| 664 |
629 std::vector<uint8> plain_text = HexStringToBytes(test.plain_text); | 665 std::vector<uint8> plain_text = HexStringToBytes(test.plain_text); |
630 std::vector<uint8> iv = HexStringToBytes(test.iv); | 666 std::vector<uint8> iv = HexStringToBytes(test.iv); |
631 | 667 |
632 blink::WebArrayBuffer output; | 668 blink::WebArrayBuffer output; |
633 | 669 |
634 // Test encryption. | 670 // Test encryption. |
635 EXPECT_TRUE(EncryptInternal(webcrypto::CreateAesCbcAlgorithm(iv), | 671 EXPECT_TRUE(EncryptInternal(webcrypto::CreateAesCbcAlgorithm(iv), |
636 key, | 672 key, |
637 plain_text, | 673 plain_text, |
638 &output)); | 674 &output)); |
(...skipping 24 matching lines...) Expand all Loading... |
663 if (cipher_text.size() > 3) { | 699 if (cipher_text.size() > 3) { |
664 EXPECT_FALSE(DecryptInternal(webcrypto::CreateAesCbcAlgorithm(iv), | 700 EXPECT_FALSE(DecryptInternal(webcrypto::CreateAesCbcAlgorithm(iv), |
665 key, | 701 key, |
666 &cipher_text[0], | 702 &cipher_text[0], |
667 cipher_text.size() - 3, | 703 cipher_text.size() - 3, |
668 &output)); | 704 &output)); |
669 } | 705 } |
670 } | 706 } |
671 } | 707 } |
672 | 708 |
673 // TODO(padolph): Add test to verify generated symmetric keys appear random. | |
674 | |
675 TEST_F(WebCryptoImplTest, GenerateKeyAes) { | 709 TEST_F(WebCryptoImplTest, GenerateKeyAes) { |
676 blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); | 710 // Generate a small sample of AES keys. |
677 ASSERT_TRUE( | 711 std::vector<blink::WebArrayBuffer> keys; |
678 GenerateKeyInternal(webcrypto::CreateAesCbcKeyGenAlgorithm(128), &key)); | 712 blink::WebArrayBuffer key_bytes; |
679 EXPECT_TRUE(key.handle()); | 713 for (int i = 0; i < 16; ++i) { |
680 EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type()); | 714 blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); |
| 715 ASSERT_TRUE( |
| 716 GenerateKeyInternal(webcrypto::CreateAesCbcKeyGenAlgorithm(128), &key)); |
| 717 EXPECT_TRUE(key.handle()); |
| 718 EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type()); |
| 719 ASSERT_TRUE( |
| 720 ExportKeyInternal(blink::WebCryptoKeyFormatRaw, key, &key_bytes)); |
| 721 keys.push_back(key_bytes); |
| 722 } |
| 723 // Ensure all entries in the key sample set are unique. This is a simplistic |
| 724 // estimate of whether the generated keys appear random. |
| 725 EXPECT_FALSE(CopiesExist(keys)); |
681 } | 726 } |
682 | 727 |
683 TEST_F(WebCryptoImplTest, GenerateKeyAesBadLength) { | 728 TEST_F(WebCryptoImplTest, GenerateKeyAesBadLength) { |
684 blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); | 729 blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); |
685 EXPECT_FALSE( | 730 EXPECT_FALSE( |
686 GenerateKeyInternal(webcrypto::CreateAesCbcKeyGenAlgorithm(0), &key)); | 731 GenerateKeyInternal(webcrypto::CreateAesCbcKeyGenAlgorithm(0), &key)); |
687 EXPECT_FALSE( | 732 EXPECT_FALSE( |
688 GenerateKeyInternal(webcrypto::CreateAesCbcKeyGenAlgorithm(0), &key)); | 733 GenerateKeyInternal(webcrypto::CreateAesCbcKeyGenAlgorithm(0), &key)); |
689 EXPECT_FALSE( | 734 EXPECT_FALSE( |
690 GenerateKeyInternal(webcrypto::CreateAesCbcKeyGenAlgorithm(129), &key)); | 735 GenerateKeyInternal(webcrypto::CreateAesCbcKeyGenAlgorithm(129), &key)); |
691 } | 736 } |
692 | 737 |
693 TEST_F(WebCryptoImplTest, GenerateKeyHmac) { | 738 TEST_F(WebCryptoImplTest, GenerateKeyHmac) { |
694 blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); | 739 // Generate a small sample of HMAC keys. |
695 blink::WebCryptoAlgorithm algorithm = webcrypto::CreateHmacKeyGenAlgorithm( | 740 std::vector<blink::WebArrayBuffer> keys; |
696 blink::WebCryptoAlgorithmIdSha1, 128); | 741 for (int i = 0; i < 16; ++i) { |
697 ASSERT_TRUE(GenerateKeyInternal(algorithm, &key)); | 742 blink::WebArrayBuffer key_bytes; |
698 EXPECT_FALSE(key.isNull()); | 743 blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); |
699 EXPECT_TRUE(key.handle()); | 744 blink::WebCryptoAlgorithm algorithm = webcrypto::CreateHmacKeyGenAlgorithm( |
700 EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type()); | 745 blink::WebCryptoAlgorithmIdSha1, 128); |
| 746 ASSERT_TRUE(GenerateKeyInternal(algorithm, &key)); |
| 747 EXPECT_FALSE(key.isNull()); |
| 748 EXPECT_TRUE(key.handle()); |
| 749 EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type()); |
| 750 } |
| 751 // Ensure all entries in the key sample set are unique. This is a simplistic |
| 752 // estimate of whether the generated keys appear random. |
| 753 EXPECT_FALSE(CopiesExist(keys)); |
701 } | 754 } |
702 | 755 |
703 TEST_F(WebCryptoImplTest, GenerateKeyHmacNoLength) { | 756 TEST_F(WebCryptoImplTest, GenerateKeyHmacNoLength) { |
704 blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); | 757 blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); |
705 blink::WebCryptoAlgorithm algorithm = | 758 blink::WebCryptoAlgorithm algorithm = |
706 webcrypto::CreateHmacKeyGenAlgorithm(blink::WebCryptoAlgorithmIdSha1, 0); | 759 webcrypto::CreateHmacKeyGenAlgorithm(blink::WebCryptoAlgorithmIdSha1, 0); |
707 ASSERT_TRUE(GenerateKeyInternal(algorithm, &key)); | 760 ASSERT_TRUE(GenerateKeyInternal(algorithm, &key)); |
708 EXPECT_TRUE(key.handle()); | 761 EXPECT_TRUE(key.handle()); |
709 EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type()); | 762 EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type()); |
710 } | 763 } |
(...skipping 401 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1112 true, | 1165 true, |
1113 blink::WebCryptoKeyUsageEncrypt, | 1166 blink::WebCryptoKeyUsageEncrypt, |
1114 &key)); | 1167 &key)); |
1115 | 1168 |
1116 // Passing case: Export a previously imported RSA public key in SPKI format | 1169 // Passing case: Export a previously imported RSA public key in SPKI format |
1117 // and compare to original data. | 1170 // and compare to original data. |
1118 blink::WebArrayBuffer output; | 1171 blink::WebArrayBuffer output; |
1119 ASSERT_TRUE(ExportKeyInternal(blink::WebCryptoKeyFormatSpki, key, &output)); | 1172 ASSERT_TRUE(ExportKeyInternal(blink::WebCryptoKeyFormatSpki, key, &output)); |
1120 ExpectArrayBufferMatchesHex(hex_rsa_spki_der, output); | 1173 ExpectArrayBufferMatchesHex(hex_rsa_spki_der, output); |
1121 | 1174 |
| 1175 // Failing case: Try to export a previously imported RSA public key in raw |
| 1176 // format (not allowed for a public key). |
| 1177 EXPECT_FALSE(ExportKeyInternal(blink::WebCryptoKeyFormatRaw, key, &output)); |
| 1178 |
1122 // Failing case: Try to export a non-extractable key | 1179 // Failing case: Try to export a non-extractable key |
1123 ASSERT_TRUE(ImportKeyInternal( | 1180 ASSERT_TRUE(ImportKeyInternal( |
1124 blink::WebCryptoKeyFormatSpki, | 1181 blink::WebCryptoKeyFormatSpki, |
1125 HexStringToBytes(hex_rsa_spki_der), | 1182 HexStringToBytes(hex_rsa_spki_der), |
1126 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5), | 1183 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5), |
1127 false, | 1184 false, |
1128 blink::WebCryptoKeyUsageEncrypt, | 1185 blink::WebCryptoKeyUsageEncrypt, |
1129 &key)); | 1186 &key)); |
1130 EXPECT_TRUE(key.handle()); | 1187 EXPECT_TRUE(key.handle()); |
1131 EXPECT_FALSE(key.extractable()); | 1188 EXPECT_FALSE(key.extractable()); |
(...skipping 443 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1575 private_key, | 1632 private_key, |
1576 reinterpret_cast<const unsigned char*>(encrypted_data.data()), | 1633 reinterpret_cast<const unsigned char*>(encrypted_data.data()), |
1577 encrypted_data.byteLength(), | 1634 encrypted_data.byteLength(), |
1578 &decrypted_data)); | 1635 &decrypted_data)); |
1579 ExpectArrayBufferMatchesHex(message_hex_str, decrypted_data); | 1636 ExpectArrayBufferMatchesHex(message_hex_str, decrypted_data); |
1580 } | 1637 } |
1581 | 1638 |
1582 #endif // #if !defined(USE_OPENSSL) | 1639 #endif // #if !defined(USE_OPENSSL) |
1583 | 1640 |
1584 } // namespace content | 1641 } // namespace content |
OLD | NEW |