@@ -28,6 +28,7 @@ using v8::ReadOnly;
28
28
using v8::SideEffectType;
29
29
using v8::Signature;
30
30
using v8::String;
31
+ using v8::Undefined;
31
32
using v8::Value;
32
33
33
34
namespace crypto {
@@ -539,62 +540,73 @@ WebCryptoKeyExportStatus DHKeyExportTraits::DoExport(
539
540
}
540
541
541
542
namespace {
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 ));
549
549
if (!ctx ||
550
550
EVP_PKEY_derive_init (ctx.get ()) <= 0 ||
551
551
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 ;
554
554
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
+ }
557
563
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);
561
565
562
- ZeroPadDiffieHellmanSecret (out_size, &result);
563
- return result;
566
+ return true ;
564
567
}
565
568
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 (
574
570
Environment* env,
575
- ManagedEVPPKey our_key,
576
- ManagedEVPPKey their_key) {
571
+ const ManagedEVPPKey& our_key,
572
+ const ManagedEVPPKey& their_key) {
573
+ char * buf = nullptr ;
577
574
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))
593
607
return ByteSource ();
594
- }
595
608
596
- ZeroPadDiffieHellmanSecret (out_size, buf, out.size ());
597
- return out;
609
+ return ByteSource::Allocated (buf, out_size);
598
610
}
599
611
} // namespace
600
612
@@ -612,11 +624,11 @@ void DiffieHellman::Stateless(const FunctionCallbackInfo<Value>& args) {
612
624
ManagedEVPPKey our_key = our_key_object->Data ()->GetAsymmetricKey ();
613
625
ManagedEVPPKey their_key = their_key_object->Data ()->GetAsymmetricKey ();
614
626
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 )
617
629
return ThrowCryptoError (env, ERR_get_error (), " diffieHellman failed" );
618
630
619
- args.GetReturnValue ().Set (out. ToBuffer (). FromMaybe (Local<Value>()) );
631
+ args.GetReturnValue ().Set (out);
620
632
}
621
633
622
634
Maybe<bool > DHBitsTraits::AdditionalConfig (
@@ -661,7 +673,6 @@ bool DHBitsTraits::DeriveBits(
661
673
const DHBitsConfig& params,
662
674
ByteSource* out) {
663
675
*out = StatelessDiffieHellmanThreadsafe (
664
- env,
665
676
params.private_key ->GetAsymmetricKey (),
666
677
params.public_key ->GetAsymmetricKey ());
667
678
return true ;
0 commit comments