Skip to content

Commit ea34cc7

Browse files
tniessentargos
authored andcommitted
crypto: deduplicate public key parsing
PR-URL: #22553 Reviewed-By: Anna Henningsen <[email protected]>
1 parent 180bb0b commit ea34cc7

File tree

1 file changed

+51
-54
lines changed

1 file changed

+51
-54
lines changed

src/node_crypto.cc

+51-54
Original file line numberDiff line numberDiff line change
@@ -3651,6 +3651,45 @@ void Sign::SignFinal(const FunctionCallbackInfo<Value>& args) {
36513651
args.GetReturnValue().Set(rc);
36523652
}
36533653

3654+
enum ParsePublicKeyResult {
3655+
kParsePublicOk,
3656+
kParsePublicNotRecognized,
3657+
kParsePublicFailed
3658+
};
3659+
3660+
static ParsePublicKeyResult ParsePublicKey(EVPKeyPointer* pkey,
3661+
const char* key_pem,
3662+
int key_pem_len) {
3663+
BIOPointer bp(BIO_new_mem_buf(const_cast<char*>(key_pem), key_pem_len));
3664+
if (!bp)
3665+
return kParsePublicFailed;
3666+
3667+
// Check if this is a PKCS#8 or RSA public key before trying as X.509.
3668+
if (strncmp(key_pem, PUBLIC_KEY_PFX, PUBLIC_KEY_PFX_LEN) == 0) {
3669+
pkey->reset(
3670+
PEM_read_bio_PUBKEY(bp.get(), nullptr, NoPasswordCallback, nullptr));
3671+
} else if (strncmp(key_pem, PUBRSA_KEY_PFX, PUBRSA_KEY_PFX_LEN) == 0) {
3672+
RSAPointer rsa(PEM_read_bio_RSAPublicKey(
3673+
bp.get(), nullptr, PasswordCallback, nullptr));
3674+
if (rsa) {
3675+
pkey->reset(EVP_PKEY_new());
3676+
if (*pkey)
3677+
EVP_PKEY_set1_RSA(pkey->get(), rsa.get());
3678+
}
3679+
} else if (strncmp(key_pem, CERTIFICATE_PFX, CERTIFICATE_PFX_LEN) == 0) {
3680+
// X.509 fallback
3681+
X509Pointer x509(PEM_read_bio_X509(
3682+
bp.get(), nullptr, NoPasswordCallback, nullptr));
3683+
if (!x509)
3684+
return kParsePublicFailed;
3685+
3686+
pkey->reset(X509_get_pubkey(x509.get()));
3687+
} else {
3688+
return kParsePublicNotRecognized;
3689+
}
3690+
3691+
return *pkey ? kParsePublicOk : kParsePublicFailed;
3692+
}
36543693

36553694
void Verify::Initialize(Environment* env, v8::Local<Object> target) {
36563695
Local<FunctionTemplate> t = env->NewFunctionTemplate(New);
@@ -3711,34 +3750,7 @@ SignBase::Error Verify::VerifyFinal(const char* key_pem,
37113750
*verify_result = false;
37123751
EVPMDPointer mdctx = std::move(mdctx_);
37133752

3714-
BIOPointer bp(BIO_new_mem_buf(const_cast<char*>(key_pem), key_pem_len));
3715-
if (!bp)
3716-
return kSignPublicKey;
3717-
3718-
// Check if this is a PKCS#8 or RSA public key before trying as X.509.
3719-
// Split this out into a separate function once we have more than one
3720-
// consumer of public keys.
3721-
if (strncmp(key_pem, PUBLIC_KEY_PFX, PUBLIC_KEY_PFX_LEN) == 0) {
3722-
pkey.reset(
3723-
PEM_read_bio_PUBKEY(bp.get(), nullptr, NoPasswordCallback, nullptr));
3724-
} else if (strncmp(key_pem, PUBRSA_KEY_PFX, PUBRSA_KEY_PFX_LEN) == 0) {
3725-
RSAPointer rsa(PEM_read_bio_RSAPublicKey(
3726-
bp.get(), nullptr, PasswordCallback, nullptr));
3727-
if (rsa) {
3728-
pkey.reset(EVP_PKEY_new());
3729-
if (pkey)
3730-
EVP_PKEY_set1_RSA(pkey.get(), rsa.get());
3731-
}
3732-
} else {
3733-
// X.509 fallback
3734-
X509Pointer x509(PEM_read_bio_X509(
3735-
bp.get(), nullptr, NoPasswordCallback, nullptr));
3736-
if (!x509)
3737-
return kSignPublicKey;
3738-
3739-
pkey.reset(X509_get_pubkey(x509.get()));
3740-
}
3741-
if (!pkey)
3753+
if (ParsePublicKey(&pkey, key_pem, key_pem_len) != kParsePublicOk)
37423754
return kSignPublicKey;
37433755

37443756
if (!EVP_DigestFinal_ex(mdctx.get(), m, &m_len))
@@ -3808,40 +3820,25 @@ bool PublicKeyCipher::Cipher(const char* key_pem,
38083820
size_t* out_len) {
38093821
EVPKeyPointer pkey;
38103822

3811-
BIOPointer bp(BIO_new_mem_buf(const_cast<char*>(key_pem), key_pem_len));
3812-
if (!bp)
3813-
return false;
3814-
38153823
// Check if this is a PKCS#8 or RSA public key before trying as X.509 and
38163824
// private key.
3817-
if (operation == kPublic &&
3818-
strncmp(key_pem, PUBLIC_KEY_PFX, PUBLIC_KEY_PFX_LEN) == 0) {
3819-
pkey.reset(PEM_read_bio_PUBKEY(bp.get(), nullptr, nullptr, nullptr));
3820-
} else if (operation == kPublic &&
3821-
strncmp(key_pem, PUBRSA_KEY_PFX, PUBRSA_KEY_PFX_LEN) == 0) {
3822-
RSAPointer rsa(
3823-
PEM_read_bio_RSAPublicKey(bp.get(), nullptr, nullptr, nullptr));
3824-
if (rsa) {
3825-
pkey.reset(EVP_PKEY_new());
3826-
if (pkey)
3827-
EVP_PKEY_set1_RSA(pkey.get(), rsa.get());
3828-
}
3829-
} else if (operation == kPublic &&
3830-
strncmp(key_pem, CERTIFICATE_PFX, CERTIFICATE_PFX_LEN) == 0) {
3831-
X509Pointer x509(
3832-
PEM_read_bio_X509(bp.get(), nullptr, NoPasswordCallback, nullptr));
3833-
if (!x509)
3825+
if (operation == kPublic) {
3826+
ParsePublicKeyResult pkeyres = ParsePublicKey(&pkey, key_pem, key_pem_len);
3827+
if (pkeyres == kParsePublicFailed)
3828+
return false;
3829+
}
3830+
if (!pkey) {
3831+
// Private key fallback.
3832+
BIOPointer bp(BIO_new_mem_buf(const_cast<char*>(key_pem), key_pem_len));
3833+
if (!bp)
38343834
return false;
3835-
3836-
pkey.reset(X509_get_pubkey(x509.get()));
3837-
} else {
38383835
pkey.reset(PEM_read_bio_PrivateKey(bp.get(),
38393836
nullptr,
38403837
PasswordCallback,
38413838
const_cast<char*>(passphrase)));
3839+
if (!pkey)
3840+
return false;
38423841
}
3843-
if (!pkey)
3844-
return false;
38453842

38463843
EVPKeyCtxPointer ctx(EVP_PKEY_CTX_new(pkey.get(), nullptr));
38473844
if (!ctx)

0 commit comments

Comments
 (0)