crypto: always accept certificates as public keys
PR-URL: https://github.com/nodejs/node/pull/24234 Reviewed-By: Refael Ackermann <refack@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
parent
823d86c47c
commit
8f300bc8a7
@ -1831,6 +1831,8 @@ Creates and returns a new key object containing a public key. If `key` is a
|
|||||||
string or `Buffer`, `format` is assumed to be `'pem'`; otherwise, `key`
|
string or `Buffer`, `format` is assumed to be `'pem'`; otherwise, `key`
|
||||||
must be an object with the properties described above.
|
must be an object with the properties described above.
|
||||||
|
|
||||||
|
If the format is `'pem'`, the `'key'` may also be an X.509 certificate.
|
||||||
|
|
||||||
### crypto.createSecretKey(key)
|
### crypto.createSecretKey(key)
|
||||||
<!-- YAML
|
<!-- YAML
|
||||||
added: REPLACEME
|
added: REPLACEME
|
||||||
|
@ -2737,8 +2737,7 @@ static ParsePublicKeyResult TryParsePublicKey(
|
|||||||
|
|
||||||
static ParsePublicKeyResult ParsePublicKeyPEM(EVPKeyPointer* pkey,
|
static ParsePublicKeyResult ParsePublicKeyPEM(EVPKeyPointer* pkey,
|
||||||
const char* key_pem,
|
const char* key_pem,
|
||||||
int key_pem_len,
|
int key_pem_len) {
|
||||||
bool allow_certificate) {
|
|
||||||
BIOPointer bp(BIO_new_mem_buf(const_cast<char*>(key_pem), key_pem_len));
|
BIOPointer bp(BIO_new_mem_buf(const_cast<char*>(key_pem), key_pem_len));
|
||||||
if (!bp)
|
if (!bp)
|
||||||
return ParsePublicKeyResult::kParsePublicFailed;
|
return ParsePublicKeyResult::kParsePublicFailed;
|
||||||
@ -2759,8 +2758,7 @@ static ParsePublicKeyResult ParsePublicKeyPEM(EVPKeyPointer* pkey,
|
|||||||
[](const unsigned char** p, long l) { // NOLINT(runtime/int)
|
[](const unsigned char** p, long l) { // NOLINT(runtime/int)
|
||||||
return d2i_PublicKey(EVP_PKEY_RSA, nullptr, p, l);
|
return d2i_PublicKey(EVP_PKEY_RSA, nullptr, p, l);
|
||||||
});
|
});
|
||||||
if (ret != ParsePublicKeyResult::kParsePublicNotRecognized ||
|
if (ret != ParsePublicKeyResult::kParsePublicNotRecognized)
|
||||||
!allow_certificate)
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
// X.509 fallback.
|
// X.509 fallback.
|
||||||
@ -2775,11 +2773,10 @@ static ParsePublicKeyResult ParsePublicKeyPEM(EVPKeyPointer* pkey,
|
|||||||
static bool ParsePublicKey(EVPKeyPointer* pkey,
|
static bool ParsePublicKey(EVPKeyPointer* pkey,
|
||||||
const PublicKeyEncodingConfig& config,
|
const PublicKeyEncodingConfig& config,
|
||||||
const char* key,
|
const char* key,
|
||||||
size_t key_len,
|
size_t key_len) {
|
||||||
bool allow_certificate) {
|
|
||||||
if (config.format_ == kKeyFormatPEM) {
|
if (config.format_ == kKeyFormatPEM) {
|
||||||
ParsePublicKeyResult r =
|
ParsePublicKeyResult r =
|
||||||
ParsePublicKeyPEM(pkey, key, key_len, allow_certificate);
|
ParsePublicKeyPEM(pkey, key, key_len);
|
||||||
return r == ParsePublicKeyResult::kParsePublicOk;
|
return r == ParsePublicKeyResult::kParsePublicOk;
|
||||||
} else {
|
} else {
|
||||||
CHECK_EQ(config.format_, kKeyFormatDER);
|
CHECK_EQ(config.format_, kKeyFormatDER);
|
||||||
@ -3029,15 +3026,14 @@ static PublicKeyEncodingConfig GetPublicKeyEncodingFromJs(
|
|||||||
static ManagedEVPPKey GetPublicKeyFromJs(
|
static ManagedEVPPKey GetPublicKeyFromJs(
|
||||||
const FunctionCallbackInfo<Value>& args,
|
const FunctionCallbackInfo<Value>& args,
|
||||||
unsigned int* offset,
|
unsigned int* offset,
|
||||||
bool allow_key_object,
|
bool allow_key_object) {
|
||||||
bool allow_certificate) {
|
|
||||||
if (args[*offset]->IsString() || Buffer::HasInstance(args[*offset])) {
|
if (args[*offset]->IsString() || Buffer::HasInstance(args[*offset])) {
|
||||||
Environment* env = Environment::GetCurrent(args);
|
Environment* env = Environment::GetCurrent(args);
|
||||||
ByteSource key = ByteSource::FromStringOrBuffer(env, args[(*offset)++]);
|
ByteSource key = ByteSource::FromStringOrBuffer(env, args[(*offset)++]);
|
||||||
PublicKeyEncodingConfig config =
|
PublicKeyEncodingConfig config =
|
||||||
GetPublicKeyEncodingFromJs(args, offset, kKeyContextInput);
|
GetPublicKeyEncodingFromJs(args, offset, kKeyContextInput);
|
||||||
EVPKeyPointer pkey;
|
EVPKeyPointer pkey;
|
||||||
ParsePublicKey(&pkey, config, key.get(), key.size(), allow_certificate);
|
ParsePublicKey(&pkey, config, key.get(), key.size());
|
||||||
if (!pkey)
|
if (!pkey)
|
||||||
ThrowCryptoError(env, ERR_get_error(), "Failed to read public key");
|
ThrowCryptoError(env, ERR_get_error(), "Failed to read public key");
|
||||||
return ManagedEVPPKey(pkey.release());
|
return ManagedEVPPKey(pkey.release());
|
||||||
@ -3158,8 +3154,7 @@ static bool IsRSAPrivateKey(const unsigned char* data, size_t size) {
|
|||||||
static ManagedEVPPKey GetPublicOrPrivateKeyFromJs(
|
static ManagedEVPPKey GetPublicOrPrivateKeyFromJs(
|
||||||
const FunctionCallbackInfo<Value>& args,
|
const FunctionCallbackInfo<Value>& args,
|
||||||
unsigned int* offset,
|
unsigned int* offset,
|
||||||
bool allow_key_object,
|
bool allow_key_object) {
|
||||||
bool allow_certificate) {
|
|
||||||
if (args[*offset]->IsString() || Buffer::HasInstance(args[*offset])) {
|
if (args[*offset]->IsString() || Buffer::HasInstance(args[*offset])) {
|
||||||
Environment* env = Environment::GetCurrent(args);
|
Environment* env = Environment::GetCurrent(args);
|
||||||
ByteSource data = ByteSource::FromStringOrBuffer(env, args[(*offset)++]);
|
ByteSource data = ByteSource::FromStringOrBuffer(env, args[(*offset)++]);
|
||||||
@ -3173,8 +3168,7 @@ static ManagedEVPPKey GetPublicOrPrivateKeyFromJs(
|
|||||||
// For PEM, we can easily determine whether it is a public or private key
|
// For PEM, we can easily determine whether it is a public or private key
|
||||||
// by looking for the respective PEM tags.
|
// by looking for the respective PEM tags.
|
||||||
ParsePublicKeyResult ret = ParsePublicKeyPEM(&pkey, data.get(),
|
ParsePublicKeyResult ret = ParsePublicKeyPEM(&pkey, data.get(),
|
||||||
data.size(),
|
data.size());
|
||||||
allow_certificate);
|
|
||||||
if (ret == ParsePublicKeyResult::kParsePublicNotRecognized) {
|
if (ret == ParsePublicKeyResult::kParsePublicNotRecognized) {
|
||||||
pkey = ParsePrivateKey(config, data.get(), data.size());
|
pkey = ParsePrivateKey(config, data.get(), data.size());
|
||||||
}
|
}
|
||||||
@ -3199,8 +3193,7 @@ static ManagedEVPPKey GetPublicOrPrivateKeyFromJs(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (is_public) {
|
if (is_public) {
|
||||||
ParsePublicKey(&pkey, config, data.get(), data.size(),
|
ParsePublicKey(&pkey, config, data.get(), data.size());
|
||||||
allow_certificate);
|
|
||||||
} else {
|
} else {
|
||||||
pkey = ParsePrivateKey(config, data.get(), data.size());
|
pkey = ParsePrivateKey(config, data.get(), data.size());
|
||||||
}
|
}
|
||||||
@ -3413,7 +3406,7 @@ void KeyObject::Init(const FunctionCallbackInfo<Value>& args) {
|
|||||||
CHECK_EQ(args.Length(), 3);
|
CHECK_EQ(args.Length(), 3);
|
||||||
|
|
||||||
offset = 0;
|
offset = 0;
|
||||||
pkey = GetPublicKeyFromJs(args, &offset, false, false);
|
pkey = GetPublicKeyFromJs(args, &offset, false);
|
||||||
if (!pkey)
|
if (!pkey)
|
||||||
return;
|
return;
|
||||||
key->InitPublic(pkey);
|
key->InitPublic(pkey);
|
||||||
@ -4695,7 +4688,7 @@ void Verify::VerifyFinal(const FunctionCallbackInfo<Value>& args) {
|
|||||||
ASSIGN_OR_RETURN_UNWRAP(&verify, args.Holder());
|
ASSIGN_OR_RETURN_UNWRAP(&verify, args.Holder());
|
||||||
|
|
||||||
unsigned int offset = 0;
|
unsigned int offset = 0;
|
||||||
ManagedEVPPKey pkey = GetPublicKeyFromJs(args, &offset, true, true);
|
ManagedEVPPKey pkey = GetPublicKeyFromJs(args, &offset, true);
|
||||||
|
|
||||||
char* hbuf = Buffer::Data(args[offset]);
|
char* hbuf = Buffer::Data(args[offset]);
|
||||||
ssize_t hlen = Buffer::Length(args[offset]);
|
ssize_t hlen = Buffer::Length(args[offset]);
|
||||||
@ -4751,7 +4744,7 @@ void PublicKeyCipher::Cipher(const FunctionCallbackInfo<Value>& args) {
|
|||||||
Environment* env = Environment::GetCurrent(args);
|
Environment* env = Environment::GetCurrent(args);
|
||||||
|
|
||||||
unsigned int offset = 0;
|
unsigned int offset = 0;
|
||||||
ManagedEVPPKey pkey = GetPublicOrPrivateKeyFromJs(args, &offset, true, true);
|
ManagedEVPPKey pkey = GetPublicOrPrivateKeyFromJs(args, &offset, true);
|
||||||
if (!pkey)
|
if (!pkey)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user