Skip to content

Commit 422740e

Browse files
committed
src,crypto: eliminate code duplication between StatelessDiffieHellman*
Signed-off-by: Darshan Sen <[email protected]>
1 parent 6bfe5a6 commit 422740e

File tree

1 file changed

+59
-48
lines changed

1 file changed

+59
-48
lines changed

src/crypto/crypto_dh.cc

Lines changed: 59 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ using v8::ReadOnly;
2828
using v8::SideEffectType;
2929
using v8::Signature;
3030
using v8::String;
31+
using v8::Undefined;
3132
using v8::Value;
3233

3334
namespace crypto {
@@ -539,62 +540,73 @@ WebCryptoKeyExportStatus DHKeyExportTraits::DoExport(
539540
}
540541

541542
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));
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

622634
Maybe<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

Comments
 (0)