Skip to content

Commit f124fe2

Browse files
committed
Init OpenSSL libctx and use it for pkey
1 parent 2194ad8 commit f124fe2

6 files changed

+108
-18
lines changed

ext/openssl/openssl.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,9 @@ PHP_GINIT_FUNCTION(openssl)
438438
#endif
439439
openssl_globals->errors = NULL;
440440
openssl_globals->errors_mark = NULL;
441+
#if PHP_OPENSSL_API_VERSION >= 0x30000
442+
php_openssl_backend_init_libctx(&openssl_globals->libctx, &openssl_globals->propq);
443+
#endif
441444
}
442445
/* }}} */
443446

@@ -450,6 +453,9 @@ PHP_GSHUTDOWN_FUNCTION(openssl)
450453
if (openssl_globals->errors_mark) {
451454
pefree(openssl_globals->errors_mark, 1);
452455
}
456+
#if PHP_OPENSSL_API_VERSION >= 0x30000
457+
php_openssl_backend_destroy_libctx(openssl_globals->libctx, openssl_globals->propq);
458+
#endif
453459
}
454460
/* }}} */
455461

@@ -2036,19 +2042,19 @@ PHP_FUNCTION(openssl_pkey_new)
20362042
#if PHP_OPENSSL_API_VERSION >= 0x30000
20372043
} else if ((data = zend_hash_str_find(Z_ARRVAL_P(args), "x25519", sizeof("x25519") - 1)) != NULL &&
20382044
Z_TYPE_P(data) == IS_ARRAY) {
2039-
php_openssl_pkey_object_curve_25519_448(return_value, EVP_PKEY_X25519, data);
2045+
php_openssl_pkey_object_curve_25519_448(return_value, "X25519", data);
20402046
return;
20412047
} else if ((data = zend_hash_str_find(Z_ARRVAL_P(args), "ed25519", sizeof("ed25519") - 1)) != NULL &&
20422048
Z_TYPE_P(data) == IS_ARRAY) {
2043-
php_openssl_pkey_object_curve_25519_448(return_value, EVP_PKEY_ED25519, data);
2049+
php_openssl_pkey_object_curve_25519_448(return_value, "ED25519", data);
20442050
return;
20452051
} else if ((data = zend_hash_str_find(Z_ARRVAL_P(args), "x448", sizeof("x448") - 1)) != NULL &&
20462052
Z_TYPE_P(data) == IS_ARRAY) {
2047-
php_openssl_pkey_object_curve_25519_448(return_value, EVP_PKEY_X448, data);
2053+
php_openssl_pkey_object_curve_25519_448(return_value, "X448", data);
20482054
return;
20492055
} else if ((data = zend_hash_str_find(Z_ARRVAL_P(args), "ed448", sizeof("ed448") - 1)) != NULL &&
20502056
Z_TYPE_P(data) == IS_ARRAY) {
2051-
php_openssl_pkey_object_curve_25519_448(return_value, EVP_PKEY_ED448, data);
2057+
php_openssl_pkey_object_curve_25519_448(return_value, "ED448", data);
20522058
return;
20532059
#endif
20542060
}

ext/openssl/openssl_backend_common.c

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1429,7 +1429,7 @@ EVP_PKEY *php_openssl_pkey_from_zval(
14291429

14301430
zend_string *php_openssl_pkey_derive(EVP_PKEY *key, EVP_PKEY *peer_key, size_t key_size)
14311431
{
1432-
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(key, NULL);
1432+
EVP_PKEY_CTX *ctx = php_openssl_pkey_new_from_pkey(key);
14331433
if (!ctx) {
14341434
return NULL;
14351435
}
@@ -1487,6 +1487,37 @@ int php_openssl_get_evp_pkey_type(int key_type) {
14871487
}
14881488
}
14891489

1490+
const char *php_openssl_get_evp_pkey_name(int key_type) {
1491+
switch (key_type) {
1492+
case OPENSSL_KEYTYPE_RSA:
1493+
return "RSA";
1494+
#if !defined(OPENSSL_NO_DSA)
1495+
case OPENSSL_KEYTYPE_DSA:
1496+
return "DSA";
1497+
#endif
1498+
#if !defined(NO_DH)
1499+
case OPENSSL_KEYTYPE_DH:
1500+
return "DH";
1501+
#endif
1502+
#ifdef HAVE_EVP_PKEY_EC
1503+
case OPENSSL_KEYTYPE_EC:
1504+
return "EC";
1505+
#endif
1506+
#if PHP_OPENSSL_API_VERSION >= 0x30000
1507+
case OPENSSL_KEYTYPE_X25519:
1508+
return "X25519";
1509+
case OPENSSL_KEYTYPE_ED25519:
1510+
return "ED25519";
1511+
case OPENSSL_KEYTYPE_X448:
1512+
return "X448";
1513+
case OPENSSL_KEYTYPE_ED448:
1514+
return "ED448";
1515+
#endif
1516+
default:
1517+
return "";
1518+
}
1519+
}
1520+
14901521
EVP_PKEY * php_openssl_generate_private_key(struct php_x509_request * req)
14911522
{
14921523
if (req->priv_key_bits < MIN_KEY_LENGTH) {
@@ -1500,14 +1531,15 @@ EVP_PKEY * php_openssl_generate_private_key(struct php_x509_request * req)
15001531
php_error_docref(NULL, E_WARNING, "Unsupported private key type");
15011532
return NULL;
15021533
}
1534+
const char *name = php_openssl_get_evp_pkey_name(req->priv_key_type);
15031535

15041536
int egdsocket, seeded;
15051537
char *randfile = php_openssl_conf_get_string(req->req_config, req->section_name, "RANDFILE");
15061538
php_openssl_load_rand_file(randfile, &egdsocket, &seeded);
15071539

15081540
EVP_PKEY *key = NULL;
15091541
EVP_PKEY *params = NULL;
1510-
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(type, NULL);
1542+
EVP_PKEY_CTX *ctx = php_openssl_pkey_new_from_name(name, type);
15111543
if (!ctx) {
15121544
php_openssl_store_errors();
15131545
goto cleanup;
@@ -1569,7 +1601,7 @@ EVP_PKEY * php_openssl_generate_private_key(struct php_x509_request * req)
15691601
}
15701602

15711603
EVP_PKEY_CTX_free(ctx);
1572-
ctx = EVP_PKEY_CTX_new(params, NULL);
1604+
ctx = php_openssl_pkey_new_from_pkey(params);
15731605
if (!ctx) {
15741606
php_openssl_store_errors();
15751607
goto cleanup;

ext/openssl/openssl_backend_v1.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,16 @@ void php_openssl_backend_shutdown(void)
4444
#endif
4545
}
4646

47+
EVP_PKEY_CTX *php_openssl_pkey_new_from_name(const char *name, int id)
48+
{
49+
return EVP_PKEY_CTX_new_id(id, NULL);
50+
}
51+
52+
EVP_PKEY_CTX *php_openssl_pkey_new_from_pkey(EVP_PKEY *pkey)
53+
{
54+
return EVP_PKEY_CTX_new(pkey, NULL);
55+
}
56+
4757
static bool php_openssl_pkey_init_rsa_data(RSA *rsa, zval *data)
4858
{
4959
BIGNUM *n, *e, *d, *p, *q, *dmp1, *dmq1, *iqmp;

ext/openssl/openssl_backend_v3.c

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,47 @@
2222
#include <openssl/param_build.h>
2323
#include <openssl/provider.h>
2424

25+
ZEND_EXTERN_MODULE_GLOBALS(openssl)
26+
2527
void php_openssl_backend_shutdown(void)
2628
{
2729
(void) 0;
2830
}
2931

32+
void php_openssl_backend_init_libctx(OSSL_LIB_CTX **plibctx, char **ppropq)
33+
{
34+
/* The return value is not checked because we cannot reasonable fail in GINIT so using NULL
35+
* (default context) is probably better. */
36+
*plibctx = OSSL_LIB_CTX_new();
37+
*ppropq = NULL;
38+
}
39+
40+
void php_openssl_backend_destroy_libctx(OSSL_LIB_CTX *libctx, char *propq)
41+
{
42+
if (libctx != NULL) {
43+
OSSL_LIB_CTX_free(libctx);
44+
}
45+
if (propq != NULL) {
46+
free(propq);
47+
}
48+
}
49+
50+
EVP_PKEY_CTX *php_openssl_pkey_new_from_name(const char *name, int id)
51+
{
52+
return EVP_PKEY_CTX_new_from_name(OPENSSL_G(libctx), name, OPENSSL_G(propq));
53+
}
54+
55+
EVP_PKEY_CTX *php_openssl_pkey_new_from_pkey(EVP_PKEY *pkey)
56+
{
57+
return EVP_PKEY_CTX_new_from_pkey(OPENSSL_G(libctx), pkey, OPENSSL_G(propq));
58+
}
59+
3060
EVP_PKEY *php_openssl_pkey_init_rsa(zval *data)
3161
{
3262
BIGNUM *n = NULL, *e = NULL, *d = NULL, *p = NULL, *q = NULL;
3363
BIGNUM *dmp1 = NULL, *dmq1 = NULL, *iqmp = NULL;
3464
EVP_PKEY *pkey = NULL;
35-
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
65+
EVP_PKEY_CTX *ctx = php_openssl_pkey_new_from_name("RSA", EVP_PKEY_RSA);
3666
OSSL_PARAM *params = NULL;
3767
OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new();
3868

@@ -100,7 +130,7 @@ EVP_PKEY *php_openssl_pkey_init_dsa(zval *data, bool *is_private)
100130
{
101131
BIGNUM *p = NULL, *q = NULL, *g = NULL, *priv_key = NULL, *pub_key = NULL;
102132
EVP_PKEY *param_key = NULL, *pkey = NULL;
103-
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_DSA, NULL);
133+
EVP_PKEY_CTX *ctx = php_openssl_pkey_new_from_name("DSA", EVP_PKEY_DSA);
104134
OSSL_PARAM *params = NULL;
105135
OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new();
106136

@@ -144,7 +174,7 @@ EVP_PKEY *php_openssl_pkey_init_dsa(zval *data, bool *is_private)
144174
} else {
145175
*is_private = true;
146176
EVP_PKEY_CTX_free(ctx);
147-
ctx = EVP_PKEY_CTX_new(param_key, NULL);
177+
ctx = php_openssl_pkey_new_from_pkey(param_key);
148178
if (EVP_PKEY_keygen_init(ctx) <= 0 || EVP_PKEY_keygen(ctx, &pkey) <= 0) {
149179
goto cleanup;
150180
}
@@ -168,7 +198,7 @@ EVP_PKEY *php_openssl_pkey_init_dh(zval *data, bool *is_private)
168198
{
169199
BIGNUM *p = NULL, *q = NULL, *g = NULL, *priv_key = NULL, *pub_key = NULL;
170200
EVP_PKEY *param_key = NULL, *pkey = NULL;
171-
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_DH, NULL);
201+
EVP_PKEY_CTX *ctx = php_openssl_pkey_new_from_name("DH", EVP_PKEY_DH);
172202
OSSL_PARAM *params = NULL;
173203
OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new();
174204

@@ -219,7 +249,7 @@ EVP_PKEY *php_openssl_pkey_init_dh(zval *data, bool *is_private)
219249
} else {
220250
*is_private = true;
221251
EVP_PKEY_CTX_free(ctx);
222-
ctx = EVP_PKEY_CTX_new(param_key, NULL);
252+
ctx = php_openssl_pkey_new_from_pkey(param_key);
223253
if (EVP_PKEY_keygen_init(ctx) <= 0 || EVP_PKEY_keygen(ctx, &pkey) <= 0) {
224254
goto cleanup;
225255
}
@@ -250,7 +280,7 @@ EVP_PKEY *php_openssl_pkey_init_ec(zval *data, bool *is_private) {
250280
unsigned char *point_q_buf = NULL;
251281
EC_GROUP *group = NULL;
252282
EVP_PKEY *param_key = NULL, *pkey = NULL;
253-
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL);
283+
EVP_PKEY_CTX *ctx = php_openssl_pkey_new_from_name("EC", EVP_PKEY_EC);
254284
BN_CTX *bctx = BN_CTX_new();
255285
OSSL_PARAM *params = NULL;
256286
OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new();
@@ -269,7 +299,7 @@ EVP_PKEY *php_openssl_pkey_init_ec(zval *data, bool *is_private) {
269299
goto cleanup;
270300
}
271301

272-
if (!(group = EC_GROUP_new_by_curve_name(nid))) {
302+
if (!(group = EC_GROUP_new_by_curve_name_ex(OPENSSL_G(libctx), OPENSSL_G(propq), nid))) {
273303
goto cleanup;
274304
}
275305

@@ -438,7 +468,7 @@ EVP_PKEY *php_openssl_pkey_init_ec(zval *data, bool *is_private) {
438468
}
439469
#endif
440470

441-
void php_openssl_pkey_object_curve_25519_448(zval *return_value, int key_type, zval *data) {
471+
void php_openssl_pkey_object_curve_25519_448(zval *return_value, const char *name, zval *data) {
442472
EVP_PKEY *pkey = NULL;
443473
EVP_PKEY_CTX *ctx = NULL;
444474
OSSL_PARAM *params = NULL;
@@ -466,7 +496,7 @@ void php_openssl_pkey_object_curve_25519_448(zval *return_value, int key_type, z
466496
}
467497

468498
params = OSSL_PARAM_BLD_to_param(bld);
469-
ctx = EVP_PKEY_CTX_new_id(key_type, NULL);
499+
ctx = php_openssl_pkey_new_from_name(name, 0);
470500
if (!params || !ctx) {
471501
goto cleanup;
472502
}

ext/openssl/php_openssl.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,10 @@ struct php_openssl_errors {
7373
ZEND_BEGIN_MODULE_GLOBALS(openssl)
7474
struct php_openssl_errors *errors;
7575
struct php_openssl_errors *errors_mark;
76+
#if PHP_OPENSSL_API_VERSION >= 0x30000
77+
OSSL_LIB_CTX *libctx;
78+
char *propq;
79+
#endif
7680
ZEND_END_MODULE_GLOBALS(openssl)
7781

7882
#define OPENSSL_G(v) ZEND_MODULE_GLOBALS_ACCESSOR(openssl, v)

ext/openssl/php_openssl_backend.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -225,8 +225,15 @@ EVP_MD * php_openssl_get_evp_md_from_algo(zend_long algo);
225225
const EVP_CIPHER * php_openssl_get_evp_cipher_from_algo(zend_long algo);
226226

227227
void php_openssl_backend_init(void);
228+
void php_openssl_backend_init_common(void);
229+
void php_openssl_backend_gshutdown(void);
228230
void php_openssl_backend_shutdown(void);
229231

232+
#if PHP_OPENSSL_API_VERSION >= 0x30000
233+
void php_openssl_backend_init_libctx(OSSL_LIB_CTX **plibctx, char **ppropq);
234+
void php_openssl_backend_destroy_libctx(OSSL_LIB_CTX *libctx, char *propq);
235+
#endif
236+
230237
const char *php_openssl_get_conf_filename(void);
231238

232239
void php_openssl_set_cert_locations(zval *return_value);
@@ -296,15 +303,16 @@ void php_openssl_add_bn_to_array(zval *ary, const BIGNUM *bn, const char *name);
296303
} \
297304
} while (0);
298305

306+
EVP_PKEY_CTX *php_openssl_pkey_new_from_name(const char *name, int id);
307+
EVP_PKEY_CTX *php_openssl_pkey_new_from_pkey(EVP_PKEY *pkey);
299308

300309
EVP_PKEY *php_openssl_pkey_init_rsa(zval *data);
301310
EVP_PKEY *php_openssl_pkey_init_dsa(zval *data, bool *is_private);
302311
BIGNUM *php_openssl_dh_pub_from_priv(BIGNUM *priv_key, BIGNUM *g, BIGNUM *p);
303312
EVP_PKEY *php_openssl_pkey_init_dh(zval *data, bool *is_private);
304313
EVP_PKEY *php_openssl_pkey_init_ec(zval *data, bool *is_private);
305-
void php_openssl_pkey_object_curve_25519_448(zval *return_value, int key_type, zval *data);
306314
#if PHP_OPENSSL_API_VERSION >= 0x30000
307-
void php_openssl_pkey_object_curve_25519_448(zval *return_value, int key_type, zval *data);
315+
void php_openssl_pkey_object_curve_25519_448(zval *return_value, const char *name, zval *data);
308316
#endif
309317
zend_long php_openssl_pkey_get_details(zval *return_value, EVP_PKEY *pkey);
310318

0 commit comments

Comments
 (0)