|
45 | 45 | #include <memory>
|
46 | 46 | #include <vector>
|
47 | 47 |
|
48 |
| -static const char PUBLIC_KEY_PFX[] = "-----BEGIN PUBLIC KEY-----"; |
49 |
| -static const int PUBLIC_KEY_PFX_LEN = sizeof(PUBLIC_KEY_PFX) - 1; |
50 |
| -static const char PUBRSA_KEY_PFX[] = "-----BEGIN RSA PUBLIC KEY-----"; |
51 |
| -static const int PUBRSA_KEY_PFX_LEN = sizeof(PUBRSA_KEY_PFX) - 1; |
52 |
| -static const char CERTIFICATE_PFX[] = "-----BEGIN CERTIFICATE-----"; |
53 |
| -static const int CERTIFICATE_PFX_LEN = sizeof(CERTIFICATE_PFX) - 1; |
54 |
| - |
55 | 48 | static const int X509_NAME_FLAGS = ASN1_STRFLGS_ESC_CTRL
|
56 | 49 | | ASN1_STRFLGS_UTF8_CONVERT
|
57 | 50 | | XN_FLAG_SEP_MULTILINE
|
@@ -3656,38 +3649,64 @@ enum ParsePublicKeyResult {
|
3656 | 3649 | kParsePublicFailed
|
3657 | 3650 | };
|
3658 | 3651 |
|
| 3652 | +static ParsePublicKeyResult TryParsePublicKey( |
| 3653 | + EVPKeyPointer* pkey, |
| 3654 | + const BIOPointer& bp, |
| 3655 | + const char* name, |
| 3656 | + // NOLINTNEXTLINE(runtime/int) |
| 3657 | + std::function<EVP_PKEY*(const unsigned char** p, long l)> parse) { |
| 3658 | + unsigned char* der_data; |
| 3659 | + long der_len; // NOLINT(runtime/int) |
| 3660 | + |
| 3661 | + // This skips surrounding data and decodes PEM to DER. |
| 3662 | + { |
| 3663 | + MarkPopErrorOnReturn mark_pop_error_on_return; |
| 3664 | + if (PEM_bytes_read_bio(&der_data, &der_len, nullptr, name, |
| 3665 | + bp.get(), nullptr, nullptr) != 1) |
| 3666 | + return kParsePublicNotRecognized; |
| 3667 | + } |
| 3668 | + |
| 3669 | + // OpenSSL might modify the pointer, so we need to make a copy before parsing. |
| 3670 | + const unsigned char* p = der_data; |
| 3671 | + pkey->reset(parse(&p, der_len)); |
| 3672 | + OPENSSL_clear_free(der_data, der_len); |
| 3673 | + |
| 3674 | + return *pkey ? kParsePublicOk : kParsePublicFailed; |
| 3675 | +} |
| 3676 | + |
3659 | 3677 | static ParsePublicKeyResult ParsePublicKey(EVPKeyPointer* pkey,
|
3660 | 3678 | const char* key_pem,
|
3661 | 3679 | int key_pem_len) {
|
3662 | 3680 | BIOPointer bp(BIO_new_mem_buf(const_cast<char*>(key_pem), key_pem_len));
|
3663 | 3681 | if (!bp)
|
3664 | 3682 | return kParsePublicFailed;
|
3665 | 3683 |
|
3666 |
| - // Check if this is a PKCS#8 or RSA public key before trying as X.509. |
3667 |
| - if (strncmp(key_pem, PUBLIC_KEY_PFX, PUBLIC_KEY_PFX_LEN) == 0) { |
3668 |
| - pkey->reset( |
3669 |
| - PEM_read_bio_PUBKEY(bp.get(), nullptr, NoPasswordCallback, nullptr)); |
3670 |
| - } else if (strncmp(key_pem, PUBRSA_KEY_PFX, PUBRSA_KEY_PFX_LEN) == 0) { |
3671 |
| - RSAPointer rsa(PEM_read_bio_RSAPublicKey( |
3672 |
| - bp.get(), nullptr, PasswordCallback, nullptr)); |
3673 |
| - if (rsa) { |
3674 |
| - pkey->reset(EVP_PKEY_new()); |
3675 |
| - if (*pkey) |
3676 |
| - EVP_PKEY_set1_RSA(pkey->get(), rsa.get()); |
3677 |
| - } |
3678 |
| - } else if (strncmp(key_pem, CERTIFICATE_PFX, CERTIFICATE_PFX_LEN) == 0) { |
3679 |
| - // X.509 fallback |
3680 |
| - X509Pointer x509(PEM_read_bio_X509( |
3681 |
| - bp.get(), nullptr, NoPasswordCallback, nullptr)); |
3682 |
| - if (!x509) |
3683 |
| - return kParsePublicFailed; |
3684 |
| - |
3685 |
| - pkey->reset(X509_get_pubkey(x509.get())); |
3686 |
| - } else { |
3687 |
| - return kParsePublicNotRecognized; |
3688 |
| - } |
3689 |
| - |
3690 |
| - return *pkey ? kParsePublicOk : kParsePublicFailed; |
| 3684 | + ParsePublicKeyResult ret; |
| 3685 | + |
| 3686 | + // Try PKCS#8 first. |
| 3687 | + ret = TryParsePublicKey(pkey, bp, "PUBLIC KEY", |
| 3688 | + [](const unsigned char** p, long l) { // NOLINT(runtime/int) |
| 3689 | + return d2i_PUBKEY(nullptr, p, l); |
| 3690 | + }); |
| 3691 | + if (ret != kParsePublicNotRecognized) |
| 3692 | + return ret; |
| 3693 | + |
| 3694 | + // Maybe it is PKCS#1. |
| 3695 | + CHECK(BIO_reset(bp.get())); |
| 3696 | + ret = TryParsePublicKey(pkey, bp, "RSA PUBLIC KEY", |
| 3697 | + [](const unsigned char** p, long l) { // NOLINT(runtime/int) |
| 3698 | + return d2i_PublicKey(EVP_PKEY_RSA, nullptr, p, l); |
| 3699 | + }); |
| 3700 | + if (ret != kParsePublicNotRecognized) |
| 3701 | + return ret; |
| 3702 | + |
| 3703 | + // X.509 fallback. |
| 3704 | + CHECK(BIO_reset(bp.get())); |
| 3705 | + return TryParsePublicKey(pkey, bp, "CERTIFICATE", |
| 3706 | + [](const unsigned char** p, long l) { // NOLINT(runtime/int) |
| 3707 | + X509Pointer x509(d2i_X509(nullptr, p, l)); |
| 3708 | + return x509 ? X509_get_pubkey(x509.get()) : nullptr; |
| 3709 | + }); |
3691 | 3710 | }
|
3692 | 3711 |
|
3693 | 3712 | void Verify::Initialize(Environment* env, v8::Local<Object> target) {
|
|
0 commit comments