@@ -28,6 +28,7 @@ using v8::ReadOnly;
2828using v8::SideEffectType;
2929using v8::Signature;
3030using v8::String;
31+ using v8::Undefined;
3132using v8::Value;
3233
3334namespace crypto {
@@ -539,62 +540,73 @@ WebCryptoKeyExportStatus DHKeyExportTraits::DoExport(
539540}
540541
541542namespace {
542- AllocatedBuffer StatelessDiffieHellman (
543- Environment* env,
544- ManagedEVPPKey our_key,
545- ManagedEVPPKey their_key) {
546- size_t out_size;
547-
548- EVPKeyCtxPointer ctx (EVP_PKEY_CTX_new (our_key.get (), nullptr ));
543+ bool CreateStatelessDiffieHellmanContext (
544+ const ManagedEVPPKey& our_key,
545+ const ManagedEVPPKey& their_key,
546+ char ** buf,
547+ size_t * out_size) {
548+ const EVPKeyCtxPointer ctx (EVP_PKEY_CTX_new (our_key.get (), nullptr ));
549549 if (!ctx ||
550550 EVP_PKEY_derive_init (ctx.get ()) <= 0 ||
551551 EVP_PKEY_derive_set_peer (ctx.get (), their_key.get ()) <= 0 ||
552- EVP_PKEY_derive (ctx.get (), nullptr , & out_size) <= 0 )
553- return AllocatedBuffer () ;
552+ EVP_PKEY_derive (ctx.get (), nullptr , out_size) <= 0 )
553+ return false ;
554554
555- AllocatedBuffer result = AllocatedBuffer::AllocateManaged (env, out_size);
556- CHECK_NOT_NULL (result.data ());
555+ *buf = MallocOpenSSL<char >(*out_size);
556+ size_t remainder_size = *out_size;
557+ if (EVP_PKEY_derive (ctx.get (),
558+ reinterpret_cast <unsigned char *>(*buf),
559+ &remainder_size) <= 0 ) {
560+ OPENSSL_clear_free (buf, *out_size);
561+ return false ;
562+ }
557563
558- unsigned char * data = reinterpret_cast <unsigned char *>(result.data ());
559- if (EVP_PKEY_derive (ctx.get (), data, &out_size) <= 0 )
560- return AllocatedBuffer ();
564+ ZeroPadDiffieHellmanSecret (remainder_size, *buf, *out_size);
561565
562- ZeroPadDiffieHellmanSecret (out_size, &result);
563- return result;
566+ return true ;
564567}
565568
566- // The version of StatelessDiffieHellman that returns an AllocatedBuffer
567- // is not threadsafe because of the AllocatedBuffer allocation of a
568- // v8::BackingStore (it'll cause much crashing if we call it from a
569- // libuv worker thread). This version allocates a ByteSource instead,
570- // which we can convert into a v8::BackingStore later.
571- // TODO(@jasnell): Eliminate the code duplication between these two
572- // versions of the function.
573- ByteSource StatelessDiffieHellmanThreadsafe (
569+ Local<Value> StatelessDiffieHellman (
574570 Environment* env,
575- ManagedEVPPKey our_key,
576- ManagedEVPPKey their_key) {
571+ const ManagedEVPPKey& our_key,
572+ const ManagedEVPPKey& their_key) {
573+ char * buf = nullptr ;
577574 size_t out_size;
578-
579- EVPKeyCtxPointer ctx (EVP_PKEY_CTX_new (our_key.get (), nullptr ));
580- if (!ctx ||
581- EVP_PKEY_derive_init (ctx.get ()) <= 0 ||
582- EVP_PKEY_derive_set_peer (ctx.get (), their_key.get ()) <= 0 ||
583- EVP_PKEY_derive (ctx.get (), nullptr , &out_size) <= 0 )
584- return ByteSource ();
585-
586- char * buf = MallocOpenSSL<char >(out_size);
587- ByteSource out = ByteSource::Allocated (buf, out_size);
588-
589- if (EVP_PKEY_derive (
590- ctx.get (),
591- reinterpret_cast <unsigned char *>(buf),
592- &out_size) <= 0 ) {
575+ if (!CreateStatelessDiffieHellmanContext (our_key,
576+ their_key,
577+ &buf,
578+ &out_size))
579+ return Undefined (env->isolate ());
580+
581+ void * hint = reinterpret_cast <void *>(static_cast <uintptr_t >(out_size));
582+ return Buffer::New (env,
583+ buf,
584+ out_size,
585+ [](char * data, void * hint) {
586+ size_t out_size = static_cast <size_t >(
587+ reinterpret_cast <uintptr_t >(hint));
588+ OPENSSL_clear_free (data, out_size);
589+ },
590+ hint).FromMaybe (Local<Object>());
591+ }
592+
593+ // The version of StatelessDiffieHellman that returns a Buffer
594+ // is not threadsafe because of the allocation of a v8::BackingStore
595+ // (it'll cause much crashing if we call it from a libuv worker
596+ // thread). This version allocates a ByteSource instead, which we can
597+ // convert into a v8::BackingStore later.
598+ ByteSource StatelessDiffieHellmanThreadsafe (
599+ const ManagedEVPPKey& our_key,
600+ const ManagedEVPPKey& their_key) {
601+ char * buf = nullptr ;
602+ size_t out_size;
603+ if (!CreateStatelessDiffieHellmanContext (our_key,
604+ their_key,
605+ &buf,
606+ &out_size))
593607 return ByteSource ();
594- }
595608
596- ZeroPadDiffieHellmanSecret (out_size, buf, out.size ());
597- return out;
609+ return ByteSource::Allocated (buf, out_size);
598610}
599611} // namespace
600612
@@ -612,11 +624,11 @@ void DiffieHellman::Stateless(const FunctionCallbackInfo<Value>& args) {
612624 ManagedEVPPKey our_key = our_key_object->Data ()->GetAsymmetricKey ();
613625 ManagedEVPPKey their_key = their_key_object->Data ()->GetAsymmetricKey ();
614626
615- AllocatedBuffer out = StatelessDiffieHellman (env, our_key, their_key);
616- if (out. size ( ) == 0 )
627+ Local<Value> out = StatelessDiffieHellman (env, our_key, their_key);
628+ if (out-> IsUndefined () || Buffer::Length (out ) == 0 )
617629 return ThrowCryptoError (env, ERR_get_error (), " diffieHellman failed" );
618630
619- args.GetReturnValue ().Set (out. ToBuffer (). FromMaybe (Local<Value>()) );
631+ args.GetReturnValue ().Set (out);
620632}
621633
622634Maybe<bool > DHBitsTraits::AdditionalConfig (
@@ -661,7 +673,6 @@ bool DHBitsTraits::DeriveBits(
661673 const DHBitsConfig& params,
662674 ByteSource* out) {
663675 *out = StatelessDiffieHellmanThreadsafe (
664- env,
665676 params.private_key ->GetAsymmetricKey (),
666677 params.public_key ->GetAsymmetricKey ());
667678 return true ;
0 commit comments