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

Unified Diff: content/renderer/webcrypto/webcrypto_impl_unittest.cc

Issue 75653002: [webcrypto] Add RSAES-PKCS1-v1_5 encrypt and decrypt for NSS. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: 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 side-by-side diff with in-line comments
Download patch
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 ffe2377a2b6b8ab2b87327c45dbcc31678969466..e1522e8d205d51b0a3f7c7df9c4e7591b5218dd3 100644
--- a/content/renderer/webcrypto/webcrypto_impl_unittest.cc
+++ b/content/renderer/webcrypto/webcrypto_impl_unittest.cc
@@ -4,6 +4,7 @@
#include "content/renderer/webcrypto/webcrypto_impl.h"
+#include <algorithm>
#include <string>
#include <vector>
@@ -80,8 +81,7 @@ blink::WebCryptoAlgorithm CreateAesCbcAlgorithm(
new blink::WebCryptoAesKeyGenParams(key_length_bits));
}
-#if !defined(USE_OPENSSL)
-blink::WebCryptoAlgorithm CreateRsaAlgorithm(
+blink::WebCryptoAlgorithm CreateRsaKeyGenAlgorithm(
blink::WebCryptoAlgorithmId algorithm_id,
unsigned modulus_length,
const std::vector<uint8>& public_exponent) {
@@ -93,7 +93,6 @@ blink::WebCryptoAlgorithm CreateRsaAlgorithm(
new blink::WebCryptoRsaKeyGenParams(
modulus_length, Start(public_exponent), public_exponent.size()));
}
-#endif // !defined(USE_OPENSSL)
} // namespace
@@ -697,9 +696,9 @@ TEST_F(WebCryptoImplTest, GenerateKeyPairRsa) {
const unsigned modulus_length = 256;
const std::vector<uint8> public_exponent = HexStringToBytes("010001");
blink::WebCryptoAlgorithm algorithm =
- CreateRsaAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5,
- modulus_length,
- public_exponent);
+ CreateRsaKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5,
+ modulus_length,
+ public_exponent);
bool extractable = false;
const blink::WebCryptoKeyUsageMask usage_mask = 0;
blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
@@ -716,7 +715,7 @@ TEST_F(WebCryptoImplTest, GenerateKeyPairRsa) {
EXPECT_EQ(usage_mask, private_key.usages());
// Fail with bad modulus.
- algorithm = CreateRsaAlgorithm(
+ algorithm = CreateRsaKeyGenAlgorithm(
blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5, 0, public_exponent);
EXPECT_FALSE(GenerateKeyPairInternal(
algorithm, extractable, usage_mask, &public_key, &private_key));
@@ -724,25 +723,26 @@ TEST_F(WebCryptoImplTest, GenerateKeyPairRsa) {
// Fail with bad exponent: larger than unsigned long.
unsigned exponent_length = sizeof(unsigned long) + 1; // NOLINT
const std::vector<uint8> long_exponent(exponent_length, 0x01);
- algorithm = CreateRsaAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5,
- modulus_length,
- long_exponent);
+ algorithm = CreateRsaKeyGenAlgorithm(
+ blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5, modulus_length, long_exponent);
EXPECT_FALSE(GenerateKeyPairInternal(
algorithm, extractable, usage_mask, &public_key, &private_key));
// Fail with bad exponent: empty.
const std::vector<uint8> empty_exponent;
- algorithm = CreateRsaAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5,
- modulus_length,
- empty_exponent);
+ algorithm =
+ CreateRsaKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5,
+ modulus_length,
+ empty_exponent);
EXPECT_FALSE(GenerateKeyPairInternal(
algorithm, extractable, usage_mask, &public_key, &private_key));
// Fail with bad exponent: all zeros.
std::vector<uint8> exponent_with_leading_zeros(15, 0x00);
- algorithm = CreateRsaAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5,
- modulus_length,
- exponent_with_leading_zeros);
+ algorithm =
+ CreateRsaKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5,
+ modulus_length,
+ exponent_with_leading_zeros);
EXPECT_FALSE(GenerateKeyPairInternal(
algorithm, extractable, usage_mask, &public_key, &private_key));
@@ -750,9 +750,10 @@ TEST_F(WebCryptoImplTest, GenerateKeyPairRsa) {
exponent_with_leading_zeros.insert(exponent_with_leading_zeros.end(),
public_exponent.begin(),
public_exponent.end());
- algorithm = CreateRsaAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5,
- modulus_length,
- exponent_with_leading_zeros);
+ algorithm =
+ CreateRsaKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5,
+ modulus_length,
+ exponent_with_leading_zeros);
EXPECT_TRUE(GenerateKeyPairInternal(
algorithm, extractable, usage_mask, &public_key, &private_key));
EXPECT_FALSE(public_key.isNull());
@@ -765,7 +766,7 @@ TEST_F(WebCryptoImplTest, GenerateKeyPairRsa) {
EXPECT_EQ(usage_mask, private_key.usages());
// Successful WebCryptoAlgorithmIdRsaOaep key generation.
- algorithm = CreateRsaAlgorithm(
+ algorithm = CreateRsaKeyGenAlgorithm(
blink::WebCryptoAlgorithmIdRsaOaep, modulus_length, public_exponent);
EXPECT_TRUE(GenerateKeyPairInternal(
algorithm, extractable, usage_mask, &public_key, &private_key));
@@ -779,9 +780,10 @@ TEST_F(WebCryptoImplTest, GenerateKeyPairRsa) {
EXPECT_EQ(usage_mask, private_key.usages());
// Successful WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 key generation.
- algorithm = CreateRsaAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
- modulus_length,
- public_exponent);
+ algorithm =
+ CreateRsaKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
+ modulus_length,
+ public_exponent);
EXPECT_TRUE(GenerateKeyPairInternal(
algorithm, extractable, usage_mask, &public_key, &private_key));
EXPECT_FALSE(public_key.isNull());
@@ -794,6 +796,137 @@ TEST_F(WebCryptoImplTest, GenerateKeyPairRsa) {
EXPECT_EQ(usage_mask, private_key.usages());
}
+// TODO(padolph): It is not clear whether we can check RSAES encryption against
+// NIST vectors, because the random data in PKCS1.5 padding makes the encryption
+// output non-deterministic unless we can force-seed NSS's PRNG.
+
+TEST_F(WebCryptoImplTest, RsaEsRoundTrip) {
+ // Note: using unrealistic short key length here to avoid bogging down tests.
+
+ // Create a key pair.
+ const unsigned kModulusLength = 256;
+ blink::WebCryptoAlgorithm algorithm =
+ CreateRsaKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5,
+ kModulusLength,
+ HexStringToBytes("010001"));
+ const blink::WebCryptoKeyUsageMask usage_mask =
+ blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt;
+ blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
+ blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
+ EXPECT_TRUE(GenerateKeyPairInternal(
+ algorithm, false, usage_mask, &public_key, &private_key));
+ EXPECT_FALSE(public_key.isNull());
+ EXPECT_FALSE(private_key.isNull());
+
+ // Make a maximum-length data message. RSAES can operate on messages up to
+ // length of k - 11 bytes, where k is the octet length of the RSA modulus.
+ const unsigned kMaxMsgSizeBytes = kModulusLength / 8 - 11;
+ // There are two hex chars for each byte.
+ const unsigned kMsgHexSize = kMaxMsgSizeBytes * 2;
+ char max_data_hex[kMsgHexSize];
+ std::fill(&max_data_hex[0], &max_data_hex[0] + kMsgHexSize, 'a');
+ max_data_hex[kMsgHexSize] = '\0';
+
+ // Verify encrypt / decrypt round trip on a few messages. Note that RSA
+ // encryption does not support empty input.
+ algorithm = CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5);
+ const char* const kTestDataHex[] = {
+ "ff",
+ "0102030405060708090a0b0c0d0e0f",
+ max_data_hex
+ };
+ blink::WebArrayBuffer encrypted_data;
+ blink::WebArrayBuffer decrypted_data;
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestDataHex); ++i) {
+ SCOPED_TRACE(i);
+ ASSERT_TRUE(EncryptInternal(
+ algorithm,
+ public_key,
+ HexStringToBytes(kTestDataHex[i]),
+ &encrypted_data));
+ EXPECT_EQ(kModulusLength/8, encrypted_data.byteLength());
+ ASSERT_TRUE(DecryptInternal(
+ algorithm,
+ private_key,
+ reinterpret_cast<const unsigned char*>(encrypted_data.data()),
+ encrypted_data.byteLength(),
+ &decrypted_data));
+ ExpectArrayBufferMatchesHex(kTestDataHex[i], decrypted_data);
+ }
+}
+
+TEST_F(WebCryptoImplTest, RsaEsFailures) {
+ // Note: using unrealistic short key length here to avoid bogging down tests.
+
+ // Create a key pair.
+ const unsigned kModulusLength = 256;
+ blink::WebCryptoAlgorithm algorithm =
+ CreateRsaKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5,
+ kModulusLength,
+ HexStringToBytes("010001"));
+ const blink::WebCryptoKeyUsageMask usage_mask =
+ blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt;
+ blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
+ blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
+ EXPECT_TRUE(GenerateKeyPairInternal(
+ algorithm, false, usage_mask, &public_key, &private_key));
+ EXPECT_FALSE(public_key.isNull());
+ EXPECT_FALSE(private_key.isNull());
+
+ // Fail encrypt with a private key.
+ algorithm = CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5);
+ blink::WebArrayBuffer encrypted_data;
+ const std::string message_hex_str("0102030405060708090a0b0c0d0e0f");
+ const std::vector<uint8> message_hex(HexStringToBytes(message_hex_str));
+ EXPECT_FALSE(
+ EncryptInternal(algorithm, private_key, message_hex, &encrypted_data));
+
+ // Fail encrypt with empty message.
+ EXPECT_FALSE(EncryptInternal(
+ algorithm, public_key, std::vector<uint8>(), &encrypted_data));
+
+ // Fail encrypt with message too large. RSAES can operate on messages up to
+ // length of k - 11 bytes, where k is the octet length of the RSA modulus.
+ const unsigned kMaxMsgSizeBytes = kModulusLength / 8 - 11;
+ EXPECT_FALSE(EncryptInternal(algorithm,
+ public_key,
+ std::vector<uint8>(kMaxMsgSizeBytes + 1, '0'),
+ &encrypted_data));
+
+ // Do a passing encrypt to generate data for decrypt.
eroman 2013/11/21 00:18:26 Not sure what a "passing encrypt" means
padolph 2013/11/21 01:56:11 Done.
+ EXPECT_TRUE(
+ EncryptInternal(algorithm, public_key, message_hex, &encrypted_data));
+
+ // Fail decrypt with a public key.
+ blink::WebArrayBuffer decrypted_data;
+ EXPECT_FALSE(DecryptInternal(
+ algorithm,
+ public_key,
+ reinterpret_cast<const unsigned char*>(encrypted_data.data()),
+ encrypted_data.byteLength(),
+ &decrypted_data));
+
+ // Corrupt encrypted data, ensure decrypt fails because padding was disrupted.
+ std::vector<uint8> corrupted_data(
+ static_cast<uint8*>(encrypted_data.data()),
+ static_cast<uint8*>(encrypted_data.data()) + encrypted_data.byteLength());
+ corrupted_data[corrupted_data.size() / 2] ^= 0x01;
+ EXPECT_FALSE(
+ DecryptInternal(algorithm, private_key, corrupted_data, &decrypted_data));
+
+ // TODO(padolph): Are there other specific data corruption scenarios to
+ // consider?
+
+ // Pass decrypt with good data just for confirmation.
+ EXPECT_TRUE(DecryptInternal(
+ algorithm,
+ private_key,
+ reinterpret_cast<const unsigned char*>(encrypted_data.data()),
+ encrypted_data.byteLength(),
+ &decrypted_data));
+ ExpectArrayBufferMatchesHex(message_hex_str, decrypted_data);
+}
+
#endif // #if !defined(USE_OPENSSL)
} // namespace content

Powered by Google App Engine
This is Rietveld 408576698