Skip to content

Commit 053cef7

Browse files
panvaaduh95
authored andcommitted
crypto: add optional callback to crypto.diffieHellman
PR-URL: #57274 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Yagiz Nizipli <[email protected]> Reviewed-By: Tobias Nießen <[email protected]>
1 parent 2a5fcb2 commit 053cef7

File tree

5 files changed

+337
-59
lines changed

5 files changed

+337
-59
lines changed

‎doc/api/crypto.md‎

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3527,23 +3527,32 @@ the corresponding digest algorithm. This does not work for all signature
35273527
algorithms, such as `'ecdsa-with-SHA256'`, so it is best to always use digest
35283528
algorithm names.
35293529

3530-
### `crypto.diffieHellman(options)`
3530+
### `crypto.diffieHellman(options[, callback])`
35313531

35323532
<!-- YAML
35333533
added:
35343534
- v13.9.0
35353535
- v12.17.0
3536+
changes:
3537+
- version: REPLACEME
3538+
pr-url: https://github.com/nodejs/node/pull/57274
3539+
description: Optional callback argument added.
35363540
-->
35373541

35383542
*`options`:{Object}
35393543
*`privateKey`:{KeyObject}
35403544
*`publicKey`:{KeyObject}
3541-
* Returns:{Buffer}
3545+
*`callback`{Function}
3546+
*`err`{Error}
3547+
*`secret`{Buffer}
3548+
* Returns:{Buffer} if the `callback` function is not provided.
35423549

35433550
Computes the Diffie-Hellman secret based on a `privateKey` and a `publicKey`.
35443551
Both keys must have the same `asymmetricKeyType`, which must be one of `'dh'`
35453552
(for Diffie-Hellman), `'ec'`, `'x448'`, or `'x25519'` (for ECDH).
35463553

3554+
If the `callback` function is provided this function uses libuv's threadpool.
3555+
35473556
### `crypto.fips`
35483557

35493558
<!-- YAML

‎lib/internal/crypto/diffiehellman.js‎

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
const{
44
ArrayBufferPrototypeSlice,
5+
FunctionPrototypeCall,
56
MathCeil,
67
ObjectDefineProperty,
78
SafeSet,
@@ -11,13 +12,14 @@ const{
1112
const{ Buffer }=require('buffer');
1213

1314
const{
15+
DHBitsJob,
1416
DiffieHellman: _DiffieHellman,
1517
DiffieHellmanGroup: _DiffieHellmanGroup,
1618
ECDH: _ECDH,
1719
ECDHBitsJob,
1820
ECDHConvertKey: _ECDHConvertKey,
19-
statelessDH,
2021
kCryptoJobAsync,
22+
kCryptoJobSync,
2123
}=internalBinding('crypto');
2224

2325
const{
@@ -32,6 +34,7 @@ const{
3234
}=require('internal/errors');
3335

3436
const{
37+
validateFunction,
3538
validateInt32,
3639
validateObject,
3740
validateString,
@@ -268,9 +271,12 @@ function getFormat(format){
268271

269272
constdhEnabledKeyTypes=newSafeSet(['dh','ec','x448','x25519']);
270273

271-
functiondiffieHellman(options){
274+
functiondiffieHellman(options,callback){
272275
validateObject(options,'options');
273276

277+
if(callback!==undefined)
278+
validateFunction(callback,'callback');
279+
274280
const{ privateKey, publicKey }=options;
275281
if(!(privateKeyinstanceofKeyObject))
276282
thrownewERR_INVALID_ARG_VALUE('options.privateKey',privateKey);
@@ -293,7 +299,24 @@ function diffieHellman(options){
293299
`${privateType} and ${publicType}`);
294300
}
295301

296-
returnstatelessDH(privateKey[kHandle],publicKey[kHandle]);
302+
constjob=newDHBitsJob(
303+
callback ? kCryptoJobAsync : kCryptoJobSync,
304+
publicKey[kHandle],
305+
privateKey[kHandle]);
306+
307+
if(!callback){
308+
const{0: err,1: secret}=job.run();
309+
if(err!==undefined)
310+
throwerr;
311+
312+
returnBuffer.from(secret);
313+
}
314+
315+
job.ondone=(error,secret)=>{
316+
if(error)returnFunctionPrototypeCall(callback,job,error);
317+
FunctionPrototypeCall(callback,job,null,Buffer.from(secret));
318+
};
319+
job.run();
297320
}
298321

299322
letmasks;

‎src/crypto/crypto_dh.cc‎

Lines changed: 16 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -483,49 +483,11 @@ WebCryptoKeyExportStatus DHKeyExportTraits::DoExport(
483483
}
484484
}
485485

486-
namespace{
487-
ByteSource StatelessDiffieHellmanThreadsafe(const EVPKeyPointer& our_key,
488-
const EVPKeyPointer& their_key){
489-
auto dp = DHPointer::stateless(our_key, their_key);
490-
if (!dp) return{};
491-
DCHECK(!dp.isSecure());
492-
493-
returnByteSource::Allocated(dp.release());
494-
}
495-
496-
voidStateless(const FunctionCallbackInfo<Value>& args){
497-
Environment* env = Environment::GetCurrent(args);
498-
499-
CHECK(args[0]->IsObject() && args[1]->IsObject());
500-
KeyObjectHandle* our_key_object;
501-
ASSIGN_OR_RETURN_UNWRAP(&our_key_object, args[0].As<Object>());
502-
CHECK_EQ(our_key_object->Data().GetKeyType(), kKeyTypePrivate);
503-
KeyObjectHandle* their_key_object;
504-
ASSIGN_OR_RETURN_UNWRAP(&their_key_object, args[1].As<Object>());
505-
CHECK_NE(their_key_object->Data().GetKeyType(), kKeyTypeSecret);
506-
507-
constauto& our_key = our_key_object->Data().GetAsymmetricKey();
508-
constauto& their_key = their_key_object->Data().GetAsymmetricKey();
509-
510-
Local<Value> out;
511-
if (!StatelessDiffieHellmanThreadsafe(our_key, their_key)
512-
.ToBuffer(env)
513-
.ToLocal(&out)) return;
514-
515-
if (Buffer::Length(out) == 0)
516-
returnThrowCryptoError(env, ERR_get_error(), "diffieHellman failed");
517-
518-
args.GetReturnValue().Set(out);
519-
}
520-
} // namespace
521-
522486
Maybe<void> DHBitsTraits::AdditionalConfig(
523487
CryptoJobMode mode,
524488
const FunctionCallbackInfo<Value>& args,
525489
unsignedint offset,
526490
DHBitsConfig* params){
527-
Environment* env = Environment::GetCurrent(args);
528-
529491
CHECK(args[offset]->IsObject()); // public key
530492
CHECK(args[offset + 1]->IsObject()); // private key
531493

@@ -535,11 +497,8 @@ Maybe<void> DHBitsTraits::AdditionalConfig(
535497
ASSIGN_OR_RETURN_UNWRAP(&public_key, args[offset], Nothing<void>());
536498
ASSIGN_OR_RETURN_UNWRAP(&private_key, args[offset + 1], Nothing<void>());
537499

538-
if (private_key->Data().GetKeyType() != kKeyTypePrivate ||
539-
public_key->Data().GetKeyType() != kKeyTypePublic){
540-
THROW_ERR_CRYPTO_INVALID_KEYTYPE(env);
541-
return Nothing<void>();
542-
}
500+
CHECK(private_key->Data().GetKeyType() == kKeyTypePrivate);
501+
CHECK(public_key->Data().GetKeyType() != kKeyTypeSecret);
543502

544503
params->public_key = public_key->Data().addRef();
545504
params->private_key = private_key->Data().addRef();
@@ -557,8 +516,20 @@ bool DHBitsTraits::DeriveBits(
557516
Environment* env,
558517
const DHBitsConfig& params,
559518
ByteSource* out){
560-
*out = StatelessDiffieHellmanThreadsafe(params.private_key.GetAsymmetricKey(),
561-
params.public_key.GetAsymmetricKey());
519+
auto dp = DHPointer::stateless(params.private_key.GetAsymmetricKey(),
520+
params.public_key.GetAsymmetricKey());
521+
if (!dp){
522+
bool can_throw =
523+
per_process::v8_initialized && Isolate::TryGetCurrent() != nullptr;
524+
if (can_throw){
525+
unsignedlong err = ERR_get_error(); // NOLINT(runtime/int)
526+
if (err) ThrowCryptoError(env, err, "diffieHellman failed");
527+
}
528+
returnfalse;
529+
}
530+
531+
*out = ByteSource::Allocated(dp.release());
532+
CHECK(!out->empty());
562533
returntrue;
563534
}
564535

@@ -611,7 +582,6 @@ void DiffieHellman::Initialize(Environment* env, Local<Object> target){
611582
make(FIXED_ONE_BYTE_STRING(env->isolate(), "DiffieHellmanGroup"),
612583
DiffieHellmanGroup);
613584

614-
SetMethodNoSideEffect(context, target, "statelessDH", Stateless);
615585
DHKeyPairGenJob::Initialize(env, target);
616586
DHKeyExportJob::Initialize(env, target);
617587
DHBitsJob::Initialize(env, target);
@@ -632,7 +602,6 @@ void DiffieHellman::RegisterExternalReferences(
632602
registry->Register(SetPrivateKey);
633603

634604
registry->Register(Check);
635-
registry->Register(Stateless);
636605

637606
DHKeyPairGenJob::RegisterExternalReferences(registry);
638607
DHKeyExportJob::RegisterExternalReferences(registry);

0 commit comments

Comments
(0)