@@ -121,7 +121,13 @@ enum php_openssl_key_type {
121
121
OPENSSL_KEYTYPE_DH ,
122
122
OPENSSL_KEYTYPE_DEFAULT = OPENSSL_KEYTYPE_RSA ,
123
123
#ifdef HAVE_EVP_PKEY_EC
124
- OPENSSL_KEYTYPE_EC = OPENSSL_KEYTYPE_DH + 1
124
+ OPENSSL_KEYTYPE_EC = OPENSSL_KEYTYPE_DH + 1 ,
125
+ #endif
126
+ #if PHP_OPENSSL_API_VERSION >= 0x30000
127
+ OPENSSL_KEYTYPE_X25519 = OPENSSL_KEYTYPE_DH + 2 ,
128
+ OPENSSL_KEYTYPE_ED25519 = OPENSSL_KEYTYPE_DH + 3 ,
129
+ OPENSSL_KEYTYPE_X448 = OPENSSL_KEYTYPE_DH + 4 ,
130
+ OPENSSL_KEYTYPE_ED448 = OPENSSL_KEYTYPE_DH + 5 ,
125
131
#endif
126
132
};
127
133
@@ -1012,7 +1018,11 @@ static int php_openssl_parse_config(struct php_x509_request * req, zval * option
1012
1018
req -> digest_name = php_openssl_conf_get_string (req -> req_config , req -> section_name , "default_md" );
1013
1019
}
1014
1020
if (req -> digest_name != NULL ) {
1015
- req -> digest = req -> md_alg = EVP_get_digestbyname (req -> digest_name );
1021
+ if (strcmp (req -> digest_name , "null" ) == 0 ) {
1022
+ req -> digest = req -> md_alg = EVP_md_null ();
1023
+ } else {
1024
+ req -> digest = req -> md_alg = EVP_get_digestbyname (req -> digest_name );
1025
+ }
1016
1026
}
1017
1027
if (req -> md_alg == NULL ) {
1018
1028
req -> md_alg = req -> digest = EVP_sha1 ();
@@ -3737,6 +3747,16 @@ static int php_openssl_get_evp_pkey_type(int key_type) {
3737
3747
#ifdef HAVE_EVP_PKEY_EC
3738
3748
case OPENSSL_KEYTYPE_EC :
3739
3749
return EVP_PKEY_EC ;
3750
+ #endif
3751
+ #if PHP_OPENSSL_API_VERSION >= 0x30000
3752
+ case OPENSSL_KEYTYPE_X25519 :
3753
+ return EVP_PKEY_X25519 ;
3754
+ case OPENSSL_KEYTYPE_ED25519 :
3755
+ return EVP_PKEY_ED25519 ;
3756
+ case OPENSSL_KEYTYPE_X448 :
3757
+ return EVP_PKEY_X448 ;
3758
+ case OPENSSL_KEYTYPE_ED448 :
3759
+ return EVP_PKEY_ED448 ;
3740
3760
#endif
3741
3761
default :
3742
3762
return -1 ;
@@ -3807,6 +3827,16 @@ static EVP_PKEY * php_openssl_generate_private_key(struct php_x509_request * req
3807
3827
goto cleanup ;
3808
3828
}
3809
3829
break ;
3830
+ #endif
3831
+ #if PHP_OPENSSL_API_VERSION >= 0x30000
3832
+ case EVP_PKEY_X25519 :
3833
+ break ;
3834
+ case EVP_PKEY_ED25519 :
3835
+ break ;
3836
+ case EVP_PKEY_X448 :
3837
+ break ;
3838
+ case EVP_PKEY_ED448 :
3839
+ break ;
3810
3840
#endif
3811
3841
EMPTY_SWITCH_DEFAULT_CASE ()
3812
3842
}
@@ -4473,6 +4503,10 @@ static EVP_PKEY *php_openssl_pkey_init_ec(zval *data, bool *is_private) {
4473
4503
4474
4504
* is_private = false;
4475
4505
4506
+ if (!ctx || !bld || !bctx ) {
4507
+ goto cleanup ;
4508
+ }
4509
+
4476
4510
zval * curve_name_zv = zend_hash_str_find (Z_ARRVAL_P (data ), "curve_name" , sizeof ("curve_name" ) - 1 );
4477
4511
if (curve_name_zv && Z_TYPE_P (curve_name_zv ) == IS_STRING && Z_STRLEN_P (curve_name_zv ) > 0 ) {
4478
4512
nid = OBJ_sn2nid (Z_STRVAL_P (curve_name_zv ));
@@ -4674,6 +4708,66 @@ static EVP_PKEY *php_openssl_pkey_init_ec(zval *data, bool *is_private) {
4674
4708
}
4675
4709
#endif
4676
4710
4711
+ #if PHP_OPENSSL_API_VERSION >= 0x30000
4712
+ static void php_openssl_pkey_object_curve_25519_448 (zval * return_value , int key_type , zval * data ) {
4713
+ EVP_PKEY * pkey = NULL ;
4714
+ EVP_PKEY_CTX * ctx = NULL ;
4715
+ OSSL_PARAM * params = NULL ;
4716
+ OSSL_PARAM_BLD * bld = OSSL_PARAM_BLD_new ();
4717
+ bool is_private ;
4718
+
4719
+ RETVAL_FALSE ;
4720
+
4721
+ if (!bld ) {
4722
+ goto cleanup ;
4723
+ }
4724
+
4725
+ zval * priv_key = zend_hash_str_find (Z_ARRVAL_P (data ), "priv_key" , sizeof ("priv_key" ) - 1 );
4726
+ if (priv_key && Z_TYPE_P (priv_key ) == IS_STRING && Z_STRLEN_P (priv_key ) > 0 ) {
4727
+ if (!OSSL_PARAM_BLD_push_octet_string (bld , OSSL_PKEY_PARAM_PRIV_KEY , Z_STRVAL_P (priv_key ), Z_STRLEN_P (priv_key ))) {
4728
+ goto cleanup ;
4729
+ }
4730
+ }
4731
+
4732
+ zval * pub_key = zend_hash_str_find (Z_ARRVAL_P (data ), "pub_key" , sizeof ("pub_key" ) - 1 );
4733
+ if (pub_key && Z_TYPE_P (pub_key ) == IS_STRING && Z_STRLEN_P (pub_key ) > 0 ) {
4734
+ if (!OSSL_PARAM_BLD_push_octet_string (bld , OSSL_PKEY_PARAM_PUB_KEY , Z_STRVAL_P (pub_key ), Z_STRLEN_P (pub_key ))) {
4735
+ goto cleanup ;
4736
+ }
4737
+ }
4738
+
4739
+ params = OSSL_PARAM_BLD_to_param (bld );
4740
+ ctx = EVP_PKEY_CTX_new_id (key_type , NULL );
4741
+ if (!params || !ctx ) {
4742
+ goto cleanup ;
4743
+ }
4744
+
4745
+ if (pub_key || priv_key ) {
4746
+ if (EVP_PKEY_fromdata_init (ctx ) <= 0 ||
4747
+ EVP_PKEY_fromdata (ctx , & pkey , EVP_PKEY_KEYPAIR , params ) <= 0 ) {
4748
+ goto cleanup ;
4749
+ }
4750
+ is_private = priv_key != NULL ;
4751
+ } else {
4752
+ is_private = true;
4753
+ PHP_OPENSSL_RAND_ADD_TIME ();
4754
+ if (EVP_PKEY_keygen_init (ctx ) <= 0 || EVP_PKEY_keygen (ctx , & pkey ) <= 0 ) {
4755
+ goto cleanup ;
4756
+ }
4757
+ }
4758
+
4759
+ if (pkey ) {
4760
+ php_openssl_pkey_object_init (return_value , pkey , is_private );
4761
+ }
4762
+
4763
+ cleanup :
4764
+ php_openssl_store_errors ();
4765
+ EVP_PKEY_CTX_free (ctx );
4766
+ OSSL_PARAM_free (params );
4767
+ OSSL_PARAM_BLD_free (bld );
4768
+ }
4769
+ #endif
4770
+
4677
4771
/* {{{ Generates a new private key */
4678
4772
PHP_FUNCTION (openssl_pkey_new )
4679
4773
{
@@ -4725,6 +4819,24 @@ PHP_FUNCTION(openssl_pkey_new)
4725
4819
}
4726
4820
php_openssl_pkey_object_init (return_value , pkey , is_private );
4727
4821
return ;
4822
+ #endif
4823
+ #if PHP_OPENSSL_API_VERSION >= 0x30000
4824
+ } else if ((data = zend_hash_str_find (Z_ARRVAL_P (args ), "x25519" , sizeof ("x25519" ) - 1 )) != NULL &&
4825
+ Z_TYPE_P (data ) == IS_ARRAY ) {
4826
+ php_openssl_pkey_object_curve_25519_448 (return_value , EVP_PKEY_X25519 , data );
4827
+ return ;
4828
+ } else if ((data = zend_hash_str_find (Z_ARRVAL_P (args ), "ed25519" , sizeof ("ed25519" ) - 1 )) != NULL &&
4829
+ Z_TYPE_P (data ) == IS_ARRAY ) {
4830
+ php_openssl_pkey_object_curve_25519_448 (return_value , EVP_PKEY_ED25519 , data );
4831
+ return ;
4832
+ } else if ((data = zend_hash_str_find (Z_ARRVAL_P (args ), "x448" , sizeof ("x448" ) - 1 )) != NULL &&
4833
+ Z_TYPE_P (data ) == IS_ARRAY ) {
4834
+ php_openssl_pkey_object_curve_25519_448 (return_value , EVP_PKEY_X448 , data );
4835
+ return ;
4836
+ } else if ((data = zend_hash_str_find (Z_ARRVAL_P (args ), "ed448" , sizeof ("ed448" ) - 1 )) != NULL &&
4837
+ Z_TYPE_P (data ) == IS_ARRAY ) {
4838
+ php_openssl_pkey_object_curve_25519_448 (return_value , EVP_PKEY_ED448 , data );
4839
+ return ;
4728
4840
#endif
4729
4841
}
4730
4842
}
@@ -4957,6 +5069,27 @@ static zend_string *php_openssl_get_utf8_param(
4957
5069
return NULL ;
4958
5070
}
4959
5071
#endif
5072
+
5073
+ static void php_openssl_copy_octet_string_param (
5074
+ zval * ary , EVP_PKEY * pkey , const char * param , const char * name ) {
5075
+ unsigned char buf [64 ];
5076
+ size_t len ;
5077
+ if (EVP_PKEY_get_octet_string_param (pkey , param , buf , sizeof (buf ), & len ) > 0 ) {
5078
+ zend_string * str = zend_string_alloc (len , 0 );
5079
+ memcpy (ZSTR_VAL (str ), buf , len );
5080
+ ZSTR_VAL (str )[len ] = '\0' ;
5081
+ add_assoc_str (ary , name , str );
5082
+ }
5083
+ }
5084
+
5085
+ static void php_openssl_copy_curve_25519_448_params (
5086
+ zval * return_value , const char * assoc_name , EVP_PKEY * pkey ) {
5087
+ zval ary ;
5088
+ array_init (& ary );
5089
+ add_assoc_zval (return_value , assoc_name , & ary );
5090
+ php_openssl_copy_octet_string_param (& ary , pkey , OSSL_PKEY_PARAM_PRIV_KEY , "priv_key" );
5091
+ php_openssl_copy_octet_string_param (& ary , pkey , OSSL_PKEY_PARAM_PUB_KEY , "pub_key" );
5092
+ }
4960
5093
#endif
4961
5094
4962
5095
/* {{{ returns an array with the key details (bits, pkey, type)*/
@@ -5065,6 +5198,28 @@ PHP_FUNCTION(openssl_pkey_get_details)
5065
5198
php_openssl_copy_bn_param (& ary , pkey , OSSL_PKEY_PARAM_PRIV_KEY , "d" );
5066
5199
break ;
5067
5200
}
5201
+ #endif
5202
+ #if PHP_OPENSSL_API_VERSION >= 0x30000
5203
+ case EVP_PKEY_X25519 : {
5204
+ ktype = OPENSSL_KEYTYPE_X25519 ;
5205
+ php_openssl_copy_curve_25519_448_params (return_value , "x25519" , pkey );
5206
+ break ;
5207
+ }
5208
+ case EVP_PKEY_ED25519 : {
5209
+ ktype = OPENSSL_KEYTYPE_ED25519 ;
5210
+ php_openssl_copy_curve_25519_448_params (return_value , "ed25519" , pkey );
5211
+ break ;
5212
+ }
5213
+ case EVP_PKEY_X448 : {
5214
+ ktype = OPENSSL_KEYTYPE_X448 ;
5215
+ php_openssl_copy_curve_25519_448_params (return_value , "x448" , pkey );
5216
+ break ;
5217
+ }
5218
+ case EVP_PKEY_ED448 : {
5219
+ ktype = OPENSSL_KEYTYPE_ED448 ;
5220
+ php_openssl_copy_curve_25519_448_params (return_value , "ed448" , pkey );
5221
+ break ;
5222
+ }
5068
5223
#endif
5069
5224
default :
5070
5225
ktype = -1 ;
@@ -6942,14 +7097,14 @@ PHP_FUNCTION(openssl_sign)
6942
7097
{
6943
7098
zval * key , * signature ;
6944
7099
EVP_PKEY * pkey ;
6945
- unsigned int siglen ;
6946
- zend_string * sigbuf ;
7100
+ zend_string * sigbuf = NULL ;
6947
7101
char * data ;
6948
7102
size_t data_len ;
6949
7103
EVP_MD_CTX * md_ctx ;
6950
7104
zend_string * method_str = NULL ;
6951
7105
zend_long method_long = OPENSSL_ALGO_SHA1 ;
6952
7106
const EVP_MD * mdtype ;
7107
+ bool can_default_digest = ZEND_THREEWAY_COMPARE (PHP_OPENSSL_API_VERSION , 0x30000 ) >= 0 ;
6953
7108
6954
7109
ZEND_PARSE_PARAMETERS_START (3 , 4 )
6955
7110
Z_PARAM_STRING (data , data_len )
@@ -6972,19 +7127,27 @@ PHP_FUNCTION(openssl_sign)
6972
7127
} else {
6973
7128
mdtype = php_openssl_get_evp_md_from_algo (method_long );
6974
7129
}
6975
- if (!mdtype ) {
7130
+ if (!mdtype && (! can_default_digest || method_long != 0 ) ) {
6976
7131
php_error_docref (NULL , E_WARNING , "Unknown digest algorithm" );
6977
7132
RETURN_FALSE ;
6978
7133
}
6979
7134
6980
- siglen = EVP_PKEY_size (pkey );
6981
- sigbuf = zend_string_alloc (siglen , 0 );
6982
-
6983
7135
md_ctx = EVP_MD_CTX_create ();
7136
+ size_t siglen ;
7137
+ #if PHP_OPENSSL_API_VERSION >= 0x10100
7138
+ if (md_ctx != NULL &&
7139
+ EVP_DigestSignInit (md_ctx , NULL , mdtype , NULL , pkey ) &&
7140
+ EVP_DigestSign (md_ctx , NULL , & siglen , (unsigned char * )data , data_len ) &&
7141
+ (sigbuf = zend_string_alloc (siglen , 0 )) != NULL &&
7142
+ EVP_DigestSign (md_ctx , (unsigned char * )ZSTR_VAL (sigbuf ), & siglen , (unsigned char * )data , data_len )) {
7143
+ #else
6984
7144
if (md_ctx != NULL &&
6985
7145
EVP_SignInit (md_ctx , mdtype ) &&
6986
7146
EVP_SignUpdate (md_ctx , data , data_len ) &&
6987
- EVP_SignFinal (md_ctx , (unsigned char * )ZSTR_VAL (sigbuf ), & siglen , pkey )) {
7147
+ (siglen = EVP_PKEY_size (pkey )) &&
7148
+ (sigbuf = zend_string_alloc (siglen , 0 )) != NULL &&
7149
+ EVP_SignFinal (md_ctx , (unsigned char * )ZSTR_VAL (sigbuf ), (unsigned int * )& siglen , pkey )) {
7150
+ #endif
6988
7151
ZSTR_VAL (sigbuf )[siglen ] = '\0' ;
6989
7152
ZSTR_LEN (sigbuf ) = siglen ;
6990
7153
ZEND_TRY_ASSIGN_REF_NEW_STR (signature , sigbuf );
@@ -7013,6 +7176,7 @@ PHP_FUNCTION(openssl_verify)
7013
7176
size_t signature_len ;
7014
7177
zend_string * method_str = NULL ;
7015
7178
zend_long method_long = OPENSSL_ALGO_SHA1 ;
7179
+ bool can_default_digest = ZEND_THREEWAY_COMPARE (PHP_OPENSSL_API_VERSION , 0x30000 ) >= 0 ;
7016
7180
7017
7181
ZEND_PARSE_PARAMETERS_START (3 , 4 )
7018
7182
Z_PARAM_STRING (data , data_len )
@@ -7029,7 +7193,7 @@ PHP_FUNCTION(openssl_verify)
7029
7193
} else {
7030
7194
mdtype = php_openssl_get_evp_md_from_algo (method_long );
7031
7195
}
7032
- if (!mdtype ) {
7196
+ if (!mdtype && (! can_default_digest || method_long != 0 ) ) {
7033
7197
php_error_docref (NULL , E_WARNING , "Unknown digest algorithm" );
7034
7198
RETURN_FALSE ;
7035
7199
}
@@ -7044,9 +7208,14 @@ PHP_FUNCTION(openssl_verify)
7044
7208
7045
7209
md_ctx = EVP_MD_CTX_create ();
7046
7210
if (md_ctx == NULL ||
7211
+ #if PHP_OPENSSL_API_VERSION >= 0x10100
7212
+ !EVP_DigestVerifyInit (md_ctx , NULL , mdtype , NULL , pkey ) ||
7213
+ (err = EVP_DigestVerify (md_ctx , (unsigned char * )signature , signature_len , (unsigned char * )data , data_len )) < 0 ) {
7214
+ #else
7047
7215
!EVP_VerifyInit (md_ctx , mdtype ) ||
7048
7216
!EVP_VerifyUpdate (md_ctx , data , data_len ) ||
7049
7217
(err = EVP_VerifyFinal (md_ctx , (unsigned char * )signature , (unsigned int )signature_len , pkey )) < 0 ) {
7218
+ #endif
7050
7219
php_openssl_store_errors ();
7051
7220
}
7052
7221
EVP_MD_CTX_destroy (md_ctx );
0 commit comments