Skip to content

Commit 7950482

Browse files
iliaalndossche
authored andcommitted
Fix GH-21083: Skip private_key_bits validation for EC/curve-based keys
openssl_pkey_new() checks private_key_bits >= 384 before generating any key. For EC, X25519, ED25519, X448, and ED448 the size is inherent to the curve or algorithm, so this check doesn't apply and causes failures when default_bits is missing from openssl.cnf (which is the case in OpenSSL 3.6's default config). Skip the minimum-bits check for key types that don't use private_key_bits. Closes GH-21387.
1 parent 284fd77 commit 7950482

File tree

3 files changed

+69
-1
lines changed

3 files changed

+69
-1
lines changed

NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ PHP NEWS
55
- Bz2:
66
. Fix truncation of total output size causing erroneous errors. (ndossche)
77

8+
- OpenSSL:
9+
. Fixed bug GH-21083 (Skip private_key_bits validation for EC/curve-based
10+
keys). (iliaal)
11+
812
- PCRE:
913
. Fixed re-entrancy issue on php_pcre_match_impl, php_pcre_replace_impl,
1014
php_pcre_split_impl, and php_pcre_grep_impl. (David Carlier)

ext/openssl/openssl.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3828,7 +3828,10 @@ static int php_openssl_get_evp_pkey_type(int key_type) {
38283828
/* {{{ php_openssl_generate_private_key */
38293829
static EVP_PKEY * php_openssl_generate_private_key(struct php_x509_request * req)
38303830
{
3831-
if (req->priv_key_bits < MIN_KEY_LENGTH) {
3831+
if ((req->priv_key_type == OPENSSL_KEYTYPE_RSA ||
3832+
req->priv_key_type == OPENSSL_KEYTYPE_DH ||
3833+
req->priv_key_type == OPENSSL_KEYTYPE_DSA) &&
3834+
req->priv_key_bits < MIN_KEY_LENGTH) {
38323835
php_error_docref(NULL, E_WARNING, "Private key length must be at least %d bits, configured to %d",
38333836
MIN_KEY_LENGTH, req->priv_key_bits);
38343837
return NULL;

ext/openssl/tests/gh21083.phpt

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
--TEST--
2+
GH-21083 (openssl_pkey_new() fails for EC keys when private_key_bits is not set)
3+
--EXTENSIONS--
4+
openssl
5+
--SKIPIF--
6+
<?php if (!defined("OPENSSL_KEYTYPE_EC")) die("skip EC disabled"); ?>
7+
--ENV--
8+
OPENSSL_CONF=
9+
--FILE--
10+
<?php
11+
// Create a minimal openssl.cnf without default_bits (simulates OpenSSL 3.6 default config)
12+
$conf = tempnam(sys_get_temp_dir(), 'ossl');
13+
file_put_contents($conf, "[req]\ndistinguished_name = req_dn\n[req_dn]\n");
14+
15+
// EC key - size is determined by the curve, private_key_bits should not be required
16+
$key = openssl_pkey_new([
17+
'config' => $conf,
18+
'private_key_type' => OPENSSL_KEYTYPE_EC,
19+
'curve_name' => 'prime256v1',
20+
]);
21+
var_dump($key !== false);
22+
$details = openssl_pkey_get_details($key);
23+
var_dump($details['bits']);
24+
var_dump($details['type'] === OPENSSL_KEYTYPE_EC);
25+
echo "EC OK\n";
26+
27+
// X25519 - fixed size key, private_key_bits should not be required
28+
if (defined('OPENSSL_KEYTYPE_X25519')) {
29+
$key = openssl_pkey_new([
30+
'config' => $conf,
31+
'private_key_type' => OPENSSL_KEYTYPE_X25519,
32+
]);
33+
var_dump($key !== false);
34+
echo "X25519 OK\n";
35+
} else {
36+
echo "bool(true)\nX25519 OK\n";
37+
}
38+
39+
// Ed25519 - fixed size key, private_key_bits should not be required
40+
if (defined('OPENSSL_KEYTYPE_ED25519')) {
41+
$key = openssl_pkey_new([
42+
'config' => $conf,
43+
'private_key_type' => OPENSSL_KEYTYPE_ED25519,
44+
]);
45+
var_dump($key !== false);
46+
echo "Ed25519 OK\n";
47+
} else {
48+
echo "bool(true)\nEd25519 OK\n";
49+
}
50+
51+
unlink($conf);
52+
?>
53+
--EXPECT--
54+
bool(true)
55+
int(256)
56+
bool(true)
57+
EC OK
58+
bool(true)
59+
X25519 OK
60+
bool(true)
61+
Ed25519 OK

0 commit comments

Comments
 (0)