From 58f7361d59e3f4fb2a06fac1079ed3af0b898cfb Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 3 Nov 2024 17:45:26 +0100 Subject: [PATCH 1/2] Implement request #77761 (openssl_x509_parse does not create entries for public key type and size) This adds a new subarray to the output named "publicKey" that can contain subentries "type", "bits", and "groupName". The latter is only applicable for public key that have a group. --- UPGRADING | 6 + ext/openssl/openssl.c | 24 +++ .../openssl_x509_parse_basic_openssl32.phpt | 18 ++- ext/openssl/tests/req77761.phpt | 144 ++++++++++++++++++ 4 files changed, 190 insertions(+), 2 deletions(-) create mode 100644 ext/openssl/tests/req77761.phpt 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..8bef4501dd4e5 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -2136,6 +2136,30 @@ 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); + + int group_name_read = EVP_PKEY_get_group_name(public_key, gname, sizeof(gname), &gname_length); + int bits = EVP_PKEY_get_bits(public_key); + const char *type = EVP_PKEY_get0_type_name(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..80417ee55470d 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(3) "RSA" + } ["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(3) "RSA" + } ["subject"]=> array(5) { ["countryName"]=> diff --git a/ext/openssl/tests/req77761.phpt b/ext/openssl/tests/req77761.phpt new file mode 100644 index 0000000000000..61611b3e3b534 --- /dev/null +++ b/ext/openssl/tests/req77761.phpt @@ -0,0 +1,144 @@ +--TEST-- +Request #77761 (openssl_x509_parse does not create entries for public key type and size) +--EXTENSIONS-- +openssl +--FILE-- + +--EXPECT-- +Array +( + [name] => /C=AU/ST=Some-State/O=Internet Widgits Pty Ltd + [publicKey] => Array + ( + [bits] => 256 + [type] => EC + [groupName] => prime256v1 + ) + + [subject] => Array + ( + [C] => AU + [ST] => Some-State + [O] => Internet Widgits Pty Ltd + ) + + [hash] => 9da13359 + [issuer] => Array + ( + [C] => AU + [ST] => Some-State + [O] => Internet Widgits Pty Ltd + ) + + [version] => 2 + [serialNumber] => 0x5A844799C78584693A21A3505050CF6139D0E08E + [serialNumberHex] => 5A844799C78584693A21A3505050CF6139D0E08E + [validFrom] => 241103164345Z + [validTo] => 251103164345Z + [validFrom_time_t] => 1730652225 + [validTo_time_t] => 1762188225 + [signatureTypeSN] => ecdsa-with-SHA256 + [signatureTypeLN] => ecdsa-with-SHA256 + [signatureTypeNID] => 794 + [purposes] => Array + ( + [1] => Array + ( + [0] => 1 + [1] => 1 + [2] => sslclient + ) + + [2] => Array + ( + [0] => 1 + [1] => 1 + [2] => sslserver + ) + + [3] => Array + ( + [0] => 1 + [1] => 1 + [2] => nssslserver + ) + + [4] => Array + ( + [0] => 1 + [1] => 1 + [2] => smimesign + ) + + [5] => Array + ( + [0] => 1 + [1] => 1 + [2] => smimeencrypt + ) + + [6] => Array + ( + [0] => 1 + [1] => 1 + [2] => crlsign + ) + + [7] => Array + ( + [0] => 1 + [1] => 1 + [2] => any + ) + + [8] => Array + ( + [0] => 1 + [1] => 1 + [2] => ocsphelper + ) + + [9] => Array + ( + [0] => + [1] => 1 + [2] => timestampsign + ) + + [10] => Array + ( + [0] => + [1] => 1 + [2] => codesign + ) + + ) + + [extensions] => Array + ( + [subjectKeyIdentifier] => 0B:7F:A6:B8:77:96:B0:51:E4:0E:D5:41:DF:6A:6E:D9:7F:D6:22:00 + [authorityKeyIdentifier] => 0B:7F:A6:B8:77:96:B0:51:E4:0E:D5:41:DF:6A:6E:D9:7F:D6:22:00 + [basicConstraints] => CA:TRUE + ) + +) From 58a895453b01e5f0c590d3bccf6b8277058736b2 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 3 Nov 2024 18:16:21 +0100 Subject: [PATCH 2/2] Fix compile and test on 1.1.1 --- ext/openssl/openssl.c | 10 +- .../openssl_x509_parse_basic_openssl32.phpt | 4 +- ext/openssl/tests/req77761.phpt | 130 ++---------------- 3 files changed, 23 insertions(+), 121 deletions(-) diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index 8bef4501dd4e5..936ace331e254 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -2143,9 +2143,17 @@ PHP_FUNCTION(openssl_x509_parse) 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); - int bits = EVP_PKEY_get_bits(public_key); 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); diff --git a/ext/openssl/tests/openssl_x509_parse_basic_openssl32.phpt b/ext/openssl/tests/openssl_x509_parse_basic_openssl32.phpt index 80417ee55470d..f48778d7fa76e 100644 --- a/ext/openssl/tests/openssl_x509_parse_basic_openssl32.phpt +++ b/ext/openssl/tests/openssl_x509_parse_basic_openssl32.phpt @@ -25,7 +25,7 @@ array(17) { ["bits"]=> int(1024) ["type"]=> - string(3) "RSA" + string(%d) "%r(RSA|rsaEncryption)%r" } ["subject"]=> array(5) { @@ -188,7 +188,7 @@ array(17) { ["bits"]=> int(1024) ["type"]=> - string(3) "RSA" + string(%d) "%r(RSA|rsaEncryption)%r" } ["subject"]=> array(5) { diff --git a/ext/openssl/tests/req77761.phpt b/ext/openssl/tests/req77761.phpt index 61611b3e3b534..72fe21b4018fc 100644 --- a/ext/openssl/tests/req77761.phpt +++ b/ext/openssl/tests/req77761.phpt @@ -21,124 +21,18 @@ W+mj -----END CERTIFICATE----- CERT; -print_r(openssl_x509_parse($certificate)); +$publicKey = openssl_x509_parse($certificate)["publicKey"]; +var_dump($publicKey["bits"]); +var_dump($publicKey["type"] === "EC" || $publicKey["type"] === "id-ecPublicKey"); + +if (OPENSSL_VERSION_NUMBER >= 0x30000000) { + var_dump($publicKey["groupName"] === "prime256v1"); +} else { + var_dump(true); +} ?> --EXPECT-- -Array -( - [name] => /C=AU/ST=Some-State/O=Internet Widgits Pty Ltd - [publicKey] => Array - ( - [bits] => 256 - [type] => EC - [groupName] => prime256v1 - ) - - [subject] => Array - ( - [C] => AU - [ST] => Some-State - [O] => Internet Widgits Pty Ltd - ) - - [hash] => 9da13359 - [issuer] => Array - ( - [C] => AU - [ST] => Some-State - [O] => Internet Widgits Pty Ltd - ) - - [version] => 2 - [serialNumber] => 0x5A844799C78584693A21A3505050CF6139D0E08E - [serialNumberHex] => 5A844799C78584693A21A3505050CF6139D0E08E - [validFrom] => 241103164345Z - [validTo] => 251103164345Z - [validFrom_time_t] => 1730652225 - [validTo_time_t] => 1762188225 - [signatureTypeSN] => ecdsa-with-SHA256 - [signatureTypeLN] => ecdsa-with-SHA256 - [signatureTypeNID] => 794 - [purposes] => Array - ( - [1] => Array - ( - [0] => 1 - [1] => 1 - [2] => sslclient - ) - - [2] => Array - ( - [0] => 1 - [1] => 1 - [2] => sslserver - ) - - [3] => Array - ( - [0] => 1 - [1] => 1 - [2] => nssslserver - ) - - [4] => Array - ( - [0] => 1 - [1] => 1 - [2] => smimesign - ) - - [5] => Array - ( - [0] => 1 - [1] => 1 - [2] => smimeencrypt - ) - - [6] => Array - ( - [0] => 1 - [1] => 1 - [2] => crlsign - ) - - [7] => Array - ( - [0] => 1 - [1] => 1 - [2] => any - ) - - [8] => Array - ( - [0] => 1 - [1] => 1 - [2] => ocsphelper - ) - - [9] => Array - ( - [0] => - [1] => 1 - [2] => timestampsign - ) - - [10] => Array - ( - [0] => - [1] => 1 - [2] => codesign - ) - - ) - - [extensions] => Array - ( - [subjectKeyIdentifier] => 0B:7F:A6:B8:77:96:B0:51:E4:0E:D5:41:DF:6A:6E:D9:7F:D6:22:00 - [authorityKeyIdentifier] => 0B:7F:A6:B8:77:96:B0:51:E4:0E:D5:41:DF:6A:6E:D9:7F:D6:22:00 - [basicConstraints] => CA:TRUE - ) - -) +int(256) +bool(true) +bool(true)