Skip to content

Commit 3724b49

Browse files
committed
Use param API to create RSA key
Instead of deprecated low-level API. A caveat here is that when using the high-level API, OpenSSL 3 requires that if the prime factors are set, the CRT parameters are also set. See openssl/openssl#16271. As such, add CRT parameters to the manual construction test. This fixes the last deprecation warnings in openssl.c, but there are more elsewhere.
1 parent ff2a39e commit 3724b49

File tree

2 files changed

+116
-21
lines changed

2 files changed

+116
-21
lines changed

ext/openssl/openssl.c

Lines changed: 100 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3789,8 +3789,8 @@ static void php_openssl_add_bn_to_array(zval *ary, const BIGNUM *bn, const char
37893789
} \
37903790
} while (0);
37913791

3792-
/* {{{ php_openssl_pkey_init_rsa */
3793-
static bool php_openssl_pkey_init_and_assign_rsa(EVP_PKEY *pkey, RSA *rsa, zval *data)
3792+
#if PHP_OPENSSL_API_VERSION < 0x30000
3793+
static bool php_openssl_pkey_init_legacy_rsa(RSA *rsa, zval *data)
37943794
{
37953795
BIGNUM *n, *e, *d, *p, *q, *dmp1, *dmq1, *iqmp;
37963796

@@ -3814,12 +3814,102 @@ static bool php_openssl_pkey_init_and_assign_rsa(EVP_PKEY *pkey, RSA *rsa, zval
38143814
return 0;
38153815
}
38163816

3817-
if (!EVP_PKEY_assign_RSA(pkey, rsa)) {
3817+
return 1;
3818+
}
3819+
#endif
3820+
3821+
static EVP_PKEY *php_openssl_pkey_init_rsa(zval *data)
3822+
{
3823+
#if PHP_OPENSSL_API_VERSION >= 0x30000
3824+
BIGNUM *n = NULL, *e = NULL, *d = NULL, *p = NULL, *q = NULL;
3825+
BIGNUM *dmp1 = NULL, *dmq1 = NULL, *iqmp = NULL;
3826+
EVP_PKEY *pkey = NULL;
3827+
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
3828+
OSSL_PARAM *params = NULL;
3829+
OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new();
3830+
3831+
OPENSSL_PKEY_SET_BN(data, n);
3832+
OPENSSL_PKEY_SET_BN(data, e);
3833+
OPENSSL_PKEY_SET_BN(data, d);
3834+
OPENSSL_PKEY_SET_BN(data, p);
3835+
OPENSSL_PKEY_SET_BN(data, q);
3836+
OPENSSL_PKEY_SET_BN(data, dmp1);
3837+
OPENSSL_PKEY_SET_BN(data, dmq1);
3838+
OPENSSL_PKEY_SET_BN(data, iqmp);
3839+
3840+
if (!ctx || !bld || !n || !d) {
3841+
goto cleanup;
3842+
}
3843+
3844+
OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_N, n);
3845+
OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_D, d);
3846+
if (e) {
3847+
OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_E, e);
3848+
}
3849+
if (p) {
3850+
OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_FACTOR1, p);
3851+
}
3852+
if (q) {
3853+
OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_FACTOR2, q);
3854+
}
3855+
if (dmp1) {
3856+
OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_EXPONENT1, dmp1);
3857+
}
3858+
if (dmq1) {
3859+
OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_EXPONENT2, dmq1);
3860+
}
3861+
if (iqmp) {
3862+
OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_COEFFICIENT1, iqmp);
3863+
}
3864+
3865+
params = OSSL_PARAM_BLD_to_param(bld);
3866+
if (!params) {
3867+
goto cleanup;
3868+
}
3869+
3870+
if (EVP_PKEY_fromdata_init(ctx) <= 0 ||
3871+
EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_KEYPAIR, params) <= 0) {
3872+
goto cleanup;
3873+
}
3874+
3875+
cleanup:
3876+
php_openssl_store_errors();
3877+
EVP_PKEY_CTX_free(ctx);
3878+
OSSL_PARAM_free(params);
3879+
OSSL_PARAM_BLD_free(bld);
3880+
BN_free(n);
3881+
BN_free(e);
3882+
BN_free(d);
3883+
BN_free(p);
3884+
BN_free(q);
3885+
BN_free(dmp1);
3886+
BN_free(dmq1);
3887+
BN_free(iqmp);
3888+
return pkey;
3889+
#else
3890+
EVP_PKEY *pkey = EVP_PKEY_new();
3891+
if (!pkey) {
38183892
php_openssl_store_errors();
3819-
return 0;
3893+
return NULL;
38203894
}
38213895

3822-
return 1;
3896+
RSA *rsa = RSA_new();
3897+
if (!rsa) {
3898+
php_openssl_store_errors();
3899+
EVP_PKEY_free(pkey);
3900+
return NULL;
3901+
}
3902+
3903+
if (!php_openssl_pkey_init_legacy_rsa(rsa, data)
3904+
|| !EVP_PKEY_assign_RSA(pkey, rsa)) {
3905+
php_openssl_store_errors();
3906+
EVP_PKEY_free(pkey);
3907+
RSA_free(rsa);
3908+
return NULL;
3909+
}
3910+
3911+
return pkey;
3912+
#endif
38233913
}
38243914

38253915
#if PHP_OPENSSL_API_VERSION < 0x30000
@@ -4363,23 +4453,12 @@ PHP_FUNCTION(openssl_pkey_new)
43634453

43644454
if ((data = zend_hash_str_find(Z_ARRVAL_P(args), "rsa", sizeof("rsa")-1)) != NULL &&
43654455
Z_TYPE_P(data) == IS_ARRAY) {
4366-
pkey = EVP_PKEY_new();
4367-
if (pkey) {
4368-
RSA *rsa = RSA_new();
4369-
if (rsa) {
4370-
if (php_openssl_pkey_init_and_assign_rsa(pkey, rsa, data)) {
4371-
php_openssl_pkey_object_init(return_value, pkey, /* is_private */ true);
4372-
return;
4373-
}
4374-
RSA_free(rsa);
4375-
} else {
4376-
php_openssl_store_errors();
4377-
}
4378-
EVP_PKEY_free(pkey);
4379-
} else {
4380-
php_openssl_store_errors();
4456+
pkey = php_openssl_pkey_init_rsa(data);
4457+
if (!pkey) {
4458+
RETURN_FALSE;
43814459
}
4382-
RETURN_FALSE;
4460+
php_openssl_pkey_object_init(return_value, pkey, /* is_private */ true);
4461+
return;
43834462
} else if ((data = zend_hash_str_find(Z_ARRVAL_P(args), "dsa", sizeof("dsa") - 1)) != NULL &&
43844463
Z_TYPE_P(data) == IS_ARRAY) {
43854464
bool is_private;

ext/openssl/tests/openssl_pkey_new_basic.phpt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,21 @@ $phex = "EECFAE81B1B9B3C908810B10A1B5600199EB9F44AEF4FDA493B81A9E3D84F632" .
2626
$qhex = "C97FB1F027F453F6341233EAAAD1D9353F6C42D08866B1D05A0F2035028B9D86" .
2727
"9840B41666B42E92EA0DA3B43204B5CFCE3352524D0416A5A441E700AF461503";
2828

29+
$dphex = "11";
30+
$dqhex = "11";
31+
$qinvhex = "b06c4fdabb6301198d265bdbae9423b380f271f73453885093077fcd39e2119f" .
32+
"c98632154f5883b167a967bf402b4e9e2e0f9656e698ea3666edfb25798039f7";
33+
2934
$rsa= openssl_pkey_new(array(
3035
'rsa' => array(
3136
'n' => hex2bin($nhex),
3237
'e' => hex2bin($ehex),
3338
'd' => hex2bin($dhex),
3439
'p' => hex2bin($phex),
3540
'q' => hex2bin($qhex),
41+
'dmp1' => hex2bin($dphex),
42+
'dmq1' => hex2bin($dqhex),
43+
'iqmp' => hex2bin($qinvhex),
3644
)
3745
));
3846
$details = openssl_pkey_get_details($rsa);
@@ -42,6 +50,10 @@ openssl_pkey_test_cmp($ehex, $rsa_details['e']);
4250
openssl_pkey_test_cmp($dhex, $rsa_details['d']);
4351
openssl_pkey_test_cmp($phex, $rsa_details['p']);
4452
openssl_pkey_test_cmp($qhex, $rsa_details['q']);
53+
openssl_pkey_test_cmp($dphex, $rsa_details['dmp1']);
54+
openssl_pkey_test_cmp($dqhex, $rsa_details['dmq1']);
55+
openssl_pkey_test_cmp($qinvhex, $rsa_details['iqmp']);
56+
echo "\n";
4557

4658
// DSA
4759
$phex = '00f8000ae45b2dacb47dd977d58b719d097bdf07cb2c17660ad898518c08' .
@@ -95,6 +107,10 @@ int(0)
95107
int(0)
96108
int(0)
97109
int(0)
110+
int(0)
111+
int(0)
112+
int(0)
113+
98114
int(0)
99115
int(0)
100116
int(0)

0 commit comments

Comments
 (0)