Skip to content

Commit 26a51e8

Browse files
committed
Extract public key portion via PEM roundtrip
The workaround with cloning the X509_REQ no longer works in OpenSSL 3. Instead extract the public key portion by round tripping through PEM.
1 parent f9e701c commit 26a51e8

File tree

1 file changed

+19
-24
lines changed

1 file changed

+19
-24
lines changed

ext/openssl/openssl.c

+19-24
Original file line numberDiff line numberDiff line change
@@ -3407,49 +3407,44 @@ PHP_FUNCTION(openssl_csr_get_subject)
34073407
}
34083408
/* }}} */
34093409

3410+
static EVP_PKEY *php_openssl_extract_public_key(EVP_PKEY *priv_key)
3411+
{
3412+
/* Extract public key portion by round-tripping through PEM. */
3413+
BIO *bio = BIO_new(BIO_s_mem());
3414+
if (!bio || !PEM_write_bio_PUBKEY(bio, priv_key)) {
3415+
BIO_free(bio);
3416+
return NULL;
3417+
}
3418+
3419+
EVP_PKEY *pub_key = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL);
3420+
BIO_free(bio);
3421+
return pub_key;
3422+
}
3423+
34103424
/* {{{ Returns the subject of a CERT or FALSE on error */
34113425
PHP_FUNCTION(openssl_csr_get_public_key)
34123426
{
3413-
X509_REQ *orig_csr, *csr;
34143427
zend_object *csr_obj;
34153428
zend_string *csr_str;
34163429
bool use_shortnames = 1;
34173430

3418-
EVP_PKEY *tpubkey;
3419-
34203431
ZEND_PARSE_PARAMETERS_START(1, 2)
34213432
Z_PARAM_OBJ_OF_CLASS_OR_STR(csr_obj, php_openssl_request_ce, csr_str)
34223433
Z_PARAM_OPTIONAL
34233434
Z_PARAM_BOOL(use_shortnames)
34243435
ZEND_PARSE_PARAMETERS_END();
34253436

3426-
orig_csr = php_openssl_csr_from_param(csr_obj, csr_str);
3427-
if (orig_csr == NULL) {
3437+
X509_REQ *csr = php_openssl_csr_from_param(csr_obj, csr_str);
3438+
if (csr == NULL) {
34283439
RETURN_FALSE;
34293440
}
34303441

3431-
#if PHP_OPENSSL_API_VERSION >= 0x10100
3432-
/* Due to changes in OpenSSL 1.1 related to locking when decoding CSR,
3433-
* the pub key is not changed after assigning. It means if we pass
3434-
* a private key, it will be returned including the private part.
3435-
* If we duplicate it, then we get just the public part which is
3436-
* the same behavior as for OpenSSL 1.0 */
3437-
csr = X509_REQ_dup(orig_csr);
3438-
#else
3439-
csr = orig_csr;
3440-
#endif
3441-
34423442
/* Retrieve the public key from the CSR */
3443-
tpubkey = X509_REQ_get_pubkey(csr);
3444-
3445-
if (csr != orig_csr) {
3446-
/* We need to free the duplicated CSR */
3447-
X509_REQ_free(csr);
3448-
}
3443+
EVP_PKEY *tpubkey = php_openssl_extract_public_key(X509_REQ_get_pubkey(csr));
34493444

34503445
if (csr_str) {
3451-
/* We also need to free the original CSR if it was freshly created */
3452-
X509_REQ_free(orig_csr);
3446+
/* We need to free the original CSR if it was freshly created */
3447+
X509_REQ_free(csr);
34533448
}
34543449

34553450
if (tpubkey == NULL) {

0 commit comments

Comments
 (0)