@@ -6888,8 +6888,9 @@ PHP_FUNCTION(openssl_digest)
6888
6888
/* Cipher mode info */
6889
6889
struct php_openssl_cipher_mode {
6890
6890
zend_bool is_aead ;
6891
- zend_bool should_set_tag_length ;
6892
6891
zend_bool is_single_run_aead ;
6892
+ zend_bool set_tag_length_always ;
6893
+ zend_bool set_tag_length_when_encrypting ;
6893
6894
int aead_get_tag_flag ;
6894
6895
int aead_set_tag_flag ;
6895
6896
int aead_ivlen_flag ;
@@ -6898,14 +6899,17 @@ struct php_openssl_cipher_mode {
6898
6899
static void php_openssl_load_cipher_mode (struct php_openssl_cipher_mode * mode , const EVP_CIPHER * cipher_type ) /* {{{ */
6899
6900
{
6900
6901
int cipher_mode = EVP_CIPHER_mode (cipher_type );
6902
+ memset (mode , 0 , sizeof (struct php_openssl_cipher_mode ));
6901
6903
switch (cipher_mode ) {
6902
6904
#if PHP_OPENSSL_API_VERSION >= 0x10100
6903
6905
case EVP_CIPH_GCM_MODE :
6904
6906
case EVP_CIPH_OCB_MODE :
6905
6907
case EVP_CIPH_CCM_MODE :
6906
6908
mode -> is_aead = 1 ;
6907
- mode -> should_set_tag_length =
6908
- cipher_mode == EVP_CIPH_CCM_MODE || cipher_mode == EVP_CIPH_OCB_MODE ;
6909
+ /* For OCB mode, explicitly set the tag length even when decrypting,
6910
+ * see https://github.com/openssl/openssl/issues/8331. */
6911
+ mode -> set_tag_length_always = cipher_mode == EVP_CIPH_OCB_MODE ;
6912
+ mode -> set_tag_length_when_encrypting = cipher_mode == EVP_CIPH_CCM_MODE ;
6909
6913
mode -> is_single_run_aead = cipher_mode == EVP_CIPH_CCM_MODE ;
6910
6914
mode -> aead_get_tag_flag = EVP_CTRL_AEAD_GET_TAG ;
6911
6915
mode -> aead_set_tag_flag = EVP_CTRL_AEAD_SET_TAG ;
@@ -6915,8 +6919,6 @@ static void php_openssl_load_cipher_mode(struct php_openssl_cipher_mode *mode, c
6915
6919
# ifdef EVP_CIPH_GCM_MODE
6916
6920
case EVP_CIPH_GCM_MODE :
6917
6921
mode -> is_aead = 1 ;
6918
- mode -> should_set_tag_length = 0 ;
6919
- mode -> is_single_run_aead = 0 ;
6920
6922
mode -> aead_get_tag_flag = EVP_CTRL_GCM_GET_TAG ;
6921
6923
mode -> aead_set_tag_flag = EVP_CTRL_GCM_SET_TAG ;
6922
6924
mode -> aead_ivlen_flag = EVP_CTRL_GCM_SET_IVLEN ;
@@ -6925,16 +6927,14 @@ static void php_openssl_load_cipher_mode(struct php_openssl_cipher_mode *mode, c
6925
6927
# ifdef EVP_CIPH_CCM_MODE
6926
6928
case EVP_CIPH_CCM_MODE :
6927
6929
mode -> is_aead = 1 ;
6928
- mode -> should_set_tag_length = 1 ;
6929
6930
mode -> is_single_run_aead = 1 ;
6931
+ mode -> set_tag_length_when_encrypting = 1 ;
6930
6932
mode -> aead_get_tag_flag = EVP_CTRL_CCM_GET_TAG ;
6931
6933
mode -> aead_set_tag_flag = EVP_CTRL_CCM_SET_TAG ;
6932
6934
mode -> aead_ivlen_flag = EVP_CTRL_CCM_SET_IVLEN ;
6933
6935
break ;
6934
6936
# endif
6935
6937
#endif
6936
- default :
6937
- memset (mode , 0 , sizeof (struct php_openssl_cipher_mode ));
6938
6938
}
6939
6939
}
6940
6940
/* }}} */
@@ -7016,9 +7016,7 @@ static int php_openssl_cipher_init(const EVP_CIPHER *cipher_type,
7016
7016
if (php_openssl_validate_iv (piv , piv_len , max_iv_len , free_iv , cipher_ctx , mode ) == FAILURE ) {
7017
7017
return FAILURE ;
7018
7018
}
7019
- if (mode -> should_set_tag_length ) {
7020
- /* Explicitly set the tag length even when decrypting,
7021
- * see https://github.com/openssl/openssl/issues/8331. */
7019
+ if (mode -> set_tag_length_always || (enc && mode -> set_tag_length_when_encrypting )) {
7022
7020
if (!EVP_CIPHER_CTX_ctrl (cipher_ctx , mode -> aead_set_tag_flag , tag_len , NULL )) {
7023
7021
php_error_docref (NULL , E_WARNING , "Setting tag length for AEAD cipher failed" );
7024
7022
return FAILURE ;
0 commit comments