@@ -4136,6 +4136,7 @@ static EVP_PKEY *php_openssl_pkey_init_dh(zval *data, bool *is_private)
4136
4136
}
4137
4137
4138
4138
#ifdef HAVE_EVP_PKEY_EC
4139
+ #if PHP_OPENSSL_API_VERSION < 0x30000
4139
4140
static bool php_openssl_pkey_init_legacy_ec (EC_KEY * eckey , zval * data , bool * is_private ) {
4140
4141
EC_GROUP * group = NULL ;
4141
4142
EC_POINT * pnt = NULL ;
@@ -4213,6 +4214,7 @@ static bool php_openssl_pkey_init_legacy_ec(EC_KEY *eckey, zval *data, bool *is_
4213
4214
}
4214
4215
4215
4216
if (!EC_KEY_check_key (eckey )) {
4217
+ * is_private = true;
4216
4218
PHP_OPENSSL_RAND_ADD_TIME ();
4217
4219
EC_KEY_generate_key (eckey );
4218
4220
php_openssl_store_errors ();
@@ -4229,8 +4231,101 @@ static bool php_openssl_pkey_init_legacy_ec(EC_KEY *eckey, zval *data, bool *is_
4229
4231
EC_GROUP_free (group );
4230
4232
return false;
4231
4233
}
4234
+ #endif
4232
4235
4233
4236
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
4234
4329
EVP_PKEY * pkey = EVP_PKEY_new ();
4235
4330
if (!pkey ) {
4236
4331
php_openssl_store_errors ();
@@ -4252,6 +4347,7 @@ static EVP_PKEY *php_openssl_pkey_init_ec(zval *data, bool *is_private) {
4252
4347
}
4253
4348
4254
4349
return pkey ;
4350
+ #endif
4255
4351
}
4256
4352
#endif
4257
4353
0 commit comments