Skip to content

Commit 233740c

Browse files
bnoordhuisaddaleax
authored andcommitted
src: remove extra heap allocations in DH functions
Replace allocate + Encode() + free patterns by calls to Malloc + the Buffer::New() overload that takes ownership of the pointer. Avoids unnecessary heap allocations and copying around of data. DRY the accessor functions for the prime, generator, public key and private key properties; deletes about 40 lines of quadruplicated code. PR-URL: #14122 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: James M Snell <[email protected]>
1 parent 8e51d31 commit 233740c

File tree

2 files changed

+31
-77
lines changed

2 files changed

+31
-77
lines changed

src/node_crypto.cc

+29-77
Original file line numberDiff line numberDiff line change
@@ -4762,99 +4762,49 @@ void DiffieHellman::GenerateKeys(const FunctionCallbackInfo<Value>& args) {
47624762
return ThrowCryptoError(env, ERR_get_error(), "Key generation failed");
47634763
}
47644764

4765-
int dataSize = BN_num_bytes(diffieHellman->dh->pub_key);
4766-
char* data = new char[dataSize];
4767-
BN_bn2bin(diffieHellman->dh->pub_key,
4768-
reinterpret_cast<unsigned char*>(data));
4769-
4770-
args.GetReturnValue().Set(Encode(env->isolate(), data, dataSize, BUFFER));
4771-
delete[] data;
4765+
size_t size = BN_num_bytes(diffieHellman->dh->pub_key);
4766+
char* data = Malloc(size);
4767+
BN_bn2bin(diffieHellman->dh->pub_key, reinterpret_cast<unsigned char*>(data));
4768+
args.GetReturnValue().Set(Buffer::New(env, data, size).ToLocalChecked());
47724769
}
47734770

47744771

4775-
void DiffieHellman::GetPrime(const FunctionCallbackInfo<Value>& args) {
4772+
void DiffieHellman::GetField(const FunctionCallbackInfo<Value>& args,
4773+
BIGNUM* (DH::*field), const char* err_if_null) {
47764774
Environment* env = Environment::GetCurrent(args);
47774775

4778-
DiffieHellman* diffieHellman;
4779-
ASSIGN_OR_RETURN_UNWRAP(&diffieHellman, args.Holder());
4776+
DiffieHellman* dh;
4777+
ASSIGN_OR_RETURN_UNWRAP(&dh, args.Holder());
4778+
if (!dh->initialised_) return env->ThrowError("Not initialized");
47804779

4781-
if (!diffieHellman->initialised_) {
4782-
return ThrowCryptoError(env, ERR_get_error(), "Not initialized");
4783-
}
4780+
const BIGNUM* num = (dh->dh)->*field;
4781+
if (num == nullptr) return env->ThrowError(err_if_null);
47844782

4785-
int dataSize = BN_num_bytes(diffieHellman->dh->p);
4786-
char* data = new char[dataSize];
4787-
BN_bn2bin(diffieHellman->dh->p, reinterpret_cast<unsigned char*>(data));
4783+
size_t size = BN_num_bytes(num);
4784+
char* data = Malloc(size);
4785+
BN_bn2bin(num, reinterpret_cast<unsigned char*>(data));
4786+
args.GetReturnValue().Set(Buffer::New(env, data, size).ToLocalChecked());
4787+
}
47884788

4789-
args.GetReturnValue().Set(Encode(env->isolate(), data, dataSize, BUFFER));
4790-
delete[] data;
4789+
void DiffieHellman::GetPrime(const FunctionCallbackInfo<Value>& args) {
4790+
GetField(args, &DH::p, "p is null");
47914791
}
47924792

47934793

47944794
void DiffieHellman::GetGenerator(const FunctionCallbackInfo<Value>& args) {
4795-
Environment* env = Environment::GetCurrent(args);
4796-
4797-
DiffieHellman* diffieHellman;
4798-
ASSIGN_OR_RETURN_UNWRAP(&diffieHellman, args.Holder());
4799-
4800-
if (!diffieHellman->initialised_) {
4801-
return ThrowCryptoError(env, ERR_get_error(), "Not initialized");
4802-
}
4803-
4804-
int dataSize = BN_num_bytes(diffieHellman->dh->g);
4805-
char* data = new char[dataSize];
4806-
BN_bn2bin(diffieHellman->dh->g, reinterpret_cast<unsigned char*>(data));
4807-
4808-
args.GetReturnValue().Set(Encode(env->isolate(), data, dataSize, BUFFER));
4809-
delete[] data;
4795+
GetField(args, &DH::g, "g is null");
48104796
}
48114797

48124798

48134799
void DiffieHellman::GetPublicKey(const FunctionCallbackInfo<Value>& args) {
4814-
Environment* env = Environment::GetCurrent(args);
4815-
4816-
DiffieHellman* diffieHellman;
4817-
ASSIGN_OR_RETURN_UNWRAP(&diffieHellman, args.Holder());
4818-
4819-
if (!diffieHellman->initialised_) {
4820-
return ThrowCryptoError(env, ERR_get_error(), "Not initialized");
4821-
}
4822-
4823-
if (diffieHellman->dh->pub_key == nullptr) {
4824-
return env->ThrowError("No public key - did you forget to generate one?");
4825-
}
4826-
4827-
int dataSize = BN_num_bytes(diffieHellman->dh->pub_key);
4828-
char* data = new char[dataSize];
4829-
BN_bn2bin(diffieHellman->dh->pub_key,
4830-
reinterpret_cast<unsigned char*>(data));
4831-
4832-
args.GetReturnValue().Set(Encode(env->isolate(), data, dataSize, BUFFER));
4833-
delete[] data;
4800+
GetField(args, &DH::pub_key,
4801+
"No public key - did you forget to generate one?");
48344802
}
48354803

48364804

48374805
void DiffieHellman::GetPrivateKey(const FunctionCallbackInfo<Value>& args) {
4838-
Environment* env = Environment::GetCurrent(args);
4839-
4840-
DiffieHellman* diffieHellman;
4841-
ASSIGN_OR_RETURN_UNWRAP(&diffieHellman, args.Holder());
4842-
4843-
if (!diffieHellman->initialised_) {
4844-
return ThrowCryptoError(env, ERR_get_error(), "Not initialized");
4845-
}
4846-
4847-
if (diffieHellman->dh->priv_key == nullptr) {
4848-
return env->ThrowError("No private key - did you forget to generate one?");
4849-
}
4850-
4851-
int dataSize = BN_num_bytes(diffieHellman->dh->priv_key);
4852-
char* data = new char[dataSize];
4853-
BN_bn2bin(diffieHellman->dh->priv_key,
4854-
reinterpret_cast<unsigned char*>(data));
4855-
4856-
args.GetReturnValue().Set(Encode(env->isolate(), data, dataSize, BUFFER));
4857-
delete[] data;
4806+
GetField(args, &DH::priv_key,
4807+
"No private key - did you forget to generate one?");
48584808
}
48594809

48604810

@@ -4882,7 +4832,7 @@ void DiffieHellman::ComputeSecret(const FunctionCallbackInfo<Value>& args) {
48824832
}
48834833

48844834
int dataSize = DH_size(diffieHellman->dh);
4885-
char* data = new char[dataSize];
4835+
char* data = Malloc(dataSize);
48864836

48874837
int size = DH_compute_key(reinterpret_cast<unsigned char*>(data),
48884838
key,
@@ -4894,7 +4844,7 @@ void DiffieHellman::ComputeSecret(const FunctionCallbackInfo<Value>& args) {
48944844

48954845
checked = DH_check_pub_key(diffieHellman->dh, key, &checkResult);
48964846
BN_free(key);
4897-
delete[] data;
4847+
free(data);
48984848

48994849
if (!checked) {
49004850
return ThrowCryptoError(env, ERR_get_error(), "Invalid Key");
@@ -4909,6 +4859,8 @@ void DiffieHellman::ComputeSecret(const FunctionCallbackInfo<Value>& args) {
49094859
} else {
49104860
return env->ThrowError("Invalid key");
49114861
}
4862+
4863+
UNREACHABLE();
49124864
}
49134865

49144866
BN_free(key);
@@ -4924,8 +4876,8 @@ void DiffieHellman::ComputeSecret(const FunctionCallbackInfo<Value>& args) {
49244876
memset(data, 0, dataSize - size);
49254877
}
49264878

4927-
args.GetReturnValue().Set(Encode(env->isolate(), data, dataSize, BUFFER));
4928-
delete[] data;
4879+
auto rc = Buffer::New(env->isolate(), data, dataSize).ToLocalChecked();
4880+
args.GetReturnValue().Set(rc);
49294881
}
49304882

49314883

src/node_crypto.h

+2
Original file line numberDiff line numberDiff line change
@@ -690,6 +690,8 @@ class DiffieHellman : public BaseObject {
690690
}
691691

692692
private:
693+
static void GetField(const v8::FunctionCallbackInfo<v8::Value>& args,
694+
BIGNUM* (DH::*field), const char* err_if_null);
693695
bool VerifyContext();
694696

695697
bool initialised_;

0 commit comments

Comments
 (0)