diff --git a/src/crypto/crypto_dh.cc b/src/crypto/crypto_dh.cc index 1c48f98656fd21..86475e3b1b1e01 100644 --- a/src/crypto/crypto_dh.cc +++ b/src/crypto/crypto_dh.cc @@ -11,6 +11,7 @@ namespace node { +using v8::ArrayBuffer; using v8::ConstructorBehavior; using v8::DontDelete; using v8::FunctionCallback; @@ -28,6 +29,7 @@ using v8::ReadOnly; using v8::SideEffectType; using v8::Signature; using v8::String; +using v8::Uint8Array; using v8::Value; namespace crypto { @@ -539,41 +541,9 @@ WebCryptoKeyExportStatus DHKeyExportTraits::DoExport( } namespace { -AllocatedBuffer StatelessDiffieHellman( - Environment* env, - ManagedEVPPKey our_key, - ManagedEVPPKey their_key) { - size_t out_size; - - EVPKeyCtxPointer ctx(EVP_PKEY_CTX_new(our_key.get(), nullptr)); - if (!ctx || - EVP_PKEY_derive_init(ctx.get()) <= 0 || - EVP_PKEY_derive_set_peer(ctx.get(), their_key.get()) <= 0 || - EVP_PKEY_derive(ctx.get(), nullptr, &out_size) <= 0) - return AllocatedBuffer(); - - AllocatedBuffer result = AllocatedBuffer::AllocateManaged(env, out_size); - CHECK_NOT_NULL(result.data()); - - unsigned char* data = reinterpret_cast<unsigned char*>(result.data()); - if (EVP_PKEY_derive(ctx.get(), data, &out_size) <= 0) - return AllocatedBuffer(); - - ZeroPadDiffieHellmanSecret(out_size, &result); - return result; -} - -// The version of StatelessDiffieHellman that returns an AllocatedBuffer -// is not threadsafe because of the AllocatedBuffer allocation of a -// v8::BackingStore (it'll cause much crashing if we call it from a -// libuv worker thread). This version allocates a ByteSource instead, -// which we can convert into a v8::BackingStore later. -// TODO(@jasnell): Eliminate the code duplication between these two -// versions of the function. ByteSource StatelessDiffieHellmanThreadsafe( - Environment* env, - ManagedEVPPKey our_key, - ManagedEVPPKey their_key) { + const ManagedEVPPKey& our_key, + const ManagedEVPPKey& their_key) { size_t out_size; EVPKeyCtxPointer ctx(EVP_PKEY_CTX_new(our_key.get(), nullptr)); @@ -612,11 +582,18 @@ void DiffieHellman::Stateless(const FunctionCallbackInfo<Value>& args) { ManagedEVPPKey our_key = our_key_object->Data()->GetAsymmetricKey(); ManagedEVPPKey their_key = their_key_object->Data()->GetAsymmetricKey(); - AllocatedBuffer out = StatelessDiffieHellman(env, our_key, their_key); - if (out.size() == 0) + Local<Value> out; + { + Local<ArrayBuffer> ab = StatelessDiffieHellmanThreadsafe(our_key, their_key) + .ToArrayBuffer(env); + out = Buffer::New(env, ab, 0, ab->ByteLength()) + .FromMaybe(Local<Uint8Array>()); + } + + if (Buffer::Length(out) == 0) return ThrowCryptoError(env, ERR_get_error(), "diffieHellman failed"); - args.GetReturnValue().Set(out.ToBuffer().FromMaybe(Local<Value>())); + args.GetReturnValue().Set(out); } Maybe<bool> DHBitsTraits::AdditionalConfig( @@ -661,7 +638,6 @@ bool DHBitsTraits::DeriveBits( const DHBitsConfig& params, ByteSource* out) { *out = StatelessDiffieHellmanThreadsafe( - env, params.private_key->GetAsymmetricKey(), params.public_key->GetAsymmetricKey()); return true;