Skip to content

Commit 3302025

Browse files
tniessencodebytere
authored andcommitted
src: store key data in separate class
This separates key handles from the actual key data: +-----------------+ | NativeKeyObject | +-----------------+ ^ extends | +-----------------+ +-----------------+ +---------------+ | KeyObject (JS) | -> | KeyObjectHandle | -> | KeyObjectData | +-----------------+ +-----------------+ +---------------+ PR-URL: #33360 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: James M Snell <[email protected]>
1 parent 44b9d08 commit 3302025

File tree

3 files changed

+116
-105
lines changed

3 files changed

+116
-105
lines changed

lib/internal/crypto/keys.js

+6-6
Original file line numberDiff line numberDiff line change
@@ -331,23 +331,23 @@ function createSecretKey(key) {
331331
key = prepareSecretKey(key, true);
332332
if (key.byteLength === 0)
333333
throw new ERR_OUT_OF_RANGE('key.byteLength', '> 0', key.byteLength);
334-
const handle = new KeyObjectHandle(kKeyTypeSecret);
335-
handle.init(key);
334+
const handle = new KeyObjectHandle();
335+
handle.init(kKeyTypeSecret, key);
336336
return new SecretKeyObject(handle);
337337
}
338338

339339
function createPublicKey(key) {
340340
const { format, type, data } = prepareAsymmetricKey(key, kCreatePublic);
341-
const handle = new KeyObjectHandle(kKeyTypePublic);
342-
handle.init(data, format, type);
341+
const handle = new KeyObjectHandle();
342+
handle.init(kKeyTypePublic, data, format, type);
343343
return new PublicKeyObject(handle);
344344
}
345345

346346
function createPrivateKey(key) {
347347
const { format, type, data, passphrase } =
348348
prepareAsymmetricKey(key, kCreatePrivate);
349-
const handle = new KeyObjectHandle(kKeyTypePrivate);
350-
handle.init(data, format, type, passphrase);
349+
const handle = new KeyObjectHandle();
350+
handle.init(kKeyTypePrivate, data, format, type, passphrase);
351351
return new PrivateKeyObject(handle);
352352
}
353353

src/node_crypto.cc

+86-83
Original file line numberDiff line numberDiff line change
@@ -2929,7 +2929,8 @@ ByteSource ByteSource::FromSymmetricKeyObjectHandle(Local<Value> handle) {
29292929
CHECK(handle->IsObject());
29302930
KeyObjectHandle* key = Unwrap<KeyObjectHandle>(handle.As<Object>());
29312931
CHECK_NOT_NULL(key);
2932-
return Foreign(key->GetSymmetricKey(), key->GetSymmetricKeySize());
2932+
return Foreign(key->Data()->GetSymmetricKey(),
2933+
key->Data()->GetSymmetricKeySize());
29332934
}
29342935

29352936
ByteSource::ByteSource(const char* data, char* allocated_data, size_t size)
@@ -3075,9 +3076,9 @@ static ManagedEVPPKey GetPrivateKeyFromJs(
30753076
CHECK(args[*offset]->IsObject() && allow_key_object);
30763077
KeyObjectHandle* key;
30773078
ASSIGN_OR_RETURN_UNWRAP(&key, args[*offset].As<Object>(), ManagedEVPPKey());
3078-
CHECK_EQ(key->GetKeyType(), kKeyTypePrivate);
3079+
CHECK_EQ(key->Data()->GetKeyType(), kKeyTypePrivate);
30793080
(*offset) += 4;
3080-
return key->GetAsymmetricKey();
3081+
return key->Data()->GetAsymmetricKey();
30813082
}
30823083
}
30833084

@@ -3135,9 +3136,9 @@ static ManagedEVPPKey GetPublicOrPrivateKeyFromJs(
31353136
CHECK(args[*offset]->IsObject());
31363137
KeyObjectHandle* key = Unwrap<KeyObjectHandle>(args[*offset].As<Object>());
31373138
CHECK_NOT_NULL(key);
3138-
CHECK_NE(key->GetKeyType(), kKeyTypeSecret);
3139+
CHECK_NE(key->Data()->GetKeyType(), kKeyTypeSecret);
31393140
(*offset) += 4;
3140-
return key->GetAsymmetricKey();
3141+
return key->Data()->GetAsymmetricKey();
31413142
}
31423143
}
31433144

@@ -3243,6 +3244,48 @@ EVP_PKEY* ManagedEVPPKey::get() const {
32433244
return pkey_.get();
32443245
}
32453246

3247+
KeyObjectData* KeyObjectData::CreateSecret(v8::Local<v8::ArrayBufferView> abv) {
3248+
size_t key_len = abv->ByteLength();
3249+
char* mem = MallocOpenSSL<char>(key_len);
3250+
abv->CopyContents(mem, key_len);
3251+
KeyObjectData* data = new KeyObjectData();
3252+
data->key_type_ = kKeyTypeSecret;
3253+
data->symmetric_key_ = std::unique_ptr<char, std::function<void(char*)>>(mem,
3254+
[key_len](char* p) {
3255+
OPENSSL_clear_free(p, key_len);
3256+
});
3257+
data->symmetric_key_len_ = key_len;
3258+
return data;
3259+
}
3260+
3261+
KeyObjectData* KeyObjectData::CreateAsymmetric(KeyType key_type,
3262+
const ManagedEVPPKey& pkey) {
3263+
CHECK(pkey);
3264+
KeyObjectData* data = new KeyObjectData();
3265+
data->key_type_ = key_type;
3266+
data->asymmetric_key_ = pkey;
3267+
return data;
3268+
}
3269+
3270+
KeyType KeyObjectData::GetKeyType() const {
3271+
return key_type_;
3272+
}
3273+
3274+
ManagedEVPPKey KeyObjectData::GetAsymmetricKey() const {
3275+
CHECK_NE(key_type_, kKeyTypeSecret);
3276+
return asymmetric_key_;
3277+
}
3278+
3279+
const char* KeyObjectData::GetSymmetricKey() const {
3280+
CHECK_EQ(key_type_, kKeyTypeSecret);
3281+
return symmetric_key_.get();
3282+
}
3283+
3284+
size_t KeyObjectData::GetSymmetricKeySize() const {
3285+
CHECK_EQ(key_type_, kKeyTypeSecret);
3286+
return symmetric_key_len_;
3287+
}
3288+
32463289
Local<Function> KeyObjectHandle::Initialize(Environment* env,
32473290
Local<Object> target) {
32483291
Local<FunctionTemplate> t = env->NewFunctionTemplate(New);
@@ -3279,46 +3322,23 @@ MaybeLocal<Object> KeyObjectHandle::Create(Environment* env,
32793322

32803323
KeyObjectHandle* key = Unwrap<KeyObjectHandle>(obj);
32813324
CHECK_NOT_NULL(key);
3282-
if (key_type == kKeyTypePublic)
3283-
key->InitPublic(pkey);
3284-
else
3285-
key->InitPrivate(pkey);
3325+
key->data_.reset(KeyObjectData::CreateAsymmetric(key_type, pkey));
32863326
return obj;
32873327
}
32883328

3289-
ManagedEVPPKey KeyObjectHandle::GetAsymmetricKey() const {
3290-
CHECK_NE(key_type_, kKeyTypeSecret);
3291-
return this->asymmetric_key_;
3292-
}
3293-
3294-
const char* KeyObjectHandle::GetSymmetricKey() const {
3295-
CHECK_EQ(key_type_, kKeyTypeSecret);
3296-
return this->symmetric_key_.get();
3297-
}
3298-
3299-
size_t KeyObjectHandle::GetSymmetricKeySize() const {
3300-
CHECK_EQ(key_type_, kKeyTypeSecret);
3301-
return this->symmetric_key_len_;
3329+
const KeyObjectData* KeyObjectHandle::Data() {
3330+
return data_.get();
33023331
}
33033332

33043333
void KeyObjectHandle::New(const FunctionCallbackInfo<Value>& args) {
33053334
CHECK(args.IsConstructCall());
3306-
CHECK(args[0]->IsInt32());
3307-
KeyType key_type = static_cast<KeyType>(args[0].As<Uint32>()->Value());
33083335
Environment* env = Environment::GetCurrent(args);
3309-
new KeyObjectHandle(env, args.This(), key_type);
3310-
}
3311-
3312-
KeyType KeyObjectHandle::GetKeyType() const {
3313-
return this->key_type_;
3336+
new KeyObjectHandle(env, args.This());
33143337
}
33153338

33163339
KeyObjectHandle::KeyObjectHandle(Environment* env,
3317-
Local<Object> wrap,
3318-
KeyType key_type)
3319-
: BaseObject(env, wrap),
3320-
key_type_(key_type),
3321-
symmetric_key_(nullptr, nullptr) {
3340+
Local<Object> wrap)
3341+
: BaseObject(env, wrap) {
33223342
MakeWeak();
33233343
}
33243344

@@ -3327,66 +3347,45 @@ void KeyObjectHandle::Init(const FunctionCallbackInfo<Value>& args) {
33273347
ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
33283348
MarkPopErrorOnReturn mark_pop_error_on_return;
33293349

3350+
CHECK(args[0]->IsInt32());
3351+
KeyType type = static_cast<KeyType>(args[0].As<Uint32>()->Value());
3352+
33303353
unsigned int offset;
33313354
ManagedEVPPKey pkey;
33323355

3333-
switch (key->key_type_) {
3356+
switch (type) {
33343357
case kKeyTypeSecret:
3335-
CHECK_EQ(args.Length(), 1);
3336-
CHECK(args[0]->IsArrayBufferView());
3337-
key->InitSecret(args[0].As<ArrayBufferView>());
3358+
CHECK_EQ(args.Length(), 2);
3359+
CHECK(args[1]->IsArrayBufferView());
3360+
key->data_.reset(
3361+
KeyObjectData::CreateSecret(args[1].As<ArrayBufferView>()));
33383362
break;
33393363
case kKeyTypePublic:
3340-
CHECK_EQ(args.Length(), 3);
3364+
CHECK_EQ(args.Length(), 4);
33413365

3342-
offset = 0;
3366+
offset = 1;
33433367
pkey = GetPublicOrPrivateKeyFromJs(args, &offset);
33443368
if (!pkey)
33453369
return;
3346-
key->InitPublic(pkey);
3370+
key->data_.reset(KeyObjectData::CreateAsymmetric(type, pkey));
33473371
break;
33483372
case kKeyTypePrivate:
3349-
CHECK_EQ(args.Length(), 4);
3373+
CHECK_EQ(args.Length(), 5);
33503374

3351-
offset = 0;
3375+
offset = 1;
33523376
pkey = GetPrivateKeyFromJs(args, &offset, false);
33533377
if (!pkey)
33543378
return;
3355-
key->InitPrivate(pkey);
3379+
key->data_.reset(KeyObjectData::CreateAsymmetric(type, pkey));
33563380
break;
33573381
default:
33583382
CHECK(false);
33593383
}
33603384
}
33613385

3362-
void KeyObjectHandle::InitSecret(Local<ArrayBufferView> abv) {
3363-
CHECK_EQ(this->key_type_, kKeyTypeSecret);
3364-
3365-
size_t key_len = abv->ByteLength();
3366-
char* mem = MallocOpenSSL<char>(key_len);
3367-
abv->CopyContents(mem, key_len);
3368-
this->symmetric_key_ = std::unique_ptr<char, std::function<void(char*)>>(mem,
3369-
[key_len](char* p) {
3370-
OPENSSL_clear_free(p, key_len);
3371-
});
3372-
this->symmetric_key_len_ = key_len;
3373-
}
3374-
3375-
void KeyObjectHandle::InitPublic(const ManagedEVPPKey& pkey) {
3376-
CHECK_EQ(this->key_type_, kKeyTypePublic);
3377-
CHECK(pkey);
3378-
this->asymmetric_key_ = pkey;
3379-
}
3380-
3381-
void KeyObjectHandle::InitPrivate(const ManagedEVPPKey& pkey) {
3382-
CHECK_EQ(this->key_type_, kKeyTypePrivate);
3383-
CHECK(pkey);
3384-
this->asymmetric_key_ = pkey;
3385-
}
3386-
33873386
Local<Value> KeyObjectHandle::GetAsymmetricKeyType() const {
3388-
CHECK_NE(this->key_type_, kKeyTypeSecret);
3389-
switch (EVP_PKEY_id(this->asymmetric_key_.get())) {
3387+
const ManagedEVPPKey& key = data_->GetAsymmetricKey();
3388+
switch (EVP_PKEY_id(key.get())) {
33903389
case EVP_PKEY_RSA:
33913390
return env()->crypto_rsa_string();
33923391
case EVP_PKEY_RSA_PSS:
@@ -3422,24 +3421,27 @@ void KeyObjectHandle::GetSymmetricKeySize(
34223421
const FunctionCallbackInfo<Value>& args) {
34233422
KeyObjectHandle* key;
34243423
ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
3425-
args.GetReturnValue().Set(static_cast<uint32_t>(key->GetSymmetricKeySize()));
3424+
args.GetReturnValue().Set(
3425+
static_cast<uint32_t>(key->Data()->GetSymmetricKeySize()));
34263426
}
34273427

34283428
void KeyObjectHandle::Export(const FunctionCallbackInfo<Value>& args) {
34293429
KeyObjectHandle* key;
34303430
ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
34313431

3432+
KeyType type = key->Data()->GetKeyType();
3433+
34323434
MaybeLocal<Value> result;
3433-
if (key->key_type_ == kKeyTypeSecret) {
3435+
if (type == kKeyTypeSecret) {
34343436
result = key->ExportSecretKey();
3435-
} else if (key->key_type_ == kKeyTypePublic) {
3437+
} else if (type == kKeyTypePublic) {
34363438
unsigned int offset = 0;
34373439
PublicKeyEncodingConfig config =
34383440
GetPublicKeyEncodingFromJs(args, &offset, kKeyContextExport);
34393441
CHECK_EQ(offset, static_cast<unsigned int>(args.Length()));
34403442
result = key->ExportPublicKey(config);
34413443
} else {
3442-
CHECK_EQ(key->key_type_, kKeyTypePrivate);
3444+
CHECK_EQ(type, kKeyTypePrivate);
34433445
unsigned int offset = 0;
34443446
NonCopyableMaybe<PrivateKeyEncodingConfig> config =
34453447
GetPrivateKeyEncodingFromJs(args, &offset, kKeyContextExport);
@@ -3454,18 +3456,19 @@ void KeyObjectHandle::Export(const FunctionCallbackInfo<Value>& args) {
34543456
}
34553457

34563458
Local<Value> KeyObjectHandle::ExportSecretKey() const {
3457-
return Buffer::Copy(env(), symmetric_key_.get(), symmetric_key_len_)
3458-
.ToLocalChecked();
3459+
const char* buf = data_->GetSymmetricKey();
3460+
unsigned int len = data_->GetSymmetricKeySize();
3461+
return Buffer::Copy(env(), buf, len).ToLocalChecked();
34593462
}
34603463

34613464
MaybeLocal<Value> KeyObjectHandle::ExportPublicKey(
34623465
const PublicKeyEncodingConfig& config) const {
3463-
return WritePublicKey(env(), asymmetric_key_.get(), config);
3466+
return WritePublicKey(env(), data_->GetAsymmetricKey().get(), config);
34643467
}
34653468

34663469
MaybeLocal<Value> KeyObjectHandle::ExportPrivateKey(
34673470
const PrivateKeyEncodingConfig& config) const {
3468-
return WritePrivateKey(env(), asymmetric_key_.get(), config);
3471+
return WritePrivateKey(env(), data_->GetAsymmetricKey().get(), config);
34693472
}
34703473

34713474
void NativeKeyObject::New(const FunctionCallbackInfo<Value>& args) {
@@ -6762,13 +6765,13 @@ void StatelessDiffieHellman(const FunctionCallbackInfo<Value>& args) {
67626765
CHECK(args[0]->IsObject() && args[1]->IsObject());
67636766
KeyObjectHandle* our_key_object;
67646767
ASSIGN_OR_RETURN_UNWRAP(&our_key_object, args[0].As<Object>());
6765-
CHECK_EQ(our_key_object->GetKeyType(), kKeyTypePrivate);
6768+
CHECK_EQ(our_key_object->Data()->GetKeyType(), kKeyTypePrivate);
67666769
KeyObjectHandle* their_key_object;
67676770
ASSIGN_OR_RETURN_UNWRAP(&their_key_object, args[1].As<Object>());
6768-
CHECK_NE(their_key_object->GetKeyType(), kKeyTypeSecret);
6771+
CHECK_NE(their_key_object->Data()->GetKeyType(), kKeyTypeSecret);
67696772

6770-
ManagedEVPPKey our_key = our_key_object->GetAsymmetricKey();
6771-
ManagedEVPPKey their_key = their_key_object->GetAsymmetricKey();
6773+
ManagedEVPPKey our_key = our_key_object->Data()->GetAsymmetricKey();
6774+
ManagedEVPPKey their_key = their_key_object->Data()->GetAsymmetricKey();
67726775

67736776
AllocatedBuffer out = StatelessDiffieHellman(env, our_key, their_key);
67746777
if (out.size() == 0)

src/node_crypto.h

+24-16
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,27 @@ class ManagedEVPPKey {
408408
EVPKeyPointer pkey_;
409409
};
410410

411+
class KeyObjectData {
412+
public:
413+
static KeyObjectData* CreateSecret(v8::Local<v8::ArrayBufferView> abv);
414+
static KeyObjectData* CreateAsymmetric(KeyType type,
415+
const ManagedEVPPKey& pkey);
416+
417+
KeyType GetKeyType() const;
418+
419+
// These functions allow unprotected access to the raw key material and should
420+
// only be used to implement cryptograohic operations requiring the key.
421+
ManagedEVPPKey GetAsymmetricKey() const;
422+
const char* GetSymmetricKey() const;
423+
size_t GetSymmetricKeySize() const;
424+
425+
private:
426+
KeyType key_type_;
427+
std::unique_ptr<char, std::function<void(char*)>> symmetric_key_;
428+
unsigned int symmetric_key_len_;
429+
ManagedEVPPKey asymmetric_key_;
430+
};
431+
411432
class KeyObjectHandle : public BaseObject {
412433
public:
413434
static v8::Local<v8::Function> Initialize(Environment* env,
@@ -422,21 +443,12 @@ class KeyObjectHandle : public BaseObject {
422443
SET_MEMORY_INFO_NAME(KeyObjectHandle)
423444
SET_SELF_SIZE(KeyObjectHandle)
424445

425-
KeyType GetKeyType() const;
426-
427-
// These functions allow unprotected access to the raw key material and should
428-
// only be used to implement cryptograohic operations requiring the key.
429-
ManagedEVPPKey GetAsymmetricKey() const;
430-
const char* GetSymmetricKey() const;
431-
size_t GetSymmetricKeySize() const;
446+
const KeyObjectData* Data();
432447

433448
protected:
434449
static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
435450

436451
static void Init(const v8::FunctionCallbackInfo<v8::Value>& args);
437-
void InitSecret(v8::Local<v8::ArrayBufferView> abv);
438-
void InitPublic(const ManagedEVPPKey& pkey);
439-
void InitPrivate(const ManagedEVPPKey& pkey);
440452

441453
static void GetAsymmetricKeyType(
442454
const v8::FunctionCallbackInfo<v8::Value>& args);
@@ -453,14 +465,10 @@ class KeyObjectHandle : public BaseObject {
453465
const PrivateKeyEncodingConfig& config) const;
454466

455467
KeyObjectHandle(Environment* env,
456-
v8::Local<v8::Object> wrap,
457-
KeyType key_type);
468+
v8::Local<v8::Object> wrap);
458469

459470
private:
460-
const KeyType key_type_;
461-
std::unique_ptr<char, std::function<void(char*)>> symmetric_key_;
462-
unsigned int symmetric_key_len_;
463-
ManagedEVPPKey asymmetric_key_;
471+
std::unique_ptr<KeyObjectData> data_;
464472
};
465473

466474
class NativeKeyObject : public BaseObject {

0 commit comments

Comments
 (0)