diff --git a/src/crypto/crypto_dsa.cc b/src/crypto/crypto_dsa.cc index 970ab5cf5f048b..c4016dc07c6743 100644 --- a/src/crypto/crypto_dsa.cc +++ b/src/crypto/crypto_dsa.cc @@ -133,11 +133,12 @@ Maybe GetDsaKeyDetail( const BIGNUM* p; // Modulus length const BIGNUM* q; // Divisor length - ManagedEVPPKey pkey = key->GetAsymmetricKey(); - int type = EVP_PKEY_id(pkey.get()); + ManagedEVPPKey m_pkey = key->GetAsymmetricKey(); + Mutex::ScopedLock lock(*m_pkey.mutex()); + int type = EVP_PKEY_id(m_pkey.get()); CHECK(type == EVP_PKEY_DSA); - DSA* dsa = EVP_PKEY_get0_DSA(pkey.get()); + DSA* dsa = EVP_PKEY_get0_DSA(m_pkey.get()); CHECK_NOT_NULL(dsa); DSA_get0_pqg(dsa, &p, &q, nullptr); diff --git a/src/crypto/crypto_ec.cc b/src/crypto/crypto_ec.cc index 1dd3b317633cdd..ec8b7a864d9d18 100644 --- a/src/crypto/crypto_ec.cc +++ b/src/crypto/crypto_ec.cc @@ -601,9 +601,11 @@ WebCryptoKeyExportStatus EC_Raw_Export( KeyObjectData* key_data, const ECKeyExportConfig& params, ByteSource* out) { - CHECK(key_data->GetAsymmetricKey()); + ManagedEVPPKey m_pkey = key_data->GetAsymmetricKey(); + CHECK(m_pkey); + Mutex::ScopedLock lock(*m_pkey.mutex()); - EC_KEY* ec_key = EVP_PKEY_get0_EC_KEY(key_data->GetAsymmetricKey().get()); + EC_KEY* ec_key = EVP_PKEY_get0_EC_KEY(m_pkey.get()); unsigned char* data; size_t len = 0; @@ -688,10 +690,11 @@ Maybe ExportJWKEcKey( Environment* env, std::shared_ptr key, Local target) { - ManagedEVPPKey pkey = key->GetAsymmetricKey(); - CHECK_EQ(EVP_PKEY_id(pkey.get()), EVP_PKEY_EC); + ManagedEVPPKey m_pkey = key->GetAsymmetricKey(); + Mutex::ScopedLock lock(*m_pkey.mutex()); + CHECK_EQ(EVP_PKEY_id(m_pkey.get()), EVP_PKEY_EC); - EC_KEY* ec = EVP_PKEY_get0_EC_KEY(pkey.get()); + EC_KEY* ec = EVP_PKEY_get0_EC_KEY(m_pkey.get()); CHECK_NOT_NULL(ec); const EC_POINT* pub = EC_KEY_get0_public_key(ec); @@ -893,10 +896,11 @@ Maybe GetEcKeyDetail( Environment* env, std::shared_ptr key, Local target) { - ManagedEVPPKey pkey = key->GetAsymmetricKey(); - CHECK_EQ(EVP_PKEY_id(pkey.get()), EVP_PKEY_EC); + ManagedEVPPKey m_pkey = key->GetAsymmetricKey(); + Mutex::ScopedLock lock(*m_pkey.mutex()); + CHECK_EQ(EVP_PKEY_id(m_pkey.get()), EVP_PKEY_EC); - EC_KEY* ec = EVP_PKEY_get0_EC_KEY(pkey.get()); + EC_KEY* ec = EVP_PKEY_get0_EC_KEY(m_pkey.get()); CHECK_NOT_NULL(ec); const EC_GROUP* group = EC_KEY_get0_group(ec); diff --git a/src/crypto/crypto_keys.cc b/src/crypto/crypto_keys.cc index 891e65dcbc2933..07004b78bac954 100644 --- a/src/crypto/crypto_keys.cc +++ b/src/crypto/crypto_keys.cc @@ -552,7 +552,8 @@ Maybe GetAsymmetricKeyDetail( } } // namespace -ManagedEVPPKey::ManagedEVPPKey(EVPKeyPointer&& pkey) : pkey_(std::move(pkey)) {} +ManagedEVPPKey::ManagedEVPPKey(EVPKeyPointer&& pkey) : pkey_(std::move(pkey)), + mutex_(std::make_shared()) {} ManagedEVPPKey::ManagedEVPPKey(const ManagedEVPPKey& that) { *this = that; @@ -564,6 +565,8 @@ ManagedEVPPKey& ManagedEVPPKey::operator=(const ManagedEVPPKey& that) { if (pkey_) EVP_PKEY_up_ref(pkey_.get()); + mutex_ = that.mutex_; + return *this; } @@ -575,6 +578,10 @@ EVP_PKEY* ManagedEVPPKey::get() const { return pkey_.get(); } +Mutex* ManagedEVPPKey::mutex() const { + return mutex_.get(); +} + void ManagedEVPPKey::MemoryInfo(MemoryTracker* tracker) const { tracker->TrackFieldWithSize("pkey", !pkey_ ? 0 : kSizeOf_EVP_PKEY + @@ -1326,8 +1333,10 @@ WebCryptoKeyExportStatus PKEY_SPKI_Export( KeyObjectData* key_data, ByteSource* out) { CHECK_EQ(key_data->GetKeyType(), kKeyTypePublic); + ManagedEVPPKey m_pkey = key_data->GetAsymmetricKey(); + Mutex::ScopedLock lock(*m_pkey.mutex()); BIOPointer bio(BIO_new(BIO_s_mem())); - if (!i2d_PUBKEY_bio(bio.get(), key_data->GetAsymmetricKey().get())) + if (!i2d_PUBKEY_bio(bio.get(), m_pkey.get())) return WebCryptoKeyExportStatus::FAILED; *out = ByteSource::FromBIO(bio); @@ -1338,8 +1347,11 @@ WebCryptoKeyExportStatus PKEY_PKCS8_Export( KeyObjectData* key_data, ByteSource* out) { CHECK_EQ(key_data->GetKeyType(), kKeyTypePrivate); + ManagedEVPPKey m_pkey = key_data->GetAsymmetricKey(); + Mutex::ScopedLock lock(*m_pkey.mutex()); + BIOPointer bio(BIO_new(BIO_s_mem())); - PKCS8Pointer p8inf(EVP_PKEY2PKCS8(key_data->GetAsymmetricKey().get())); + PKCS8Pointer p8inf(EVP_PKEY2PKCS8(m_pkey.get())); if (!i2d_PKCS8_PRIV_KEY_INFO_bio(bio.get(), p8inf.get())) return WebCryptoKeyExportStatus::FAILED; diff --git a/src/crypto/crypto_keys.h b/src/crypto/crypto_keys.h index 64bf45a1dba0ed..5f9fcc8510a781 100644 --- a/src/crypto/crypto_keys.h +++ b/src/crypto/crypto_keys.h @@ -81,6 +81,7 @@ class ManagedEVPPKey : public MemoryRetainer { operator bool() const; EVP_PKEY* get() const; + Mutex* mutex() const; void MemoryInfo(MemoryTracker* tracker) const override; SET_MEMORY_INFO_NAME(ManagedEVPPKey) @@ -127,6 +128,7 @@ class ManagedEVPPKey : public MemoryRetainer { size_t size_of_public_key() const; EVPKeyPointer pkey_; + std::shared_ptr mutex_; }; // Objects of this class can safely be shared among threads. diff --git a/src/crypto/crypto_rsa.cc b/src/crypto/crypto_rsa.cc index 971b184b0c53f5..741e1885e2659c 100644 --- a/src/crypto/crypto_rsa.cc +++ b/src/crypto/crypto_rsa.cc @@ -191,9 +191,10 @@ WebCryptoCipherStatus RSA_Cipher( const ByteSource& in, ByteSource* out) { CHECK_NE(key_data->GetKeyType(), kKeyTypeSecret); + ManagedEVPPKey m_pkey = key_data->GetAsymmetricKey(); + Mutex::ScopedLock lock(*m_pkey.mutex()); - EVPKeyCtxPointer ctx( - EVP_PKEY_CTX_new(key_data->GetAsymmetricKey().get(), nullptr)); + EVPKeyCtxPointer ctx(EVP_PKEY_CTX_new(m_pkey.get(), nullptr)); if (!ctx || init(ctx.get()) <= 0) return WebCryptoCipherStatus::FAILED; @@ -363,17 +364,18 @@ Maybe ExportJWKRsaKey( Environment* env, std::shared_ptr key, Local target) { - ManagedEVPPKey pkey = key->GetAsymmetricKey(); - int type = EVP_PKEY_id(pkey.get()); + ManagedEVPPKey m_pkey = key->GetAsymmetricKey(); + Mutex::ScopedLock lock(*m_pkey.mutex()); + int type = EVP_PKEY_id(m_pkey.get()); CHECK(type == EVP_PKEY_RSA || type == EVP_PKEY_RSA_PSS); // TODO(tniessen): Remove the "else" branch once we drop support for OpenSSL // versions older than 1.1.1e via FIPS / dynamic linking. RSA* rsa; if (OpenSSL_version_num() >= 0x1010105fL) { - rsa = EVP_PKEY_get0_RSA(pkey.get()); + rsa = EVP_PKEY_get0_RSA(m_pkey.get()); } else { - rsa = static_cast(EVP_PKEY_get0(pkey.get())); + rsa = static_cast(EVP_PKEY_get0(m_pkey.get())); } CHECK_NOT_NULL(rsa); @@ -511,17 +513,18 @@ Maybe GetRsaKeyDetail( const BIGNUM* e; // Public Exponent const BIGNUM* n; // Modulus - ManagedEVPPKey pkey = key->GetAsymmetricKey(); - int type = EVP_PKEY_id(pkey.get()); + ManagedEVPPKey m_pkey = key->GetAsymmetricKey(); + Mutex::ScopedLock lock(*m_pkey.mutex()); + int type = EVP_PKEY_id(m_pkey.get()); CHECK(type == EVP_PKEY_RSA || type == EVP_PKEY_RSA_PSS); // TODO(tniessen): Remove the "else" branch once we drop support for OpenSSL // versions older than 1.1.1e via FIPS / dynamic linking. RSA* rsa; if (OpenSSL_version_num() >= 0x1010105fL) { - rsa = EVP_PKEY_get0_RSA(pkey.get()); + rsa = EVP_PKEY_get0_RSA(m_pkey.get()); } else { - rsa = static_cast(EVP_PKEY_get0(pkey.get())); + rsa = static_cast(EVP_PKEY_get0(m_pkey.get())); } CHECK_NOT_NULL(rsa); diff --git a/src/crypto/crypto_sig.cc b/src/crypto/crypto_sig.cc index b0d97ade6c8bd1..dc03ca0d633348 100644 --- a/src/crypto/crypto_sig.cc +++ b/src/crypto/crypto_sig.cc @@ -96,9 +96,9 @@ AllocatedBuffer Node_SignFinal(Environment* env, return AllocatedBuffer(); } -int GetDefaultSignPadding(const ManagedEVPPKey& key) { - return EVP_PKEY_id(key.get()) == EVP_PKEY_RSA_PSS ? RSA_PKCS1_PSS_PADDING : - RSA_PKCS1_PADDING; +int GetDefaultSignPadding(const ManagedEVPPKey& m_pkey) { + return EVP_PKEY_id(m_pkey.get()) == EVP_PKEY_RSA_PSS ? RSA_PKCS1_PSS_PADDING : + RSA_PKCS1_PADDING; } unsigned int GetBytesOfRS(const ManagedEVPPKey& pkey) { @@ -752,11 +752,11 @@ Maybe SignTraits::AdditionalConfig( } // If this is an EC key (assuming ECDSA) we need to convert the // the signature from WebCrypto format into DER format... - if (EVP_PKEY_id(params->key->GetAsymmetricKey().get()) == EVP_PKEY_EC) { + ManagedEVPPKey m_pkey = params->key->GetAsymmetricKey(); + Mutex::ScopedLock lock(*m_pkey.mutex()); + if (EVP_PKEY_id(m_pkey.get()) == EVP_PKEY_EC) { params->signature = - ConvertFromWebCryptoSignature( - params->key->GetAsymmetricKey(), - signature.ToByteSource()); + ConvertFromWebCryptoSignature(m_pkey, signature.ToByteSource()); } else { params->signature = mode == kCryptoJobAsync ? signature.ToCopy() @@ -774,6 +774,8 @@ bool SignTraits::DeriveBits( EVPMDPointer context(EVP_MD_CTX_new()); EVP_PKEY_CTX* ctx = nullptr; + ManagedEVPPKey m_pkey = params.key->GetAsymmetricKey(); + Mutex::ScopedLock lock(*m_pkey.mutex()); switch (params.mode) { case SignConfiguration::kSign: CHECK_EQ(params.key->GetKeyType(), kKeyTypePrivate); @@ -782,7 +784,7 @@ bool SignTraits::DeriveBits( &ctx, params.digest, nullptr, - params.key->GetAsymmetricKey().get())) { + m_pkey.get())) { return false; } break; @@ -793,7 +795,7 @@ bool SignTraits::DeriveBits( &ctx, params.digest, nullptr, - params.key->GetAsymmetricKey().get())) { + m_pkey.get())) { return false; } break; @@ -801,13 +803,13 @@ bool SignTraits::DeriveBits( int padding = params.flags & SignConfiguration::kHasPadding ? params.padding - : GetDefaultSignPadding(params.key->GetAsymmetricKey()); + : GetDefaultSignPadding(m_pkey); Maybe salt_length = params.flags & SignConfiguration::kHasSaltLength ? Just(params.salt_length) : Nothing(); if (!ApplyRSAOptions( - params.key->GetAsymmetricKey(), + m_pkey, ctx, padding, salt_length)) {