Skip to content

Commit 7fb786e

Browse files
committed
fixup! crypto: support OpenSSL STORE private keys
1 parent 54c8eea commit 7fb786e

3 files changed

Lines changed: 47 additions & 51 deletions

File tree

lib/internal/crypto/keys.js

Lines changed: 9 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ const {
2727
kKeyFormatRawPublic,
2828
kKeyFormatRawPrivate,
2929
kKeyFormatRawSeed,
30+
kKeyFormatStore,
3031
kKeyEncodingPKCS1,
3132
kKeyEncodingPKCS8,
3233
kKeyEncodingSPKI,
@@ -100,17 +101,6 @@ const maybeEmitDEP0204 = getDeprecationWarningEmitter(
100101
(key) => !getCryptoKeyExtractable(key),
101102
);
102103

103-
function getStoreURLString(url, property, name) {
104-
const value = url[property];
105-
if (typeof value !== 'string') {
106-
throw new ERR_INVALID_ARG_VALUE(
107-
name,
108-
url,
109-
`must have a string ${property}`);
110-
}
111-
return value;
112-
}
113-
114104
// Key input contexts.
115105
const kConsumePublic = 0;
116106
const kConsumePrivate = 1;
@@ -566,13 +556,14 @@ function getKeyTypes(allowKeyObject, bufferOnly = false) {
566556
return types;
567557
}
568558

569-
function validateStoreURL(url, name) {
570-
return getStoreURLString(url, 'href', name);
571-
}
572-
573559
function prepareStorePrivateKey(url, options, name, optionsName = name) {
574560
let passphrase;
575561
let encoding;
562+
const href = url.href;
563+
564+
if (typeof href !== 'string') {
565+
throw new ERR_INVALID_ARG_VALUE(name, url, 'must have a string href');
566+
}
576567

577568
if (options !== undefined) {
578569
({ passphrase, encoding } = options);
@@ -592,7 +583,8 @@ function prepareStorePrivateKey(url, options, name, optionsName = name) {
592583
}
593584

594585
return {
595-
storeURL: validateStoreURL(url, name),
586+
data: href,
587+
format: kKeyFormatStore,
596588
passphrase,
597589
};
598590
}
@@ -914,15 +906,9 @@ function toPublicCryptoKey(key, keyUsages) {
914906
}
915907

916908
function createPrivateKey(key) {
917-
const { format, type, data, passphrase, namedCurve, storeURL } =
909+
const { format, type, data, passphrase, namedCurve } =
918910
prepareAsymmetricKey(key, kCreatePrivate);
919911
const handle = new KeyObjectHandle();
920-
if (storeURL !== undefined) {
921-
handle.initPrivateKeyFromStore(
922-
storeURL,
923-
passphrase ?? null);
924-
return new PrivateKeyObject(handle);
925-
}
926912
handle.init(kKeyTypePrivate, data, format ?? null,
927913
type ?? null, passphrase ?? null, namedCurve ?? null);
928914
return new PrivateKeyObject(handle);

src/crypto/crypto_keys.cc

Lines changed: 38 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ using v8::Value;
5757

5858
namespace crypto {
5959
namespace {
60+
constexpr int kKeyFormatStore = -1;
61+
6062
Maybe<EVPKeyPointer::AsymmetricKeyEncodingConfig> GetKeyFormatAndTypeFromJs(
6163
const FunctionCallbackInfo<Value>& args,
6264
unsigned int* offset,
@@ -1129,8 +1131,6 @@ Local<Function> KeyObjectHandle::Initialize(Environment* env) {
11291131
KeyObjectHandle::kInternalFieldCount);
11301132

11311133
SetProtoMethod(isolate, templ, "init", Init);
1132-
SetProtoMethod(
1133-
isolate, templ, "initPrivateKeyFromStore", InitPrivateKeyFromStore);
11341134
SetProtoMethodNoSideEffect(isolate, templ, "getKeyType", GetKeyType);
11351135
SetProtoMethodNoSideEffect(isolate, templ, "isStoreBacked", IsStoreBacked);
11361136
SetProtoMethodNoSideEffect(
@@ -1160,7 +1160,6 @@ void KeyObjectHandle::RegisterExternalReferences(
11601160
ExternalReferenceRegistry* registry) {
11611161
registry->Register(New);
11621162
registry->Register(Init);
1163-
registry->Register(InitPrivateKeyFromStore);
11641163
registry->Register(GetKeyType);
11651164
registry->Register(IsStoreBacked);
11661165
registry->Register(GetSymmetricKeySize);
@@ -1208,6 +1207,10 @@ KeyObjectHandle::KeyObjectHandle(Environment* env,
12081207
MakeWeak();
12091208
}
12101209

1210+
static KeyObjectData LoadPrivateKeyFromStore(Environment* env,
1211+
Local<Value> uri_arg,
1212+
Local<Value> passphrase_arg);
1213+
12111214
void KeyObjectHandle::Init(const FunctionCallbackInfo<Value>& args) {
12121215
KeyObjectHandle* key;
12131216
ASSIGN_OR_RETURN_UNWRAP(&key, args.This());
@@ -1243,8 +1246,18 @@ void KeyObjectHandle::Init(const FunctionCallbackInfo<Value>& args) {
12431246
// args: [keyType, buffer/object, formatInt, typeString/null,
12441247
// passphrase/null, namedCurve/null]
12451248
if (args[2]->IsInt32()) {
1246-
auto format = static_cast<EVPKeyPointer::PKFormatType>(
1247-
args[2].As<Int32>()->Value());
1249+
int format_int = args[2].As<Int32>()->Value();
1250+
if (format_int == kKeyFormatStore) {
1251+
if (type != kKeyTypePrivate) {
1252+
THROW_ERR_INVALID_ARG_VALUE(
1253+
env, "OpenSSL STORE can only be used for private keys");
1254+
return;
1255+
}
1256+
key->data_ = LoadPrivateKeyFromStore(env, args[1], args[4]);
1257+
return;
1258+
}
1259+
auto format =
1260+
static_cast<EVPKeyPointer::PKFormatType>(format_int);
12481261
if (format == EVPKeyPointer::PKFormatType::RAW_PUBLIC ||
12491262
format == EVPKeyPointer::PKFormatType::RAW_PRIVATE ||
12501263
format == EVPKeyPointer::PKFormatType::RAW_SEED) {
@@ -1293,24 +1306,22 @@ void KeyObjectHandle::Init(const FunctionCallbackInfo<Value>& args) {
12931306
}
12941307
}
12951308

1296-
void KeyObjectHandle::InitPrivateKeyFromStore(
1297-
const FunctionCallbackInfo<Value>& args) {
1298-
Environment* env = Environment::GetCurrent(args);
1299-
CHECK_EQ(args.Length(), 2);
1300-
CHECK(args[0]->IsString());
1301-
CHECK(args[1]->IsNull() || IsAnyBufferSource(args[1]));
1309+
static KeyObjectData LoadPrivateKeyFromStore(Environment* env,
1310+
Local<Value> uri_arg,
1311+
Local<Value> passphrase_arg) {
1312+
CHECK(uri_arg->IsString());
1313+
CHECK(passphrase_arg->IsNull() || IsAnyBufferSource(passphrase_arg));
13021314

1303-
Utf8Value uri_value(env->isolate(), args[0]);
1315+
Utf8Value uri_value(env->isolate(), uri_arg);
13041316
std::string_view uri(*uri_value, uri_value.length());
13051317
THROW_IF_INSUFFICIENT_PERMISSIONS(
1306-
env, permission::PermissionScope::kCryptoStore, uri);
1318+
env, permission::PermissionScope::kCryptoStore, uri, {});
13071319

13081320
#if OPENSSL_VERSION_MAJOR < 3 || defined(OPENSSL_IS_BORINGSSL)
13091321
THROW_ERR_CRYPTO_OPERATION_FAILED(
13101322
env, "OpenSSL STORE providers are not supported by this OpenSSL build");
1323+
return {};
13111324
#else
1312-
KeyObjectHandle* key;
1313-
ASSIGN_OR_RETURN_UNWRAP(&key, args.This());
13141325
MarkPopErrorOnReturn mark_pop_error_on_return;
13151326

13161327
std::string store_propq;
@@ -1321,26 +1332,26 @@ void KeyObjectHandle::InitPrivateKeyFromStore(
13211332
THROW_ERR_INVALID_ARG_VALUE(
13221333
env,
13231334
"The \"url\" argument must identify an OpenSSL STORE provider URL");
1324-
return;
1335+
return {};
13251336
case StoreProviderStatus::NotFound:
13261337
ThrowCryptoError(env,
13271338
mark_pop_error_on_return.peekError(),
13281339
"Failed to open OpenSSL STORE");
1329-
return;
1340+
return {};
13301341
}
13311342

13321343
ByteSource passphrase;
1333-
bool has_passphrase = !args[1]->IsNull();
1344+
bool has_passphrase = !passphrase_arg->IsNull();
13341345
if (has_passphrase) {
1335-
passphrase = ByteSource::FromStringOrBuffer(env, args[1]);
1346+
passphrase = ByteSource::FromStringOrBuffer(env, passphrase_arg);
13361347
}
13371348
const ByteSource* passphrase_ptr = has_passphrase ? &passphrase : nullptr;
13381349
UIMethodPointer ui_method(UI_UTIL_wrap_read_pem_callback(
13391350
has_passphrase ? PasswordCallback : NoPasswordCallback, 0));
13401351
if (!ui_method) {
13411352
THROW_ERR_CRYPTO_OPERATION_FAILED(
13421353
env, "Unable to initialize OpenSSL STORE password callback");
1343-
return;
1354+
return {};
13441355
}
13451356

13461357
void* ui_data = has_passphrase ? &passphrase_ptr : nullptr;
@@ -1357,14 +1368,14 @@ void KeyObjectHandle::InitPrivateKeyFromStore(
13571368
ThrowCryptoError(env,
13581369
mark_pop_error_on_return.peekError(),
13591370
"Failed to open OpenSSL STORE");
1360-
return;
1371+
return {};
13611372
}
13621373

13631374
if (OSSL_STORE_expect(store.get(), OSSL_STORE_INFO_PKEY) != 1) {
13641375
ThrowCryptoError(env,
13651376
mark_pop_error_on_return.peekError(),
13661377
"Failed to set OpenSSL STORE expectation");
1367-
return;
1378+
return {};
13681379
}
13691380

13701381
while (OSSL_STORE_eof(store.get()) != 1) {
@@ -1374,7 +1385,7 @@ void KeyObjectHandle::InitPrivateKeyFromStore(
13741385
ThrowCryptoError(env,
13751386
mark_pop_error_on_return.peekError(),
13761387
"Failed to load key from OpenSSL STORE");
1377-
return;
1388+
return {};
13781389
}
13791390
break;
13801391
}
@@ -1388,16 +1399,16 @@ void KeyObjectHandle::InitPrivateKeyFromStore(
13881399
ThrowCryptoError(env,
13891400
mark_pop_error_on_return.peekError(),
13901401
"Failed to extract key from OpenSSL STORE");
1391-
return;
1402+
return {};
13921403
}
13931404

1394-
key->data_ = KeyObjectData::CreateAsymmetric(
1405+
return KeyObjectData::CreateAsymmetric(
13951406
kKeyTypePrivate, EVPKeyPointer(pkey), true);
1396-
return;
13971407
}
13981408

13991409
THROW_ERR_CRYPTO_OPERATION_FAILED(
14001410
env, "OpenSSL STORE did not return a private key");
1411+
return {};
14011412
#endif
14021413
}
14031414

@@ -2324,6 +2335,7 @@ void Initialize(Environment* env, Local<Object> target) {
23242335
NODE_DEFINE_CONSTANT(target, kKeyFormatRawPublic);
23252336
NODE_DEFINE_CONSTANT(target, kKeyFormatRawPrivate);
23262337
NODE_DEFINE_CONSTANT(target, kKeyFormatRawSeed);
2338+
NODE_DEFINE_CONSTANT(target, kKeyFormatStore);
23272339
NODE_DEFINE_CONSTANT(target, kKeyTypeSecret);
23282340
NODE_DEFINE_CONSTANT(target, kKeyTypePublic);
23292341
NODE_DEFINE_CONSTANT(target, kKeyTypePrivate);

src/crypto/crypto_keys.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,8 +159,6 @@ class KeyObjectHandle : public BaseObject {
159159
static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
160160

161161
static void Init(const v8::FunctionCallbackInfo<v8::Value>& args);
162-
static void InitPrivateKeyFromStore(
163-
const v8::FunctionCallbackInfo<v8::Value>& args);
164162
static void GetKeyType(const v8::FunctionCallbackInfo<v8::Value>& args);
165163
static void IsStoreBacked(const v8::FunctionCallbackInfo<v8::Value>& args);
166164
static void GetKeyDetail(const v8::FunctionCallbackInfo<v8::Value>& args);

0 commit comments

Comments
 (0)