|
45 | 45 | #include<memory> |
46 | 46 | #include<vector> |
47 | 47 |
|
48 | | -staticconstchar PUBLIC_KEY_PFX[] = "-----BEGIN PUBLIC KEY-----"; |
49 | | -staticconstint PUBLIC_KEY_PFX_LEN = sizeof(PUBLIC_KEY_PFX) - 1; |
50 | | -staticconstchar PUBRSA_KEY_PFX[] = "-----BEGIN RSA PUBLIC KEY-----"; |
51 | | -staticconstint PUBRSA_KEY_PFX_LEN = sizeof(PUBRSA_KEY_PFX) - 1; |
52 | | -staticconstchar CERTIFICATE_PFX[] = "-----BEGIN CERTIFICATE-----"; |
53 | | -staticconstint CERTIFICATE_PFX_LEN = sizeof(CERTIFICATE_PFX) - 1; |
54 | | - |
55 | 48 | staticconstint 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 | +constchar* name, |
| 3656 | +// NOLINTNEXTLINE(runtime/int) |
| 3657 | + std::function<EVP_PKEY*(constunsignedchar** p, long l)> parse){ |
| 3658 | +unsignedchar* 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 | +returnkParsePublicNotRecognized; |
| 3667 | + } |
| 3668 | + |
| 3669 | +// OpenSSL might modify the pointer, so we need to make a copy before parsing. |
| 3670 | +constunsignedchar* 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 | constchar* 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 | returnkParsePublicFailed; |
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 | | - } elseif (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 | | - } elseif (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 | | -returnkParsePublicFailed; |
3684 | | - |
3685 | | - pkey->reset(X509_get_pubkey(x509.get())); |
3686 | | - } else{ |
3687 | | -returnkParsePublicNotRecognized; |
3688 | | - } |
3689 | | - |
3690 | | -return *pkey ? kParsePublicOk : kParsePublicFailed; |
| 3684 | + ParsePublicKeyResult ret; |
| 3685 | + |
| 3686 | +// Try PKCS#8 first. |
| 3687 | + ret = TryParsePublicKey(pkey, bp, "PUBLIC KEY", |
| 3688 | + [](constunsignedchar** p, long l){// NOLINT(runtime/int) |
| 3689 | +returnd2i_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 | + [](constunsignedchar** p, long l){// NOLINT(runtime/int) |
| 3698 | +returnd2i_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 | +returnTryParsePublicKey(pkey, bp, "CERTIFICATE", |
| 3706 | + [](constunsignedchar** 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 | voidVerify::Initialize(Environment* env, v8::Local<Object> target){ |
|
0 commit comments