Skip to content

Commit 13313d9

Browse files
committed
Use EVP_PKEY APIs for key generation
Use high level API instead of deprecated low level API.
1 parent da2cd93 commit 13313d9

File tree

2 files changed

+101
-105
lines changed

2 files changed

+101
-105
lines changed

ext/openssl/openssl.c

Lines changed: 100 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -3631,132 +3631,130 @@ static EVP_PKEY *php_openssl_pkey_from_zval(zval *val, int public_key, char *pas
36313631
return key;
36323632
}
36333633

3634+
static int php_openssl_get_evp_pkey_type(int key_type) {
3635+
switch (key_type) {
3636+
case OPENSSL_KEYTYPE_RSA:
3637+
return EVP_PKEY_RSA;
3638+
#if !defined(NO_DSA)
3639+
case OPENSSL_KEYTYPE_DSA:
3640+
return EVP_PKEY_DSA;
3641+
#endif
3642+
#if !defined(NO_DH)
3643+
case OPENSSL_KEYTYPE_DH:
3644+
return EVP_PKEY_DH;
3645+
#endif
3646+
#ifdef HAVE_EVP_PKEY_EC
3647+
case OPENSSL_KEYTYPE_EC:
3648+
return EVP_PKEY_EC;
3649+
#endif
3650+
default:
3651+
return -1;
3652+
}
3653+
}
3654+
36343655
/* {{{ php_openssl_generate_private_key */
36353656
static EVP_PKEY * php_openssl_generate_private_key(struct php_x509_request * req)
36363657
{
3637-
char * randfile = NULL;
3638-
int egdsocket, seeded;
3639-
EVP_PKEY * return_val = NULL;
3640-
36413658
if (req->priv_key_bits < MIN_KEY_LENGTH) {
36423659
php_error_docref(NULL, E_WARNING, "Private key length must be at least %d bits, configured to %d",
36433660
MIN_KEY_LENGTH, req->priv_key_bits);
36443661
return NULL;
36453662
}
36463663

3647-
randfile = php_openssl_conf_get_string(req->req_config, req->section_name, "RANDFILE");
3664+
int type = php_openssl_get_evp_pkey_type(req->priv_key_type);
3665+
if (type < 0) {
3666+
php_error_docref(NULL, E_WARNING, "Unsupported private key type");
3667+
return NULL;
3668+
}
3669+
3670+
int egdsocket, seeded;
3671+
char *randfile = php_openssl_conf_get_string(req->req_config, req->section_name, "RANDFILE");
36483672
php_openssl_load_rand_file(randfile, &egdsocket, &seeded);
3673+
PHP_OPENSSL_RAND_ADD_TIME();
36493674

3650-
if ((req->priv_key = EVP_PKEY_new()) != NULL) {
3651-
switch(req->priv_key_type) {
3652-
case OPENSSL_KEYTYPE_RSA:
3653-
{
3654-
RSA* rsaparam;
3655-
BIGNUM *bne = (BIGNUM *)BN_new();
3656-
if (BN_set_word(bne, RSA_F4) != 1) {
3657-
BN_free(bne);
3658-
php_error_docref(NULL, E_WARNING, "Failed setting exponent");
3659-
return NULL;
3660-
}
3661-
rsaparam = RSA_new();
3662-
PHP_OPENSSL_RAND_ADD_TIME();
3663-
if (rsaparam == NULL || !RSA_generate_key_ex(rsaparam, req->priv_key_bits, bne, NULL)) {
3664-
php_openssl_store_errors();
3665-
RSA_free(rsaparam);
3666-
rsaparam = NULL;
3667-
}
3668-
BN_free(bne);
3669-
if (rsaparam && EVP_PKEY_assign_RSA(req->priv_key, rsaparam)) {
3670-
return_val = req->priv_key;
3671-
} else {
3672-
php_openssl_store_errors();
3673-
}
3674-
}
3675-
break;
3675+
EVP_PKEY *key = NULL;
3676+
EVP_PKEY *params = NULL;
3677+
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(type, NULL);
3678+
if (!ctx) {
3679+
php_openssl_store_errors();
3680+
goto cleanup;
3681+
}
3682+
3683+
if (type != EVP_PKEY_RSA) {
3684+
if (EVP_PKEY_paramgen_init(ctx) <= 0) {
3685+
php_openssl_store_errors();
3686+
goto cleanup;
3687+
}
3688+
3689+
switch (type) {
36763690
#if !defined(NO_DSA)
3677-
case OPENSSL_KEYTYPE_DSA:
3678-
PHP_OPENSSL_RAND_ADD_TIME();
3679-
{
3680-
DSA *dsaparam = DSA_new();
3681-
if (dsaparam && DSA_generate_parameters_ex(dsaparam, req->priv_key_bits, NULL, 0, NULL, NULL, NULL)) {
3682-
DSA_set_method(dsaparam, DSA_get_default_method());
3683-
if (DSA_generate_key(dsaparam)) {
3684-
if (EVP_PKEY_assign_DSA(req->priv_key, dsaparam)) {
3685-
return_val = req->priv_key;
3686-
} else {
3687-
php_openssl_store_errors();
3688-
}
3689-
} else {
3690-
php_openssl_store_errors();
3691-
DSA_free(dsaparam);
3692-
}
3693-
} else {
3694-
php_openssl_store_errors();
3695-
}
3696-
}
3697-
break;
3691+
case EVP_PKEY_DSA:
3692+
if (EVP_PKEY_CTX_set_dsa_paramgen_bits(ctx, req->priv_key_bits) <= 0) {
3693+
php_openssl_store_errors();
3694+
goto cleanup;
3695+
}
3696+
break;
36983697
#endif
36993698
#if !defined(NO_DH)
3700-
case OPENSSL_KEYTYPE_DH:
3701-
PHP_OPENSSL_RAND_ADD_TIME();
3702-
{
3703-
int codes = 0;
3704-
DH *dhparam = DH_new();
3705-
if (dhparam && DH_generate_parameters_ex(dhparam, req->priv_key_bits, 2, NULL)) {
3706-
DH_set_method(dhparam, DH_get_default_method());
3707-
if (DH_check(dhparam, &codes) && codes == 0 && DH_generate_key(dhparam)) {
3708-
if (EVP_PKEY_assign_DH(req->priv_key, dhparam)) {
3709-
return_val = req->priv_key;
3710-
} else {
3711-
php_openssl_store_errors();
3712-
}
3713-
} else {
3714-
php_openssl_store_errors();
3715-
DH_free(dhparam);
3716-
}
3717-
} else {
3718-
php_openssl_store_errors();
3719-
}
3720-
}
3721-
break;
3699+
case EVP_PKEY_DH:
3700+
if (EVP_PKEY_CTX_set_dh_paramgen_prime_len(ctx, req->priv_key_bits) <= 0) {
3701+
php_openssl_store_errors();
3702+
goto cleanup;
3703+
}
3704+
break;
37223705
#endif
37233706
#ifdef HAVE_EVP_PKEY_EC
3724-
case OPENSSL_KEYTYPE_EC:
3725-
{
3726-
EC_KEY *eckey;
3727-
if (req->curve_name == NID_undef) {
3728-
php_error_docref(NULL, E_WARNING, "Missing configuration value: \"curve_name\" not set");
3729-
return NULL;
3730-
}
3731-
eckey = EC_KEY_new_by_curve_name(req->curve_name);
3732-
if (eckey) {
3733-
EC_KEY_set_asn1_flag(eckey, OPENSSL_EC_NAMED_CURVE);
3734-
if (EC_KEY_generate_key(eckey) &&
3735-
EVP_PKEY_assign_EC_KEY(req->priv_key, eckey)) {
3736-
return_val = req->priv_key;
3737-
} else {
3738-
EC_KEY_free(eckey);
3739-
}
3740-
}
3741-
}
3742-
break;
3707+
case EVP_PKEY_EC:
3708+
if (req->curve_name == NID_undef) {
3709+
php_error_docref(NULL, E_WARNING, "Missing configuration value: \"curve_name\" not set");
3710+
goto cleanup;
3711+
}
3712+
3713+
if (EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, req->curve_name) <= 0 ||
3714+
EVP_PKEY_CTX_set_ec_param_enc(ctx, OPENSSL_EC_NAMED_CURVE) <= 0) {
3715+
php_openssl_store_errors();
3716+
goto cleanup;
3717+
}
3718+
break;
37433719
#endif
3744-
default:
3745-
php_error_docref(NULL, E_WARNING, "Unsupported private key type");
3720+
EMPTY_SWITCH_DEFAULT_CASE()
37463721
}
3747-
} else {
3722+
3723+
if (EVP_PKEY_paramgen(ctx, &params) <= 0) {
3724+
php_openssl_store_errors();
3725+
goto cleanup;
3726+
}
3727+
3728+
EVP_PKEY_CTX_free(ctx);
3729+
ctx = EVP_PKEY_CTX_new(params, NULL);
3730+
if (!ctx) {
3731+
php_openssl_store_errors();
3732+
goto cleanup;
3733+
}
3734+
}
3735+
3736+
if (EVP_PKEY_keygen_init(ctx) <= 0) {
37483737
php_openssl_store_errors();
3738+
goto cleanup;
37493739
}
37503740

3751-
php_openssl_write_rand_file(randfile, egdsocket, seeded);
3741+
if (type == EVP_PKEY_RSA && EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, req->priv_key_bits) <= 0) {
3742+
php_openssl_store_errors();
3743+
goto cleanup;
3744+
}
37523745

3753-
if (return_val == NULL) {
3754-
EVP_PKEY_free(req->priv_key);
3755-
req->priv_key = NULL;
3756-
return NULL;
3746+
if (EVP_PKEY_keygen(ctx, &key) <= 0) {
3747+
php_openssl_store_errors();
3748+
goto cleanup;
37573749
}
37583750

3759-
return return_val;
3751+
req->priv_key = key;
3752+
3753+
cleanup:
3754+
php_openssl_write_rand_file(randfile, egdsocket, seeded);
3755+
EVP_PKEY_free(params);
3756+
EVP_PKEY_CTX_free(ctx);
3757+
return key;
37603758
}
37613759
/* }}} */
37623760

ext/openssl/tests/bug80747.phpt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,7 @@ $conf = array(
1515
'private_key_bits' => 511,
1616
);
1717
var_dump(openssl_pkey_new($conf));
18-
while ($e = openssl_error_string()) {
19-
echo $e, "\n";
20-
}
18+
echo openssl_error_string(), "\n";
2119

2220
?>
2321
--EXPECTF--

0 commit comments

Comments
 (0)