diff --git a/UPGRADING b/UPGRADING index a336173ffd8b0..07261f93178c6 100644 --- a/UPGRADING +++ b/UPGRADING @@ -40,6 +40,12 @@ PHP 8.5 UPGRADE NOTES - DOM: . Added Dom\Element::$outerHTML. +- OpenSSL: + . openssl_x509_parse() now outputs information about the public key. + The output contains an additional subarray "publicKey" with the entries + "bits", "type", and "groupName". The last one is only applicable for + public keys that have a group. + - XSL: . The $namespace argument of XSLTProcessor::getParameter(), XSLTProcessor::setParameter() and XSLTProcessor::removeParameter() diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index f6994a06c5428..936ace331e254 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -2136,6 +2136,38 @@ PHP_FUNCTION(openssl_x509_parse) add_assoc_string(return_value, "name", cert_name); OPENSSL_free(cert_name); + const EVP_PKEY *public_key = X509_get0_pubkey(cert); + if (public_key) { + char gname[64]; + size_t gname_length; + zval public_key_zv; + array_init(&public_key_zv); + +#if PHP_OPENSSL_API_VERSION >= 0x30000 + int group_name_read = EVP_PKEY_get_group_name(public_key, gname, sizeof(gname), &gname_length); + const char *type = EVP_PKEY_get0_type_name(public_key); +#else + int group_name_read = 0; + (void) gname; + gname_length = 0; + const char *type = OBJ_nid2sn(EVP_PKEY_base_id(public_key)); +#endif + + int bits = EVP_PKEY_bits(public_key); + + if (bits > 0 && type) { + add_assoc_long(&public_key_zv, "bits", bits); + add_assoc_string(&public_key_zv, "type", type); + if (group_name_read == 1) { + /* Does not exist on all key types */ + add_assoc_stringl(&public_key_zv, "groupName", gname, gname_length); + } + add_assoc_zval(return_value, "publicKey", &public_key_zv); + } else { + zval_ptr_dtor(&public_key_zv); + } + } + php_openssl_add_assoc_name_entry(return_value, "subject", subject_name, useshortnames); /* hash as used in CA directories to lookup cert by subject name */ { diff --git a/ext/openssl/tests/openssl_x509_parse_basic_openssl32.phpt b/ext/openssl/tests/openssl_x509_parse_basic_openssl32.phpt index a0b125fb4ea06..f48778d7fa76e 100644 --- a/ext/openssl/tests/openssl_x509_parse_basic_openssl32.phpt +++ b/ext/openssl/tests/openssl_x509_parse_basic_openssl32.phpt @@ -17,9 +17,16 @@ var_dump(openssl_x509_parse($cert, false)); ?> --EXPECTF-- bool(true) -array(16) { +array(17) { ["name"]=> string(96) "/C=BR/ST=Rio Grande do Sul/L=Porto Alegre/CN=Henrique do N. Angelo/emailAddress=hnangelo@php.net" + ["publicKey"]=> + array(2) { + ["bits"]=> + int(1024) + ["type"]=> + string(%d) "%r(RSA|rsaEncryption)%r" + } ["subject"]=> array(5) { ["C"]=> @@ -173,9 +180,16 @@ serial:AE:C5:56:CC:72:37:50:A2%A" string(7) "CA:TRUE" } } -array(16) { +array(17) { ["name"]=> string(96) "/C=BR/ST=Rio Grande do Sul/L=Porto Alegre/CN=Henrique do N. Angelo/emailAddress=hnangelo@php.net" + ["publicKey"]=> + array(2) { + ["bits"]=> + int(1024) + ["type"]=> + string(%d) "%r(RSA|rsaEncryption)%r" + } ["subject"]=> array(5) { ["countryName"]=> diff --git a/ext/openssl/tests/req77761.phpt b/ext/openssl/tests/req77761.phpt new file mode 100644 index 0000000000000..72fe21b4018fc --- /dev/null +++ b/ext/openssl/tests/req77761.phpt @@ -0,0 +1,38 @@ +--TEST-- +Request #77761 (openssl_x509_parse does not create entries for public key type and size) +--EXTENSIONS-- +openssl +--FILE-- += 0x30000000) { + var_dump($publicKey["groupName"] === "prime256v1"); +} else { + var_dump(true); +} + +?> +--EXPECT-- +int(256) +bool(true) +bool(true)