Skip to content

Init OpenSSL libctx and use it for pkey #18282

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions ext/openssl/openssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,9 @@ PHP_GINIT_FUNCTION(openssl)
#endif
openssl_globals->errors = NULL;
openssl_globals->errors_mark = NULL;
#if PHP_OPENSSL_API_VERSION >= 0x30000
php_openssl_backend_init_libctx(&openssl_globals->libctx, &openssl_globals->propq);
#endif
}
/* }}} */

Expand All @@ -450,6 +453,9 @@ PHP_GSHUTDOWN_FUNCTION(openssl)
if (openssl_globals->errors_mark) {
pefree(openssl_globals->errors_mark, 1);
}
#if PHP_OPENSSL_API_VERSION >= 0x30000
php_openssl_backend_destroy_libctx(openssl_globals->libctx, openssl_globals->propq);
#endif
}
/* }}} */

Expand Down Expand Up @@ -2036,19 +2042,19 @@ PHP_FUNCTION(openssl_pkey_new)
#if PHP_OPENSSL_API_VERSION >= 0x30000
} else if ((data = zend_hash_str_find(Z_ARRVAL_P(args), "x25519", sizeof("x25519") - 1)) != NULL &&
Z_TYPE_P(data) == IS_ARRAY) {
php_openssl_pkey_object_curve_25519_448(return_value, EVP_PKEY_X25519, data);
php_openssl_pkey_object_curve_25519_448(return_value, "X25519", data);
return;
} else if ((data = zend_hash_str_find(Z_ARRVAL_P(args), "ed25519", sizeof("ed25519") - 1)) != NULL &&
Z_TYPE_P(data) == IS_ARRAY) {
php_openssl_pkey_object_curve_25519_448(return_value, EVP_PKEY_ED25519, data);
php_openssl_pkey_object_curve_25519_448(return_value, "ED25519", data);
return;
} else if ((data = zend_hash_str_find(Z_ARRVAL_P(args), "x448", sizeof("x448") - 1)) != NULL &&
Z_TYPE_P(data) == IS_ARRAY) {
php_openssl_pkey_object_curve_25519_448(return_value, EVP_PKEY_X448, data);
php_openssl_pkey_object_curve_25519_448(return_value, "X448", data);
return;
} else if ((data = zend_hash_str_find(Z_ARRVAL_P(args), "ed448", sizeof("ed448") - 1)) != NULL &&
Z_TYPE_P(data) == IS_ARRAY) {
php_openssl_pkey_object_curve_25519_448(return_value, EVP_PKEY_ED448, data);
php_openssl_pkey_object_curve_25519_448(return_value, "ED448", data);
return;
#endif
}
Expand Down
38 changes: 35 additions & 3 deletions ext/openssl/openssl_backend_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -1429,7 +1429,7 @@ EVP_PKEY *php_openssl_pkey_from_zval(

zend_string *php_openssl_pkey_derive(EVP_PKEY *key, EVP_PKEY *peer_key, size_t key_size)
{
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(key, NULL);
EVP_PKEY_CTX *ctx = php_openssl_pkey_new_from_pkey(key);
if (!ctx) {
return NULL;
}
Expand Down Expand Up @@ -1487,6 +1487,37 @@ int php_openssl_get_evp_pkey_type(int key_type) {
}
}

const char *php_openssl_get_evp_pkey_name(int key_type) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are there any drawbacks to making it static?

switch (key_type) {
case OPENSSL_KEYTYPE_RSA:
return "RSA";
#if !defined(OPENSSL_NO_DSA)
case OPENSSL_KEYTYPE_DSA:
return "DSA";
#endif
#if !defined(NO_DH)
case OPENSSL_KEYTYPE_DH:
return "DH";
#endif
#ifdef HAVE_EVP_PKEY_EC
case OPENSSL_KEYTYPE_EC:
return "EC";
#endif
#if PHP_OPENSSL_API_VERSION >= 0x30000
case OPENSSL_KEYTYPE_X25519:
return "X25519";
case OPENSSL_KEYTYPE_ED25519:
return "ED25519";
case OPENSSL_KEYTYPE_X448:
return "X448";
case OPENSSL_KEYTYPE_ED448:
return "ED448";
#endif
default:
return "";
}
}

EVP_PKEY * php_openssl_generate_private_key(struct php_x509_request * req)
{
if (req->priv_key_bits < MIN_KEY_LENGTH) {
Expand All @@ -1500,14 +1531,15 @@ EVP_PKEY * php_openssl_generate_private_key(struct php_x509_request * req)
php_error_docref(NULL, E_WARNING, "Unsupported private key type");
return NULL;
}
const char *name = php_openssl_get_evp_pkey_name(req->priv_key_type);

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

EVP_PKEY *key = NULL;
EVP_PKEY *params = NULL;
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(type, NULL);
EVP_PKEY_CTX *ctx = php_openssl_pkey_new_from_name(name, type);
if (!ctx) {
php_openssl_store_errors();
goto cleanup;
Expand Down Expand Up @@ -1569,7 +1601,7 @@ EVP_PKEY * php_openssl_generate_private_key(struct php_x509_request * req)
}

EVP_PKEY_CTX_free(ctx);
ctx = EVP_PKEY_CTX_new(params, NULL);
ctx = php_openssl_pkey_new_from_pkey(params);
if (!ctx) {
php_openssl_store_errors();
goto cleanup;
Expand Down
10 changes: 10 additions & 0 deletions ext/openssl/openssl_backend_v1.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,16 @@ void php_openssl_backend_shutdown(void)
#endif
}

EVP_PKEY_CTX *php_openssl_pkey_new_from_name(const char *name, int id)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't name unnecessary?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be fair, I think he had to for the sake of ssl apis inter-compatibility (look at the version for openssl 3.x), maybe just adding (void)name; should do.

{
return EVP_PKEY_CTX_new_id(id, NULL);
}

EVP_PKEY_CTX *php_openssl_pkey_new_from_pkey(EVP_PKEY *pkey)
{
return EVP_PKEY_CTX_new(pkey, NULL);
}

static bool php_openssl_pkey_init_rsa_data(RSA *rsa, zval *data)
{
BIGNUM *n, *e, *d, *p, *q, *dmp1, *dmq1, *iqmp;
Expand Down
48 changes: 39 additions & 9 deletions ext/openssl/openssl_backend_v3.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,47 @@
#include <openssl/param_build.h>
#include <openssl/provider.h>

ZEND_EXTERN_MODULE_GLOBALS(openssl)

void php_openssl_backend_shutdown(void)
{
(void) 0;
}

void php_openssl_backend_init_libctx(OSSL_LIB_CTX **plibctx, char **ppropq)
{
/* The return value is not checked because we cannot reasonable fail in GINIT so using NULL
* (default context) is probably better. */
*plibctx = OSSL_LIB_CTX_new();
*ppropq = NULL;
}

void php_openssl_backend_destroy_libctx(OSSL_LIB_CTX *libctx, char *propq)
{
if (libctx != NULL) {
OSSL_LIB_CTX_free(libctx);
}
if (propq != NULL) {
free(propq);
}
}
Comment on lines +32 to +48
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it okay to omit #if PHP_OPENSSL_API_VERSION >= 0x30000?


EVP_PKEY_CTX *php_openssl_pkey_new_from_name(const char *name, int id)
{
return EVP_PKEY_CTX_new_from_name(OPENSSL_G(libctx), name, OPENSSL_G(propq));
}

EVP_PKEY_CTX *php_openssl_pkey_new_from_pkey(EVP_PKEY *pkey)
{
return EVP_PKEY_CTX_new_from_pkey(OPENSSL_G(libctx), pkey, OPENSSL_G(propq));
}

EVP_PKEY *php_openssl_pkey_init_rsa(zval *data)
{
BIGNUM *n = NULL, *e = NULL, *d = NULL, *p = NULL, *q = NULL;
BIGNUM *dmp1 = NULL, *dmq1 = NULL, *iqmp = NULL;
EVP_PKEY *pkey = NULL;
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
EVP_PKEY_CTX *ctx = php_openssl_pkey_new_from_name("RSA", EVP_PKEY_RSA);
OSSL_PARAM *params = NULL;
OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new();

Expand Down Expand Up @@ -100,7 +130,7 @@ EVP_PKEY *php_openssl_pkey_init_dsa(zval *data, bool *is_private)
{
BIGNUM *p = NULL, *q = NULL, *g = NULL, *priv_key = NULL, *pub_key = NULL;
EVP_PKEY *param_key = NULL, *pkey = NULL;
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_DSA, NULL);
EVP_PKEY_CTX *ctx = php_openssl_pkey_new_from_name("DSA", EVP_PKEY_DSA);
OSSL_PARAM *params = NULL;
OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new();

Expand Down Expand Up @@ -144,7 +174,7 @@ EVP_PKEY *php_openssl_pkey_init_dsa(zval *data, bool *is_private)
} else {
*is_private = true;
EVP_PKEY_CTX_free(ctx);
ctx = EVP_PKEY_CTX_new(param_key, NULL);
ctx = php_openssl_pkey_new_from_pkey(param_key);
if (EVP_PKEY_keygen_init(ctx) <= 0 || EVP_PKEY_keygen(ctx, &pkey) <= 0) {
goto cleanup;
}
Expand All @@ -168,7 +198,7 @@ EVP_PKEY *php_openssl_pkey_init_dh(zval *data, bool *is_private)
{
BIGNUM *p = NULL, *q = NULL, *g = NULL, *priv_key = NULL, *pub_key = NULL;
EVP_PKEY *param_key = NULL, *pkey = NULL;
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_DH, NULL);
EVP_PKEY_CTX *ctx = php_openssl_pkey_new_from_name("DH", EVP_PKEY_DH);
OSSL_PARAM *params = NULL;
OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new();

Expand Down Expand Up @@ -219,7 +249,7 @@ EVP_PKEY *php_openssl_pkey_init_dh(zval *data, bool *is_private)
} else {
*is_private = true;
EVP_PKEY_CTX_free(ctx);
ctx = EVP_PKEY_CTX_new(param_key, NULL);
ctx = php_openssl_pkey_new_from_pkey(param_key);
if (EVP_PKEY_keygen_init(ctx) <= 0 || EVP_PKEY_keygen(ctx, &pkey) <= 0) {
goto cleanup;
}
Expand Down Expand Up @@ -250,7 +280,7 @@ EVP_PKEY *php_openssl_pkey_init_ec(zval *data, bool *is_private) {
unsigned char *point_q_buf = NULL;
EC_GROUP *group = NULL;
EVP_PKEY *param_key = NULL, *pkey = NULL;
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL);
EVP_PKEY_CTX *ctx = php_openssl_pkey_new_from_name("EC", EVP_PKEY_EC);
BN_CTX *bctx = BN_CTX_new();
OSSL_PARAM *params = NULL;
OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new();
Expand All @@ -269,7 +299,7 @@ EVP_PKEY *php_openssl_pkey_init_ec(zval *data, bool *is_private) {
goto cleanup;
}

if (!(group = EC_GROUP_new_by_curve_name(nid))) {
if (!(group = EC_GROUP_new_by_curve_name_ex(OPENSSL_G(libctx), OPENSSL_G(propq), nid))) {
goto cleanup;
}

Expand Down Expand Up @@ -438,7 +468,7 @@ EVP_PKEY *php_openssl_pkey_init_ec(zval *data, bool *is_private) {
}
#endif

void php_openssl_pkey_object_curve_25519_448(zval *return_value, int key_type, zval *data) {
void php_openssl_pkey_object_curve_25519_448(zval *return_value, const char *name, zval *data) {
EVP_PKEY *pkey = NULL;
EVP_PKEY_CTX *ctx = NULL;
OSSL_PARAM *params = NULL;
Expand Down Expand Up @@ -466,7 +496,7 @@ void php_openssl_pkey_object_curve_25519_448(zval *return_value, int key_type, z
}

params = OSSL_PARAM_BLD_to_param(bld);
ctx = EVP_PKEY_CTX_new_id(key_type, NULL);
ctx = php_openssl_pkey_new_from_name(name, 0);
if (!params || !ctx) {
goto cleanup;
}
Expand Down
4 changes: 4 additions & 0 deletions ext/openssl/php_openssl.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ struct php_openssl_errors {
ZEND_BEGIN_MODULE_GLOBALS(openssl)
struct php_openssl_errors *errors;
struct php_openssl_errors *errors_mark;
#if PHP_OPENSSL_API_VERSION >= 0x30000
OSSL_LIB_CTX *libctx;
char *propq;
#endif
ZEND_END_MODULE_GLOBALS(openssl)

#define OPENSSL_G(v) ZEND_MODULE_GLOBALS_ACCESSOR(openssl, v)
Expand Down
12 changes: 10 additions & 2 deletions ext/openssl/php_openssl_backend.h
Original file line number Diff line number Diff line change
Expand Up @@ -225,8 +225,15 @@ EVP_MD * php_openssl_get_evp_md_from_algo(zend_long algo);
const EVP_CIPHER * php_openssl_get_evp_cipher_from_algo(zend_long algo);

void php_openssl_backend_init(void);
void php_openssl_backend_init_common(void);
void php_openssl_backend_gshutdown(void);
void php_openssl_backend_shutdown(void);

#if PHP_OPENSSL_API_VERSION >= 0x30000
void php_openssl_backend_init_libctx(OSSL_LIB_CTX **plibctx, char **ppropq);
void php_openssl_backend_destroy_libctx(OSSL_LIB_CTX *libctx, char *propq);
#endif

const char *php_openssl_get_conf_filename(void);

void php_openssl_set_cert_locations(zval *return_value);
Expand Down Expand Up @@ -296,15 +303,16 @@ void php_openssl_add_bn_to_array(zval *ary, const BIGNUM *bn, const char *name);
} \
} while (0);

EVP_PKEY_CTX *php_openssl_pkey_new_from_name(const char *name, int id);
EVP_PKEY_CTX *php_openssl_pkey_new_from_pkey(EVP_PKEY *pkey);

EVP_PKEY *php_openssl_pkey_init_rsa(zval *data);
EVP_PKEY *php_openssl_pkey_init_dsa(zval *data, bool *is_private);
BIGNUM *php_openssl_dh_pub_from_priv(BIGNUM *priv_key, BIGNUM *g, BIGNUM *p);
EVP_PKEY *php_openssl_pkey_init_dh(zval *data, bool *is_private);
EVP_PKEY *php_openssl_pkey_init_ec(zval *data, bool *is_private);
void php_openssl_pkey_object_curve_25519_448(zval *return_value, int key_type, zval *data);
#if PHP_OPENSSL_API_VERSION >= 0x30000
void php_openssl_pkey_object_curve_25519_448(zval *return_value, int key_type, zval *data);
void php_openssl_pkey_object_curve_25519_448(zval *return_value, const char *name, zval *data);
#endif
zend_long php_openssl_pkey_get_details(zval *return_value, EVP_PKEY *pkey);

Expand Down
Loading