Skip to content

Commit f9e701c

Browse files
committed
Use param API for creating EC keys
Rather than the deprecated low level APIs.
1 parent 2466986 commit f9e701c

File tree

1 file changed

+96
-0
lines changed

1 file changed

+96
-0
lines changed

ext/openssl/openssl.c

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4136,6 +4136,7 @@ static EVP_PKEY *php_openssl_pkey_init_dh(zval *data, bool *is_private)
41364136
}
41374137

41384138
#ifdef HAVE_EVP_PKEY_EC
4139+
#if PHP_OPENSSL_API_VERSION < 0x30000
41394140
static bool php_openssl_pkey_init_legacy_ec(EC_KEY *eckey, zval *data, bool *is_private) {
41404141
EC_GROUP *group = NULL;
41414142
EC_POINT *pnt = NULL;
@@ -4213,6 +4214,7 @@ static bool php_openssl_pkey_init_legacy_ec(EC_KEY *eckey, zval *data, bool *is_
42134214
}
42144215

42154216
if (!EC_KEY_check_key(eckey)) {
4217+
*is_private = true;
42164218
PHP_OPENSSL_RAND_ADD_TIME();
42174219
EC_KEY_generate_key(eckey);
42184220
php_openssl_store_errors();
@@ -4229,8 +4231,101 @@ static bool php_openssl_pkey_init_legacy_ec(EC_KEY *eckey, zval *data, bool *is_
42294231
EC_GROUP_free(group);
42304232
return false;
42314233
}
4234+
#endif
42324235

42334236
static EVP_PKEY *php_openssl_pkey_init_ec(zval *data, bool *is_private) {
4237+
#if PHP_OPENSSL_API_VERSION >= 0x30000
4238+
BIGNUM *d = NULL, *x = NULL, *y = NULL;
4239+
EC_GROUP *group = NULL;
4240+
EC_POINT *pnt = NULL;
4241+
char *pnt_oct = NULL;
4242+
EVP_PKEY *param_key = NULL, *pkey = NULL;
4243+
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL);
4244+
OSSL_PARAM *params = NULL;
4245+
OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new();
4246+
zval *curve_name_zv = zend_hash_str_find(Z_ARRVAL_P(data), "curve_name", sizeof("curve_name") - 1);
4247+
4248+
OPENSSL_PKEY_SET_BN(data, d);
4249+
OPENSSL_PKEY_SET_BN(data, x);
4250+
OPENSSL_PKEY_SET_BN(data, y);
4251+
4252+
if (!ctx || !bld || !curve_name_zv || Z_TYPE_P(curve_name_zv) != IS_STRING) {
4253+
goto cleanup;
4254+
}
4255+
4256+
int nid = OBJ_sn2nid(Z_STRVAL_P(curve_name_zv));
4257+
group = EC_GROUP_new_by_curve_name(nid);
4258+
if (!group) {
4259+
php_error_docref(NULL, E_WARNING, "Unknown curve name");
4260+
goto cleanup;
4261+
}
4262+
4263+
OSSL_PARAM_BLD_push_utf8_string(
4264+
bld, OSSL_PKEY_PARAM_GROUP_NAME, Z_STRVAL_P(curve_name_zv), Z_STRLEN_P(curve_name_zv));
4265+
4266+
if (d) {
4267+
OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_PRIV_KEY, d);
4268+
4269+
pnt = EC_POINT_new(group);
4270+
if (!pnt || !EC_POINT_mul(group, pnt, d, NULL, NULL, NULL)) {
4271+
goto cleanup;
4272+
}
4273+
} else if (x && y) {
4274+
/* OpenSSL does not allow setting EC_PUB_X/EC_PUB_Y, so convert to encoded format. */
4275+
pnt = EC_POINT_new(group);
4276+
if (!pnt || !EC_POINT_set_affine_coordinates(group, pnt, x, y, NULL)) {
4277+
goto cleanup;
4278+
}
4279+
}
4280+
4281+
if (pnt) {
4282+
size_t pnt_oct_len =
4283+
EC_POINT_point2buf(group, pnt, POINT_CONVERSION_COMPRESSED, &pnt_oct, NULL);
4284+
if (!pnt_oct_len) {
4285+
goto cleanup;
4286+
}
4287+
4288+
OSSL_PARAM_BLD_push_octet_string(bld, OSSL_PKEY_PARAM_PUB_KEY, pnt_oct, pnt_oct_len);
4289+
}
4290+
4291+
params = OSSL_PARAM_BLD_to_param(bld);
4292+
if (!params) {
4293+
goto cleanup;
4294+
}
4295+
4296+
if (EVP_PKEY_fromdata_init(ctx) <= 0 ||
4297+
EVP_PKEY_fromdata(ctx, &param_key, EVP_PKEY_KEYPAIR, params) <= 0) {
4298+
goto cleanup;
4299+
}
4300+
4301+
EVP_PKEY_CTX_free(ctx);
4302+
ctx = EVP_PKEY_CTX_new(param_key, NULL);
4303+
if (EVP_PKEY_check(ctx)) {
4304+
*is_private = d != NULL;
4305+
EVP_PKEY_up_ref(param_key);
4306+
pkey = param_key;
4307+
} else {
4308+
*is_private = true;
4309+
PHP_OPENSSL_RAND_ADD_TIME();
4310+
if (EVP_PKEY_keygen_init(ctx) <= 0 || EVP_PKEY_keygen(ctx, &pkey) <= 0) {
4311+
goto cleanup;
4312+
}
4313+
}
4314+
4315+
cleanup:
4316+
php_openssl_store_errors();
4317+
EVP_PKEY_free(param_key);
4318+
EVP_PKEY_CTX_free(ctx);
4319+
OSSL_PARAM_free(params);
4320+
OSSL_PARAM_BLD_free(bld);
4321+
EC_POINT_free(pnt);
4322+
EC_GROUP_free(group);
4323+
OPENSSL_free(pnt_oct);
4324+
BN_free(d);
4325+
BN_free(x);
4326+
BN_free(y);
4327+
return pkey;
4328+
#else
42344329
EVP_PKEY *pkey = EVP_PKEY_new();
42354330
if (!pkey) {
42364331
php_openssl_store_errors();
@@ -4252,6 +4347,7 @@ static EVP_PKEY *php_openssl_pkey_init_ec(zval *data, bool *is_private) {
42524347
}
42534348

42544349
return pkey;
4350+
#endif
42554351
}
42564352
#endif
42574353

0 commit comments

Comments
 (0)