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..c5468ffb448dabec4b39cd9431f5251daa65c8b9 100644 |
--- a/content/renderer/webcrypto/webcrypto_impl_unittest.cc |
+++ b/content/renderer/webcrypto/webcrypto_impl_unittest.cc |
@@ -40,19 +40,19 @@ blink::WebCryptoAlgorithm CreateAlgorithm(blink::WebCryptoAlgorithmId id) { |
} |
blink::WebCryptoAlgorithm CreateHmacAlgorithm( |
- blink::WebCryptoAlgorithmId hashId) { |
+ blink::WebCryptoAlgorithmId hash_id) { |
return blink::WebCryptoAlgorithm::adoptParamsAndCreate( |
blink::WebCryptoAlgorithmIdHmac, |
- new blink::WebCryptoHmacParams(CreateAlgorithm(hashId))); |
+ new blink::WebCryptoHmacParams(CreateAlgorithm(hash_id))); |
} |
blink::WebCryptoAlgorithm CreateHmacKeyAlgorithm( |
- blink::WebCryptoAlgorithmId hashId, |
+ blink::WebCryptoAlgorithmId hash_id, |
unsigned hash_length) { |
// hash_length < 0 means unspecified |
return blink::WebCryptoAlgorithm::adoptParamsAndCreate( |
blink::WebCryptoAlgorithmIdHmac, |
- new blink::WebCryptoHmacKeyParams(CreateAlgorithm(hashId), |
+ new blink::WebCryptoHmacKeyParams(CreateAlgorithm(hash_id), |
(hash_length != 0), |
hash_length)); |
} |
@@ -80,8 +80,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 +92,26 @@ blink::WebCryptoAlgorithm CreateRsaAlgorithm( |
new blink::WebCryptoRsaKeyGenParams( |
modulus_length, Start(public_exponent), public_exponent.size())); |
} |
-#endif // !defined(USE_OPENSSL) |
+ |
+// TODO(padolph): Move to webcrypto_util |
+bool IsHashAlgorithm(blink::WebCryptoAlgorithmId alg_id) { |
+ return alg_id == blink::WebCryptoAlgorithmIdSha1 || |
+ alg_id == blink::WebCryptoAlgorithmIdSha224 || |
+ alg_id == blink::WebCryptoAlgorithmIdSha256 || |
+ alg_id == blink::WebCryptoAlgorithmIdSha384 || |
+ alg_id == blink::WebCryptoAlgorithmIdSha512; |
+} |
+ |
+blink::WebCryptoAlgorithm CreateRsaAlgorithmWithInnerHash( |
+ blink::WebCryptoAlgorithmId algorithm_id, |
+ blink::WebCryptoAlgorithmId hash_id) { |
+ DCHECK(algorithm_id == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 || |
+ algorithm_id == blink::WebCryptoAlgorithmIdRsaOaep); |
+ DCHECK(IsHashAlgorithm(hash_id)); |
+ return blink::WebCryptoAlgorithm::adoptParamsAndCreate( |
+ algorithm_id, |
+ new blink::WebCryptoRsaSsaParams(CreateAlgorithm(hash_id))); |
+} |
} // namespace |
@@ -697,9 +715,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 +734,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 +742,28 @@ 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 +771,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 +787,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 +801,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 +817,132 @@ TEST_F(WebCryptoImplTest, GenerateKeyPairRsa) { |
EXPECT_EQ(usage_mask, private_key.usages()); |
} |
+TEST_F(WebCryptoImplTest, SignVerifyRsa) { |
+ |
+ // Generate an RSA key pair. |
+ blink::WebCryptoAlgorithm algorithm = |
+ CreateRsaKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, |
+ 1024, |
+ HexStringToBytes("010001")); |
+ const blink::WebCryptoKeyUsageMask usage_mask = |
+ blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify; |
+ blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull(); |
+ blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull(); |
+ EXPECT_TRUE(GenerateKeyPairInternal( |
+ algorithm, true, usage_mask, &public_key, &private_key)); |
+ EXPECT_FALSE(public_key.isNull()); |
+ EXPECT_FALSE(private_key.isNull()); |
+ |
+ algorithm = CreateRsaAlgorithmWithInnerHash( |
+ blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, |
+ blink::WebCryptoAlgorithmIdSha1); |
+ blink::WebArrayBuffer signature; |
+ bool signature_match = false; |
+ |
+ const char* kTestData[] = {"", "00", "010203040506070809"}; |
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestData); ++i) { |
+ |
+ SCOPED_TRACE(i); |
+ |
+ // Sign data with the private key. |
+ const std::vector<uint8> data = HexStringToBytes(kTestData[i]); |
+ ASSERT_TRUE(SignInternal(algorithm, private_key, data, &signature)); |
+ |
+ // Verify the signature with the public key. |
+ signature_match = false; |
+ EXPECT_TRUE(VerifySignatureInternal( |
+ algorithm, |
+ public_key, |
+ static_cast<const unsigned char*>(signature.data()), |
+ signature.byteLength(), |
+ data, |
+ &signature_match)); |
+ EXPECT_TRUE(signature_match); |
+ } |
+ |
+ const std::vector<uint8> data = HexStringToBytes("010203040506070809"); |
+ ASSERT_TRUE(SignInternal(algorithm, private_key, data, &signature)); |
+ |
+ // Ensure truncated signature does not verify by passing one less byte. |
+ signature_match = false; |
+ EXPECT_TRUE(VerifySignatureInternal( |
+ algorithm, |
+ public_key, |
+ static_cast<const unsigned char*>(signature.data()), |
+ signature.byteLength() - 1, |
+ data, |
+ &signature_match)); |
+ EXPECT_FALSE(signature_match); |
+ |
+ // Ensure corrupted signature does not verify. |
+ std::vector<uint8> corrupt_sig( |
+ static_cast<uint8*>(signature.data()), |
+ static_cast<uint8*>(signature.data()) + signature.byteLength()); |
+ corrupt_sig[corrupt_sig.size() / 2] ^= 0x1; |
+ signature_match = false; |
+ EXPECT_TRUE(VerifySignatureInternal( |
+ algorithm, |
+ public_key, |
+ Start(corrupt_sig), |
+ corrupt_sig.size(), |
+ data, |
+ &signature_match)); |
+ EXPECT_FALSE(signature_match); |
+ |
+ // Ensure extra long signature does not cause issues and fails. |
+ const unsigned char kLongSignature[1024] = { 0 }; |
+ EXPECT_TRUE(VerifySignatureInternal( |
+ algorithm, |
+ public_key, |
+ kLongSignature, |
+ sizeof(kLongSignature), |
+ data, |
+ &signature_match)); |
+ EXPECT_FALSE(signature_match); |
+ |
+ // Ensure can't verify using a private key. |
+ EXPECT_FALSE(VerifySignatureInternal( |
+ algorithm, |
+ private_key, |
+ static_cast<const unsigned char*>(signature.data()), |
+ signature.byteLength(), |
+ data, |
+ &signature_match)); |
+ |
+ // Ensure can't sign using a public key. |
+ EXPECT_FALSE(SignInternal(algorithm, public_key, data, &signature)); |
+ |
+ // TODO(padolph): Not sure this kind of test is required here, it might be |
+ // more appropriate on the Blink side. |
+ // Fail sign and verify with malformed algorithm (no inner hash) |
+ algorithm = CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5); |
+ EXPECT_FALSE(SignInternal(algorithm, private_key, data, &signature)); |
+ EXPECT_FALSE(VerifySignatureInternal( |
+ algorithm, |
+ public_key, |
+ static_cast<const unsigned char*>(signature.data()), |
+ signature.byteLength(), |
+ data, |
+ &signature_match)); |
+ |
+ // TODO(padolph): Not sure this kind of test is required here, it might be |
+ // more appropriate on the Blink side. |
+ // Fail sign and verify with incompatible algorithm |
+ algorithm = CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5); |
+ EXPECT_FALSE(SignInternal(algorithm, private_key, data, &signature)); |
+ EXPECT_FALSE(VerifySignatureInternal( |
+ algorithm, |
+ public_key, |
+ static_cast<const unsigned char*>(signature.data()), |
+ signature.byteLength(), |
+ data, |
+ &signature_match)); |
+} |
+ |
+// TODO(padolph): RSA sign sample sets. NIST RSA test keys are in discrete |
+// format (primes and coefficients), so we need both public and private JWK key |
+// import working first. |
+ |
#endif // #if !defined(USE_OPENSSL) |
} // namespace content |