Skip to content

Commit 9110ab3

Browse files
committed
crypto: fix malloc mixing in X509ToObject
EC_KEY_key2buf returns an OPENSSL_malloc'd pointer so it shouldn't be passed into Buffer::New, which expect a libc malloc'd pointer. Instead, factor out the ECDH::GetPublicKey code which uses EC_POINT_point2oct. This preserves the existing behavior where encoding failures are silently ignored, but it is probably safe to CHECK fail them instead.
1 parent f40778e commit 9110ab3

File tree

1 file changed

+30
-42
lines changed

1 file changed

+30
-42
lines changed

src/node_crypto.cc

Lines changed: 30 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1628,6 +1628,24 @@ static void AddFingerprintDigest(const unsigned char* md,
16281628
}
16291629
}
16301630

1631+
static MaybeLocal<Object> ECPointToBuffer(Environment* env,
1632+
const EC_GROUP* group,
1633+
const EC_POINT* point,
1634+
point_conversion_form_t form) {
1635+
size_t len = EC_POINT_point2oct(group, point, form, nullptr, 0, nullptr);
1636+
if (len == 0) {
1637+
env->ThrowError("Failed to get public key length");
1638+
return MaybeLocal<Object>();
1639+
}
1640+
MallocedBuffer<unsigned char> buf(len);
1641+
len = EC_POINT_point2oct(group, point, form, buf.data, buf.size, nullptr);
1642+
if (len == 0) {
1643+
env->ThrowError("Failed to get public key");
1644+
return MaybeLocal<Object>();
1645+
}
1646+
return Buffer::New(env, buf.release(), len);
1647+
}
1648+
16311649
static Local<Object> X509ToObject(Environment* env, X509* cert) {
16321650
EscapableHandleScope scope(env->isolate());
16331651
Local<Context> context = env->context();
@@ -1744,16 +1762,12 @@ static Local<Object> X509ToObject(Environment* env, X509* cert) {
17441762
}
17451763
}
17461764

1747-
unsigned char* pub = nullptr;
1748-
size_t publen = EC_KEY_key2buf(ec.get(), EC_KEY_get_conv_form(ec.get()),
1749-
&pub, nullptr);
1750-
if (publen > 0) {
1751-
Local<Object> buf = Buffer::New(env, pub, publen).ToLocalChecked();
1752-
// Ownership of pub pointer accepted by Buffer.
1753-
pub = nullptr;
1765+
const EC_POINT* pubkey = EC_KEY_get0_public_key(ec.get());
1766+
if (pubkey != nullptr) {
1767+
Local<Object> buf =
1768+
ECPointToBuffer(env, group, pubkey, EC_KEY_get_conv_form(ec.get()))
1769+
.ToLocalChecked();
17541770
info->Set(context, env->pubkey_string(), buf).FromJust();
1755-
} else {
1756-
CHECK_NULL(pub);
17571771
}
17581772

17591773
const int nid = EC_GROUP_get_curve_name(group);
@@ -5256,26 +5270,14 @@ void ECDH::GetPublicKey(const FunctionCallbackInfo<Value>& args) {
52565270
if (pub == nullptr)
52575271
return env->ThrowError("Failed to get ECDH public key");
52585272

5259-
int size;
52605273
CHECK(args[0]->IsUint32());
52615274
uint32_t val = args[0].As<Uint32>()->Value();
52625275
point_conversion_form_t form = static_cast<point_conversion_form_t>(val);
52635276

5264-
size = EC_POINT_point2oct(ecdh->group_, pub, form, nullptr, 0, nullptr);
5265-
if (size == 0)
5266-
return env->ThrowError("Failed to get public key length");
5267-
5268-
unsigned char* out = node::Malloc<unsigned char>(size);
5269-
5270-
int r = EC_POINT_point2oct(ecdh->group_, pub, form, out, size, nullptr);
5271-
if (r != size) {
5272-
free(out);
5273-
return env->ThrowError("Failed to get public key");
5274-
}
5275-
5276-
Local<Object> buf =
5277-
Buffer::New(env, reinterpret_cast<char*>(out), size).ToLocalChecked();
5278-
args.GetReturnValue().Set(buf);
5277+
MaybeLocal<Object> buf =
5278+
ECPointToBuffer(env, EC_KEY_get0_group(ecdh->key_.get()), pub, form);
5279+
if (buf.IsEmpty()) return;
5280+
args.GetReturnValue().Set(buf.ToLocalChecked());
52795281
}
52805282

52815283

@@ -6165,23 +6167,9 @@ void ConvertKey(const FunctionCallbackInfo<Value>& args) {
61656167
uint32_t val = args[2].As<Uint32>()->Value();
61666168
point_conversion_form_t form = static_cast<point_conversion_form_t>(val);
61676169

6168-
int size = EC_POINT_point2oct(
6169-
group.get(), pub.get(), form, nullptr, 0, nullptr);
6170-
6171-
if (size == 0)
6172-
return env->ThrowError("Failed to get public key length");
6173-
6174-
unsigned char* out = node::Malloc<unsigned char>(size);
6175-
6176-
int r = EC_POINT_point2oct(group.get(), pub.get(), form, out, size, nullptr);
6177-
if (r != size) {
6178-
free(out);
6179-
return env->ThrowError("Failed to get public key");
6180-
}
6181-
6182-
Local<Object> buf =
6183-
Buffer::New(env, reinterpret_cast<char*>(out), size).ToLocalChecked();
6184-
args.GetReturnValue().Set(buf);
6170+
MaybeLocal<Object> buf = ECPointToBuffer(env, group.get(), pub.get(), form);
6171+
if (buf.IsEmpty()) return;
6172+
args.GetReturnValue().Set(buf.ToLocalChecked());
61856173
}
61866174

61876175

0 commit comments

Comments
 (0)