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