From 6597ec5a4b7acd48801b21ad587aee2b5eb93b1c Mon Sep 17 00:00:00 2001 From: Filip Skokan Date: Tue, 28 Jul 2026 15:02:45 +0200 Subject: [PATCH 1/4] crypto: handle DH operation failures Report DH failures instead of aborting or returning an empty secret. Signed-off-by: Filip Skokan --- src/crypto/crypto_dh.cc | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/crypto/crypto_dh.cc b/src/crypto/crypto_dh.cc index a824e4e0ce90..4fa152b6f7ae 100644 --- a/src/crypto/crypto_dh.cc +++ b/src/crypto/crypto_dh.cc @@ -337,6 +337,10 @@ void ComputeSecret(const FunctionCallbackInfo& args) { } auto dp = dh.computeSecret(key); + if (!dp) { + return THROW_ERR_CRYPTO_OPERATION_FAILED(env, + "Failed to compute shared secret"); + } Local buffer; if (DataPointerToBuffer(env, std::move(dp)).ToLocal(&buffer)) { @@ -354,8 +358,9 @@ void SetPublicKey(const FunctionCallbackInfo& args) { if (!buf.CheckSizeInt32()) [[unlikely]] return THROW_ERR_OUT_OF_RANGE(env, "buf is too big"); BignumPointer num(buf.data(), buf.size()); - CHECK(num); - CHECK(dh.setPublicKey(std::move(num))); + if (!num) return THROW_ERR_INVALID_ARG_VALUE(env, "Invalid public key"); + if (!dh.setPublicKey(std::move(num))) + return THROW_ERR_INVALID_ARG_VALUE(env, "Invalid public key"); } void SetPrivateKey(const FunctionCallbackInfo& args) { @@ -368,8 +373,9 @@ void SetPrivateKey(const FunctionCallbackInfo& args) { if (!buf.CheckSizeInt32()) [[unlikely]] return THROW_ERR_OUT_OF_RANGE(env, "buf is too big"); BignumPointer num(buf.data(), buf.size()); - CHECK(num); - CHECK(dh.setPrivateKey(std::move(num))); + if (!num) return THROW_ERR_INVALID_ARG_VALUE(env, "Invalid private key"); + if (!dh.setPrivateKey(std::move(num))) + return THROW_ERR_INVALID_ARG_VALUE(env, "Invalid private key"); } void Check(const FunctionCallbackInfo& args) { From ee9bbdeaa7d89f703bd13acf5406c6863ef9f738 Mon Sep 17 00:00:00 2001 From: Filip Skokan Date: Tue, 28 Jul 2026 15:02:46 +0200 Subject: [PATCH 2/4] crypto: initialize KeyObjectData mutex eagerly Create the mutex before sharing key data so every copy uses one lock. Signed-off-by: Filip Skokan --- src/crypto/crypto_keys.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/crypto/crypto_keys.cc b/src/crypto/crypto_keys.cc index 42ea84371b9c..111462463833 100644 --- a/src/crypto/crypto_keys.cc +++ b/src/crypto/crypto_keys.cc @@ -952,10 +952,13 @@ KeyObjectData::KeyObjectData(std::nullptr_t) KeyObjectData::KeyObjectData(ByteSource symmetric_key) : key_type_(KeyType::kKeyTypeSecret), + mutex_(std::make_shared()), data_(std::make_shared(std::move(symmetric_key))) {} KeyObjectData::KeyObjectData(KeyType type, EVPKeyPointer&& pkey) - : key_type_(type), data_(std::make_shared(std::move(pkey))) {} + : key_type_(type), + mutex_(std::make_shared()), + data_(std::make_shared(std::move(pkey))) {} void KeyObjectData::Data::MemoryInfo(MemoryTracker* tracker) const { if (asymmetric_key) { From e59eb619f01b3660c193e2cb9387f5102fd672fc Mon Sep 17 00:00:00 2001 From: Filip Skokan Date: Tue, 28 Jul 2026 15:03:01 +0200 Subject: [PATCH 3/4] crypto: handle XOF output allocation failure Return an operation error when XOF output allocation fails. Signed-off-by: Filip Skokan --- src/crypto/crypto_turboshake.cc | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/crypto/crypto_turboshake.cc b/src/crypto/crypto_turboshake.cc index 6a05bf10fb8f..e53e2910c6d3 100644 --- a/src/crypto/crypto_turboshake.cc +++ b/src/crypto/crypto_turboshake.cc @@ -469,7 +469,11 @@ bool TurboShakeTraits::DeriveBits(Environment* env, CryptoJobMode mode, CryptoErrorStore* errors) { CHECK_GT(params.output_length, 0); - char* buf = MallocOpenSSL(params.output_length); + char* buf = static_cast(OPENSSL_malloc(params.output_length)); + if (buf == nullptr) { + errors->Insert(NodeCryptoError::ALLOCATION_FAILED); + return false; + } const uint8_t* input = reinterpret_cast(params.data.data()); size_t input_len = params.data.size(); @@ -595,7 +599,11 @@ bool KangarooTwelveTraits::DeriveBits(Environment* env, return false; } - char* buf = MallocOpenSSL(params.output_length); + char* buf = static_cast(OPENSSL_malloc(params.output_length)); + if (buf == nullptr) { + errors->Insert(NodeCryptoError::ALLOCATION_FAILED); + return false; + } switch (params.variant) { case KangarooTwelveVariant::KT128: From a1033046ab732dc7213892fc1060786cf954770d Mon Sep 17 00:00:00 2001 From: Filip Skokan Date: Thu, 30 Jul 2026 22:18:26 +0200 Subject: [PATCH 4/4] fixup! crypto: handle DH operation failures Signed-off-by: Filip Skokan --- src/crypto/crypto_dh.cc | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/crypto/crypto_dh.cc b/src/crypto/crypto_dh.cc index 4fa152b6f7ae..92780cfeeebf 100644 --- a/src/crypto/crypto_dh.cc +++ b/src/crypto/crypto_dh.cc @@ -358,8 +358,7 @@ void SetPublicKey(const FunctionCallbackInfo& args) { if (!buf.CheckSizeInt32()) [[unlikely]] return THROW_ERR_OUT_OF_RANGE(env, "buf is too big"); BignumPointer num(buf.data(), buf.size()); - if (!num) return THROW_ERR_INVALID_ARG_VALUE(env, "Invalid public key"); - if (!dh.setPublicKey(std::move(num))) + if (!num || !dh.setPublicKey(std::move(num))) return THROW_ERR_INVALID_ARG_VALUE(env, "Invalid public key"); } @@ -373,8 +372,7 @@ void SetPrivateKey(const FunctionCallbackInfo& args) { if (!buf.CheckSizeInt32()) [[unlikely]] return THROW_ERR_OUT_OF_RANGE(env, "buf is too big"); BignumPointer num(buf.data(), buf.size()); - if (!num) return THROW_ERR_INVALID_ARG_VALUE(env, "Invalid private key"); - if (!dh.setPrivateKey(std::move(num))) + if (!num || !dh.setPrivateKey(std::move(num))) return THROW_ERR_INVALID_ARG_VALUE(env, "Invalid private key"); }