Chromium Code Reviews| Index: content/renderer/webcrypto/webcrypto_impl_unittest.cc |
| diff --git a/content/renderer/webcrypto/webcrypto_impl_unittest.cc b/content/renderer/webcrypto/webcrypto_impl_unittest.cc |
| index 48552b76e62bb32a1fe5d0f2b6609a5f9fc13d5f..9cb33249b4ea55d4c6b25f4db4599b20695f572e 100644 |
| --- a/content/renderer/webcrypto/webcrypto_impl_unittest.cc |
| +++ b/content/renderer/webcrypto/webcrypto_impl_unittest.cc |
| @@ -94,6 +94,43 @@ blink::WebCryptoAlgorithm CreateRsaKeyGenAlgorithm( |
| #endif // #if !defined(USE_OPENSSL) |
| +// Determines if two ArrayBuffers have identical content. |
| +bool ArrayBuffersEqual( |
| + const blink::WebArrayBuffer& a, |
| + const blink::WebArrayBuffer& b) { |
| + if (a.byteLength() != b.byteLength()) |
| + return false; |
| + const uint8* a_begin = static_cast<uint8*>(a.data()); |
| + const uint8* const a_end = a_begin + a.byteLength(); |
| + const uint8* b_begin = static_cast<uint8*>(b.data()); |
| + 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
|
| +} |
| + |
| +// Adapts ArrayBufferEqual() into a unary predicate for use with std::count_if |
| +// in CopiesExist(). |
| +class ArrayBufferEqualTo { |
| + public: |
| + ArrayBufferEqualTo(const blink::WebArrayBuffer& b) : b_(b) {} |
| + bool operator()(const blink::WebArrayBuffer& a) const { |
| + return ArrayBuffersEqual(a, b_); |
| + } |
| + |
| + private: |
| + const blink::WebArrayBuffer& b_; |
| +}; |
| + |
| +// Given a vector of WebArrayBuffers, determines if there are any copies. Not |
| +// the most efficient implementation, but the vector is expected to be small. |
| +bool CopiesExist(std::vector<blink::WebArrayBuffer> bufs) { |
| + 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.
|
| + it != bufs.end(); |
| + ++it) { |
| + if (std::count_if(bufs.begin(), bufs.end(), ArrayBufferEqualTo(*it)) != 1) |
| + return true; |
| + } |
| + return false; |
| +} |
| + |
| } // namespace |
| class WebCryptoImplTest : public testing::Test { |
| @@ -432,6 +469,11 @@ TEST_F(WebCryptoImplTest, HMACSampleSets) { |
| blink::WebCryptoKey key = ImportSecretKeyFromRawHexString( |
| test.key, algorithm, blink::WebCryptoKeyUsageSign); |
| + // Verify exported raw key is identical to the imported data |
| + blink::WebArrayBuffer raw_key; |
| + EXPECT_TRUE(ExportKeyInternal(blink::WebCryptoKeyFormatRaw, key, &raw_key)); |
| + ExpectArrayBufferMatchesHex(test.key, raw_key); |
| + |
| std::vector<uint8> message_raw = HexStringToBytes(test.message); |
| blink::WebArrayBuffer output; |
| @@ -476,11 +518,17 @@ TEST_F(WebCryptoImplTest, HMACSampleSets) { |
| #if !defined(USE_OPENSSL) |
| TEST_F(WebCryptoImplTest, AesCbcFailures) { |
| + const std::string key_hex = "2b7e151628aed2a6abf7158809cf4f3c"; |
| blink::WebCryptoKey key = ImportSecretKeyFromRawHexString( |
| - "2b7e151628aed2a6abf7158809cf4f3c", |
| + key_hex, |
| webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc), |
| blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt); |
| + // Verify exported raw key is identical to the imported data |
| + blink::WebArrayBuffer raw_key; |
| + EXPECT_TRUE(ExportKeyInternal(blink::WebCryptoKeyFormatRaw, key, &raw_key)); |
| + ExpectArrayBufferMatchesHex(key_hex, raw_key); |
| + |
| blink::WebArrayBuffer output; |
| // Use an invalid |iv| (fewer than 16 bytes) |
| @@ -534,9 +582,10 @@ TEST_F(WebCryptoImplTest, AesCbcFailures) { |
| &key)); |
| } |
| - // Fail exporting the key in SPKI format (SPKI export not allowed for secret |
| - // keys) |
| + // Fail exporting the key in SPKI and PKCS#8 formats (not allowed for secret |
| + // keys). |
| EXPECT_FALSE(ExportKeyInternal(blink::WebCryptoKeyFormatSpki, key, &output)); |
| + EXPECT_FALSE(ExportKeyInternal(blink::WebCryptoKeyFormatPkcs8, key, &output)); |
| } |
| TEST_F(WebCryptoImplTest, AesCbcSampleSets) { |
| @@ -626,6 +675,11 @@ TEST_F(WebCryptoImplTest, AesCbcSampleSets) { |
| webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc), |
| blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt); |
| + // Verify exported raw key is identical to the imported data |
| + blink::WebArrayBuffer raw_key; |
| + EXPECT_TRUE(ExportKeyInternal(blink::WebCryptoKeyFormatRaw, key, &raw_key)); |
| + ExpectArrayBufferMatchesHex(test.key, raw_key); |
| + |
| std::vector<uint8> plain_text = HexStringToBytes(test.plain_text); |
| std::vector<uint8> iv = HexStringToBytes(test.iv); |
| @@ -670,14 +724,23 @@ TEST_F(WebCryptoImplTest, AesCbcSampleSets) { |
| } |
| } |
| -// TODO(padolph): Add test to verify generated symmetric keys appear random. |
| - |
| TEST_F(WebCryptoImplTest, GenerateKeyAes) { |
| - blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); |
| - ASSERT_TRUE( |
| - GenerateKeyInternal(webcrypto::CreateAesCbcKeyGenAlgorithm(128), &key)); |
| - EXPECT_TRUE(key.handle()); |
| - EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type()); |
| + // Generate a small sample of AES keys. |
| + std::vector<blink::WebArrayBuffer> keys; |
| + blink::WebArrayBuffer key_bytes; |
| + for (int i = 0; i < 16; ++i) { |
| + blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); |
| + ASSERT_TRUE( |
| + GenerateKeyInternal(webcrypto::CreateAesCbcKeyGenAlgorithm(128), &key)); |
| + EXPECT_TRUE(key.handle()); |
| + EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type()); |
| + ASSERT_TRUE( |
| + ExportKeyInternal(blink::WebCryptoKeyFormatRaw, key, &key_bytes)); |
| + keys.push_back(key_bytes); |
| + } |
| + // Ensure all entries in the key sample set are unique. This is a simplistic |
| + // estimate of whether the generated keys appear random. |
| + EXPECT_FALSE(CopiesExist(keys)); |
| } |
| TEST_F(WebCryptoImplTest, GenerateKeyAesBadLength) { |
| @@ -691,13 +754,21 @@ TEST_F(WebCryptoImplTest, GenerateKeyAesBadLength) { |
| } |
| TEST_F(WebCryptoImplTest, GenerateKeyHmac) { |
| - blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); |
| - blink::WebCryptoAlgorithm algorithm = webcrypto::CreateHmacKeyGenAlgorithm( |
| - blink::WebCryptoAlgorithmIdSha1, 128); |
| - ASSERT_TRUE(GenerateKeyInternal(algorithm, &key)); |
| - EXPECT_FALSE(key.isNull()); |
| - EXPECT_TRUE(key.handle()); |
| - EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type()); |
| + // Generate a small sample of HMAC keys. |
| + std::vector<blink::WebArrayBuffer> keys; |
| + for (int i = 0; i < 16; ++i) { |
| + blink::WebArrayBuffer key_bytes; |
| + blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); |
| + blink::WebCryptoAlgorithm algorithm = webcrypto::CreateHmacKeyGenAlgorithm( |
| + blink::WebCryptoAlgorithmIdSha1, 128); |
| + ASSERT_TRUE(GenerateKeyInternal(algorithm, &key)); |
| + EXPECT_FALSE(key.isNull()); |
| + EXPECT_TRUE(key.handle()); |
| + EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type()); |
| + } |
| + // Ensure all entries in the key sample set are unique. This is a simplistic |
| + // estimate of whether the generated keys appear random. |
| + EXPECT_FALSE(CopiesExist(keys)); |
| } |
| TEST_F(WebCryptoImplTest, GenerateKeyHmacNoLength) { |
| @@ -1119,6 +1190,10 @@ TEST_F(WebCryptoImplTest, ImportExportSpki) { |
| ASSERT_TRUE(ExportKeyInternal(blink::WebCryptoKeyFormatSpki, key, &output)); |
| ExpectArrayBufferMatchesHex(hex_rsa_spki_der, output); |
| + // Failing case: Try to export a previously imported RSA public key in raw |
| + // format (not allowed for a public key). |
| + EXPECT_FALSE(ExportKeyInternal(blink::WebCryptoKeyFormatRaw, key, &output)); |
| + |
| // Failing case: Try to export a non-extractable key |
| ASSERT_TRUE(ImportKeyInternal( |
| blink::WebCryptoKeyFormatSpki, |