Skip to content
This repository was archived by the owner on Mar 4, 2020. It is now read-only.

Commit 6579434

Browse files
davidbenzcbenz
authored andcommitted
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. PR-URL: nodejs/node#25717 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net>
1 parent 2dc0f88 commit 6579434

1 file changed

Lines changed: 31 additions & 46 deletions

File tree

src/node_crypto.cc

Lines changed: 31 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1628,6 +1628,25 @@ 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(
1641+
len, env->isolate()->GetArrayBufferAllocator());
1642+
len = EC_POINT_point2oct(group, point, form, buf.data, buf.size, nullptr);
1643+
if (len == 0) {
1644+
env->ThrowError("Failed to get public key");
1645+
return MaybeLocal<Object>();
1646+
}
1647+
return Buffer::New(env, buf.release(), len);
1648+
}
1649+
16311650
static Local<Object> X509ToObject(Environment* env, X509* cert) {
16321651
EscapableHandleScope scope(env->isolate());
16331652
Local<Context> context = env->context();
@@ -1744,16 +1763,12 @@ static Local<Object> X509ToObject(Environment* env, X509* cert) {
17441763
}
17451764
}
17461765

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;
1766+
const EC_POINT* pubkey = EC_KEY_get0_public_key(ec.get());
1767+
if (pubkey != nullptr) {
1768+
Local<Object> buf =
1769+
ECPointToBuffer(env, group, pubkey, EC_KEY_get_conv_form(ec.get()))
1770+
.ToLocalChecked();
17541771
info->Set(context, env->pubkey_string(), buf).FromJust();
1755-
} else {
1756-
CHECK_NULL(pub);
17571772
}
17581773

17591774
const int nid = EC_GROUP_get_curve_name(group);
@@ -4548,28 +4563,14 @@ void ECDH::GetPublicKey(const FunctionCallbackInfo<Value>& args) {
45484563
if (pub == nullptr)
45494564
return env->ThrowError("Failed to get ECDH public key");
45504565

4551-
int size;
45524566
CHECK(args[0]->IsUint32());
45534567
uint32_t val = args[0].As<Uint32>()->Value();
45544568
point_conversion_form_t form = static_cast<point_conversion_form_t>(val);
45554569

4556-
size = EC_POINT_point2oct(ecdh->group_, pub, form, nullptr, 0, nullptr);
4557-
if (size == 0)
4558-
return env->ThrowError("Failed to get public key length");
4559-
4560-
auto* allocator = env->isolate()->GetArrayBufferAllocator();
4561-
unsigned char* out =
4562-
static_cast<unsigned char*>(allocator->AllocateUninitialized(size));
4563-
4564-
int r = EC_POINT_point2oct(ecdh->group_, pub, form, out, size, nullptr);
4565-
if (r != size) {
4566-
allocator->Free(out, size);
4567-
return env->ThrowError("Failed to get public key");
4568-
}
4569-
4570-
Local<Object> buf =
4571-
Buffer::New(env, reinterpret_cast<char*>(out), size).ToLocalChecked();
4572-
args.GetReturnValue().Set(buf);
4570+
MaybeLocal<Object> buf =
4571+
ECPointToBuffer(env, EC_KEY_get0_group(ecdh->key_.get()), pub, form);
4572+
if (buf.IsEmpty()) return;
4573+
args.GetReturnValue().Set(buf.ToLocalChecked());
45734574
}
45744575

45754576

@@ -5177,25 +5178,9 @@ void ConvertKey(const FunctionCallbackInfo<Value>& args) {
51775178
uint32_t val = args[2].As<Uint32>()->Value();
51785179
point_conversion_form_t form = static_cast<point_conversion_form_t>(val);
51795180

5180-
int size = EC_POINT_point2oct(
5181-
group.get(), pub.get(), form, nullptr, 0, nullptr);
5182-
5183-
if (size == 0)
5184-
return env->ThrowError("Failed to get public key length");
5185-
5186-
auto* allocator = env->isolate()->GetArrayBufferAllocator();
5187-
unsigned char* out =
5188-
static_cast<unsigned char*>(allocator->AllocateUninitialized(size));
5189-
5190-
int r = EC_POINT_point2oct(group.get(), pub.get(), form, out, size, nullptr);
5191-
if (r != size) {
5192-
allocator->Free(out, size);
5193-
return env->ThrowError("Failed to get public key");
5194-
}
5195-
5196-
Local<Object> buf =
5197-
Buffer::New(env, reinterpret_cast<char*>(out), size).ToLocalChecked();
5198-
args.GetReturnValue().Set(buf);
5181+
MaybeLocal<Object> buf = ECPointToBuffer(env, group.get(), pub.get(), form);
5182+
if (buf.IsEmpty()) return;
5183+
args.GetReturnValue().Set(buf.ToLocalChecked());
51995184
}
52005185

52015186

0 commit comments

Comments
 (0)