Index: content/child/webcrypto/openssl/rsa_key_openssl.cc |
diff --git a/content/child/webcrypto/openssl/rsa_key_openssl.cc b/content/child/webcrypto/openssl/rsa_key_openssl.cc |
index 42098eba8e5131e281bd814d57d5e4fbe365c1e0..3c7defc6b982cec5aff619c3da694e09af96a3e7 100644 |
--- a/content/child/webcrypto/openssl/rsa_key_openssl.cc |
+++ b/content/child/webcrypto/openssl/rsa_key_openssl.cc |
@@ -88,25 +88,147 @@ Status CreateRsaHashedKeyAlgorithm( |
return Status::Success(); |
} |
-// Verifies that |key| is consistent with the input algorithm id, and creates a |
-// blink::WebCryptoKeyAlgorithm describing the key. |
-// Returns Status::Success() on success and sets |*key_algorithm|. |
-Status ValidateKeyTypeAndCreateKeyAlgorithm( |
- const blink::WebCryptoAlgorithm& algorithm, |
- EVP_PKEY* key, |
- blink::WebCryptoKeyAlgorithm* key_algorithm) { |
- // TODO(eroman): Validate the algorithm OID against the webcrypto provided |
- // hash. http://crbug.com/389400 |
- if (EVP_PKEY_id(key) != EVP_PKEY_RSA) |
- return Status::DataError(); // Data did not define an RSA key. |
- return CreateRsaHashedKeyAlgorithm(algorithm.id(), |
- GetInnerHashAlgorithm(algorithm).id(), |
- key, |
- key_algorithm); |
+Status CreateWebCryptoPrivateKey( |
+ crypto::ScopedEVP_PKEY private_key, |
+ const blink::WebCryptoAlgorithmId rsa_algorithm_id, |
+ const blink::WebCryptoAlgorithm& hash, |
+ bool extractable, |
+ blink::WebCryptoKeyUsageMask usage_mask, |
+ blink::WebCryptoKey* key) { |
+ blink::WebCryptoKeyAlgorithm key_algorithm; |
+ Status status = CreateRsaHashedKeyAlgorithm( |
+ rsa_algorithm_id, hash.id(), private_key.get(), &key_algorithm); |
+ if (status.IsError()) |
+ return status; |
+ |
+ // Serialize the key at creation time so that if structured cloning is |
+ // requested it can be done synchronously from the Blink thread. |
+ std::vector<uint8_t> pkcs8_data; |
+ status = ExportPKeyPkcs8(private_key.get(), &pkcs8_data); |
+ if (status.IsError()) |
+ return status; |
+ |
+ *key = blink::WebCryptoKey::create( |
+ new AsymKeyOpenSsl(private_key.Pass(), CryptoData(pkcs8_data)), |
+ blink::WebCryptoKeyTypePrivate, |
+ extractable, |
+ key_algorithm, |
+ usage_mask); |
+ return Status::Success(); |
+} |
+ |
+Status CreateWebCryptoPublicKey( |
+ crypto::ScopedEVP_PKEY public_key, |
+ const blink::WebCryptoAlgorithmId rsa_algorithm_id, |
+ const blink::WebCryptoAlgorithm& hash, |
+ bool extractable, |
+ blink::WebCryptoKeyUsageMask usage_mask, |
+ blink::WebCryptoKey* key) { |
+ blink::WebCryptoKeyAlgorithm key_algorithm; |
+ Status status = CreateRsaHashedKeyAlgorithm( |
+ rsa_algorithm_id, hash.id(), public_key.get(), &key_algorithm); |
+ if (status.IsError()) |
+ return status; |
+ |
+ // Serialize the key at creation time so that if structured cloning is |
+ // requested it can be done synchronously from the Blink thread. |
+ std::vector<uint8_t> spki_data; |
+ status = ExportPKeySpki(public_key.get(), &spki_data); |
+ if (status.IsError()) |
+ return status; |
+ |
+ *key = blink::WebCryptoKey::create( |
+ new AsymKeyOpenSsl(public_key.Pass(), CryptoData(spki_data)), |
+ blink::WebCryptoKeyTypePublic, |
+ extractable, |
+ key_algorithm, |
+ usage_mask); |
+ return Status::Success(); |
} |
} // namespace |
+Status RsaHashedAlgorithm::VerifyKeyUsagesBeforeGenerateKeyPair( |
+ blink::WebCryptoKeyUsageMask combined_usage_mask, |
+ blink::WebCryptoKeyUsageMask* public_usage_mask, |
+ blink::WebCryptoKeyUsageMask* private_usage_mask) const { |
+ Status status = CheckKeyCreationUsages( |
+ all_public_key_usages_ | all_private_key_usages_, combined_usage_mask); |
+ if (status.IsError()) |
+ return status; |
+ |
+ *public_usage_mask = combined_usage_mask & all_public_key_usages_; |
+ *private_usage_mask = combined_usage_mask & all_private_key_usages_; |
+ |
+ return Status::Success(); |
+} |
+ |
+Status RsaHashedAlgorithm::GenerateKeyPair( |
+ const blink::WebCryptoAlgorithm& algorithm, |
+ bool extractable, |
+ blink::WebCryptoKeyUsageMask public_usage_mask, |
+ blink::WebCryptoKeyUsageMask private_usage_mask, |
+ blink::WebCryptoKey* public_key, |
+ blink::WebCryptoKey* private_key) const { |
+ const blink::WebCryptoRsaHashedKeyGenParams* params = |
+ algorithm.rsaHashedKeyGenParams(); |
+ |
+ unsigned int public_exponent = 0; |
+ unsigned int modulus_length_bits = 0; |
+ Status status = |
+ GetRsaKeyGenParameters(params, &public_exponent, &modulus_length_bits); |
+ if (status.IsError()) |
+ return status; |
+ |
+ crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); |
+ |
+ // Generate an RSA key pair. |
+ crypto::ScopedRSA rsa_private_key(RSA_new()); |
+ crypto::ScopedBIGNUM bn(BN_new()); |
+ if (!rsa_private_key.get() || !bn.get() || |
+ !BN_set_word(bn.get(), public_exponent)) { |
+ return Status::OperationError(); |
+ } |
+ |
+ if (!RSA_generate_key_ex( |
+ rsa_private_key.get(), modulus_length_bits, bn.get(), NULL)) { |
+ return Status::OperationError(); |
+ } |
+ |
+ // Construct an EVP_PKEY for the private key. |
+ crypto::ScopedEVP_PKEY private_pkey(EVP_PKEY_new()); |
+ if (!private_pkey || |
+ !EVP_PKEY_set1_RSA(private_pkey.get(), rsa_private_key.get())) { |
+ return Status::OperationError(); |
+ } |
+ |
+ // Construct an EVP_PKEY for the public key. |
+ crypto::ScopedRSA rsa_public_key(RSAPublicKey_dup(rsa_private_key.get())); |
+ crypto::ScopedEVP_PKEY public_pkey(EVP_PKEY_new()); |
+ if (!public_pkey || |
+ !EVP_PKEY_set1_RSA(public_pkey.get(), rsa_public_key.get())) { |
+ return Status::OperationError(); |
+ } |
+ |
+ // Note that extractable is unconditionally set to true. This is because per |
+ // the WebCrypto spec generated public keys are always public. |
+ status = CreateWebCryptoPublicKey(public_pkey.Pass(), |
+ algorithm.id(), |
+ params->hash(), |
+ true, |
+ public_usage_mask, |
+ public_key); |
+ if (status.IsError()) |
+ return status; |
+ |
+ return CreateWebCryptoPrivateKey(private_pkey.Pass(), |
+ algorithm.id(), |
+ params->hash(), |
+ extractable, |
+ private_usage_mask, |
+ private_key); |
+} |
+ |
Status RsaHashedAlgorithm::VerifyKeyUsagesBeforeImportKey( |
blink::WebCryptoKeyFormat format, |
blink::WebCryptoKeyUsageMask usage_mask) const { |
@@ -145,27 +267,18 @@ Status RsaHashedAlgorithm::ImportKeyPkcs8( |
if (!private_key.get()) |
return Status::DataError(); |
- blink::WebCryptoKeyAlgorithm key_algorithm; |
- Status status = ValidateKeyTypeAndCreateKeyAlgorithm( |
- algorithm, private_key.get(), &key_algorithm); |
- if (status.IsError()) |
- return status; |
- |
- // TODO(eroman): This is probably going to be the same as the input. |
- std::vector<uint8_t> pkcs8_data; |
- status = ExportPKeyPkcs8(private_key.get(), &pkcs8_data); |
- if (status.IsError()) |
- return status; |
+ if (EVP_PKEY_id(private_key.get()) != EVP_PKEY_RSA) |
+ return Status::DataError(); // Data did not define an RSA key. |
- scoped_ptr<AsymKeyOpenSsl> key_handle( |
- new AsymKeyOpenSsl(private_key.Pass(), CryptoData(pkcs8_data))); |
+ // TODO(eroman): Validate the algorithm OID against the webcrypto provided |
+ // hash. http://crbug.com/389400 |
- *key = blink::WebCryptoKey::create(key_handle.release(), |
- blink::WebCryptoKeyTypePrivate, |
- extractable, |
- key_algorithm, |
- usage_mask); |
- return Status::Success(); |
+ return CreateWebCryptoPrivateKey(private_key.Pass(), |
+ algorithm.id(), |
+ algorithm.rsaHashedImportParams()->hash(), |
+ extractable, |
+ usage_mask, |
+ key); |
} |
Status RsaHashedAlgorithm::ImportKeySpki( |
@@ -188,27 +301,18 @@ Status RsaHashedAlgorithm::ImportKeySpki( |
if (!public_key.get()) |
return Status::DataError(); |
- blink::WebCryptoKeyAlgorithm key_algorithm; |
- Status status = ValidateKeyTypeAndCreateKeyAlgorithm( |
- algorithm, public_key.get(), &key_algorithm); |
- if (status.IsError()) |
- return status; |
- |
- // TODO(eroman): This is probably going to be the same as the input. |
- std::vector<uint8_t> spki_data; |
- status = ExportPKeySpki(public_key.get(), &spki_data); |
- if (status.IsError()) |
- return status; |
+ if (EVP_PKEY_id(public_key.get()) != EVP_PKEY_RSA) |
+ return Status::DataError(); // Data did not define an RSA key. |
- scoped_ptr<AsymKeyOpenSsl> key_handle( |
- new AsymKeyOpenSsl(public_key.Pass(), CryptoData(spki_data))); |
+ // TODO(eroman): Validate the algorithm OID against the webcrypto provided |
+ // hash. http://crbug.com/389400 |
- *key = blink::WebCryptoKey::create(key_handle.release(), |
- blink::WebCryptoKeyTypePublic, |
- extractable, |
- key_algorithm, |
- usage_mask); |
- return Status::Success(); |
+ return CreateWebCryptoPublicKey(public_key.Pass(), |
+ algorithm.id(), |
+ algorithm.rsaHashedImportParams()->hash(), |
+ extractable, |
+ usage_mask, |
+ key); |
} |
Status RsaHashedAlgorithm::ExportKeyPkcs8(const blink::WebCryptoKey& key, |