@@ -3819,8 +3819,8 @@ static bool php_openssl_pkey_init_and_assign_rsa(EVP_PKEY *pkey, RSA *rsa, zval
38193819 return 1 ;
38203820}
38213821
3822- /* {{{ php_openssl_pkey_init_dsa */
3823- static bool php_openssl_pkey_init_dsa (DSA * dsa , zval * data , bool * is_private )
3822+ #if PHP_OPENSSL_API_VERSION < 0x30000
3823+ static bool php_openssl_pkey_init_legacy_dsa (DSA * dsa , zval * data , bool * is_private )
38243824{
38253825 BIGNUM * p , * q , * g , * priv_key , * pub_key ;
38263826 const BIGNUM * priv_key_const , * pub_key_const ;
@@ -3853,9 +3853,102 @@ static bool php_openssl_pkey_init_dsa(DSA *dsa, zval *data, bool *is_private)
38533853 return 0 ;
38543854 }
38553855 /* all good */
3856+ * is_private = true;
38563857 return 1 ;
38573858}
3858- /* }}} */
3859+ #endif
3860+
3861+ static EVP_PKEY * php_openssl_pkey_init_dsa (zval * data , bool * is_private )
3862+ {
3863+ #if PHP_OPENSSL_API_VERSION >= 0x30000
3864+ BIGNUM * p = NULL , * q = NULL , * g = NULL , * priv_key = NULL , * pub_key = NULL ;
3865+ EVP_PKEY * param_key = NULL , * pkey = NULL ;
3866+ EVP_PKEY_CTX * ctx = EVP_PKEY_CTX_new_id (EVP_PKEY_DSA , NULL );
3867+ OSSL_PARAM * params = NULL ;
3868+ OSSL_PARAM_BLD * bld = OSSL_PARAM_BLD_new ();
3869+
3870+ OPENSSL_PKEY_SET_BN (data , p );
3871+ OPENSSL_PKEY_SET_BN (data , q );
3872+ OPENSSL_PKEY_SET_BN (data , g );
3873+ OPENSSL_PKEY_SET_BN (data , priv_key );
3874+ OPENSSL_PKEY_SET_BN (data , pub_key );
3875+
3876+ if (!ctx || !bld || !p || !q || !g ) {
3877+ goto cleanup ;
3878+ }
3879+
3880+ OSSL_PARAM_BLD_push_BN (bld , OSSL_PKEY_PARAM_FFC_P , p );
3881+ OSSL_PARAM_BLD_push_BN (bld , OSSL_PKEY_PARAM_FFC_Q , q );
3882+ OSSL_PARAM_BLD_push_BN (bld , OSSL_PKEY_PARAM_FFC_G , g );
3883+ // TODO: We silently ignore priv_key if pub_key is not given, unlike in the DH case.
3884+ if (pub_key ) {
3885+ OSSL_PARAM_BLD_push_BN (bld , OSSL_PKEY_PARAM_PUB_KEY , pub_key );
3886+ if (priv_key ) {
3887+ OSSL_PARAM_BLD_push_BN (bld , OSSL_PKEY_PARAM_PRIV_KEY , priv_key );
3888+ }
3889+ }
3890+
3891+ params = OSSL_PARAM_BLD_to_param (bld );
3892+ if (!params ) {
3893+ goto cleanup ;
3894+ }
3895+
3896+ if (EVP_PKEY_fromdata_init (ctx ) <= 0 ||
3897+ EVP_PKEY_fromdata (ctx , & param_key , EVP_PKEY_KEYPAIR , params ) <= 0 ) {
3898+ goto cleanup ;
3899+ }
3900+
3901+ if (pub_key ) {
3902+ * is_private = priv_key != NULL ;
3903+ EVP_PKEY_up_ref (param_key );
3904+ pkey = param_key ;
3905+ } else {
3906+ * is_private = true;
3907+ PHP_OPENSSL_RAND_ADD_TIME ();
3908+ EVP_PKEY_CTX_free (ctx );
3909+ ctx = EVP_PKEY_CTX_new (param_key , NULL );
3910+ if (EVP_PKEY_keygen_init (ctx ) <= 0 || EVP_PKEY_keygen (ctx , & pkey ) <= 0 ) {
3911+ goto cleanup ;
3912+ }
3913+ }
3914+
3915+ cleanup :
3916+ php_openssl_store_errors ();
3917+ EVP_PKEY_free (param_key );
3918+ EVP_PKEY_CTX_free (ctx );
3919+ OSSL_PARAM_free (params );
3920+ OSSL_PARAM_BLD_free (bld );
3921+ BN_free (p );
3922+ BN_free (q );
3923+ BN_free (g );
3924+ BN_free (priv_key );
3925+ BN_free (pub_key );
3926+ return pkey ;
3927+ #else
3928+ EVP_PKEY * pkey = EVP_PKEY_new ();
3929+ if (!pkey ) {
3930+ php_openssl_store_errors ();
3931+ return NULL ;
3932+ }
3933+
3934+ DSA * dsa = DSA_new ();
3935+ if (!dsa ) {
3936+ php_openssl_store_errors ();
3937+ EVP_PKEY_free (pkey );
3938+ return NULL ;
3939+ }
3940+
3941+ if (!php_openssl_pkey_init_legacy_dsa (dsa , data , is_private )
3942+ || !EVP_PKEY_assign_DSA (pkey , dsa )) {
3943+ php_openssl_store_errors ();
3944+ EVP_PKEY_free (pkey );
3945+ DSA_free (dsa );
3946+ return NULL ;
3947+ }
3948+
3949+ return pkey ;
3950+ #endif
3951+ }
38593952
38603953/* {{{ php_openssl_dh_pub_from_priv */
38613954static BIGNUM * php_openssl_dh_pub_from_priv (BIGNUM * priv_key , BIGNUM * g , BIGNUM * p )
@@ -4070,28 +4163,13 @@ PHP_FUNCTION(openssl_pkey_new)
40704163 RETURN_FALSE ;
40714164 } else if ((data = zend_hash_str_find (Z_ARRVAL_P (args ), "dsa" , sizeof ("dsa" ) - 1 )) != NULL &&
40724165 Z_TYPE_P (data ) == IS_ARRAY ) {
4073- pkey = EVP_PKEY_new ();
4074- if (pkey ) {
4075- DSA * dsa = DSA_new ();
4076- if (dsa ) {
4077- bool is_private ;
4078- if (php_openssl_pkey_init_dsa (dsa , data , & is_private )) {
4079- if (EVP_PKEY_assign_DSA (pkey , dsa )) {
4080- php_openssl_pkey_object_init (return_value , pkey , is_private );
4081- return ;
4082- } else {
4083- php_openssl_store_errors ();
4084- }
4085- }
4086- DSA_free (dsa );
4087- } else {
4088- php_openssl_store_errors ();
4089- }
4090- EVP_PKEY_free (pkey );
4091- } else {
4092- php_openssl_store_errors ();
4166+ bool is_private ;
4167+ pkey = php_openssl_pkey_init_dsa (data , & is_private );
4168+ if (!pkey ) {
4169+ RETURN_FALSE ;
40934170 }
4094- RETURN_FALSE ;
4171+ php_openssl_pkey_object_init (return_value , pkey , is_private );
4172+ return ;
40954173 } else if ((data = zend_hash_str_find (Z_ARRVAL_P (args ), "dh" , sizeof ("dh" ) - 1 )) != NULL &&
40964174 Z_TYPE_P (data ) == IS_ARRAY ) {
40974175 bool is_private ;
0 commit comments