@@ -6483,8 +6483,9 @@ PHP_FUNCTION(openssl_digest)
6483
6483
/* Cipher mode info */
6484
6484
struct php_openssl_cipher_mode {
6485
6485
zend_bool is_aead ;
6486
- zend_bool should_set_tag_length ;
6487
6486
zend_bool is_single_run_aead ;
6487
+ zend_bool set_tag_length_always ;
6488
+ zend_bool set_tag_length_when_encrypting ;
6488
6489
int aead_get_tag_flag ;
6489
6490
int aead_set_tag_flag ;
6490
6491
int aead_ivlen_flag ;
@@ -6493,14 +6494,17 @@ struct php_openssl_cipher_mode {
6493
6494
static void php_openssl_load_cipher_mode (struct php_openssl_cipher_mode * mode , const EVP_CIPHER * cipher_type ) /* {{{ */
6494
6495
{
6495
6496
int cipher_mode = EVP_CIPHER_mode (cipher_type );
6497
+ memset (mode , 0 , sizeof (struct php_openssl_cipher_mode ));
6496
6498
switch (cipher_mode ) {
6497
6499
#if PHP_OPENSSL_API_VERSION >= 0x10100
6498
6500
case EVP_CIPH_GCM_MODE :
6499
6501
case EVP_CIPH_OCB_MODE :
6500
6502
case EVP_CIPH_CCM_MODE :
6501
6503
mode -> is_aead = 1 ;
6502
- mode -> should_set_tag_length =
6503
- cipher_mode == EVP_CIPH_CCM_MODE || cipher_mode == EVP_CIPH_OCB_MODE ;
6504
+ /* For OCB mode, explicitly set the tag length even when decrypting,
6505
+ * see https://github.com/openssl/openssl/issues/8331. */
6506
+ mode -> set_tag_length_always = cipher_mode == EVP_CIPH_OCB_MODE ;
6507
+ mode -> set_tag_length_when_encrypting = cipher_mode == EVP_CIPH_CCM_MODE ;
6504
6508
mode -> is_single_run_aead = cipher_mode == EVP_CIPH_CCM_MODE ;
6505
6509
mode -> aead_get_tag_flag = EVP_CTRL_AEAD_GET_TAG ;
6506
6510
mode -> aead_set_tag_flag = EVP_CTRL_AEAD_SET_TAG ;
@@ -6510,8 +6514,6 @@ static void php_openssl_load_cipher_mode(struct php_openssl_cipher_mode *mode, c
6510
6514
# ifdef EVP_CIPH_GCM_MODE
6511
6515
case EVP_CIPH_GCM_MODE :
6512
6516
mode -> is_aead = 1 ;
6513
- mode -> should_set_tag_length = 0 ;
6514
- mode -> is_single_run_aead = 0 ;
6515
6517
mode -> aead_get_tag_flag = EVP_CTRL_GCM_GET_TAG ;
6516
6518
mode -> aead_set_tag_flag = EVP_CTRL_GCM_SET_TAG ;
6517
6519
mode -> aead_ivlen_flag = EVP_CTRL_GCM_SET_IVLEN ;
@@ -6520,16 +6522,14 @@ static void php_openssl_load_cipher_mode(struct php_openssl_cipher_mode *mode, c
6520
6522
# ifdef EVP_CIPH_CCM_MODE
6521
6523
case EVP_CIPH_CCM_MODE :
6522
6524
mode -> is_aead = 1 ;
6523
- mode -> should_set_tag_length = 1 ;
6524
6525
mode -> is_single_run_aead = 1 ;
6526
+ mode -> set_tag_length_when_encrypting = 1 ;
6525
6527
mode -> aead_get_tag_flag = EVP_CTRL_CCM_GET_TAG ;
6526
6528
mode -> aead_set_tag_flag = EVP_CTRL_CCM_SET_TAG ;
6527
6529
mode -> aead_ivlen_flag = EVP_CTRL_CCM_SET_IVLEN ;
6528
6530
break ;
6529
6531
# endif
6530
6532
#endif
6531
- default :
6532
- memset (mode , 0 , sizeof (struct php_openssl_cipher_mode ));
6533
6533
}
6534
6534
}
6535
6535
/* }}} */
@@ -6611,9 +6611,7 @@ static int php_openssl_cipher_init(const EVP_CIPHER *cipher_type,
6611
6611
if (php_openssl_validate_iv (piv , piv_len , max_iv_len , free_iv , cipher_ctx , mode ) == FAILURE ) {
6612
6612
return FAILURE ;
6613
6613
}
6614
- if (mode -> should_set_tag_length ) {
6615
- /* Explicitly set the tag length even when decrypting,
6616
- * see https://github.com/openssl/openssl/issues/8331. */
6614
+ if (mode -> set_tag_length_always || (enc && mode -> set_tag_length_when_encrypting )) {
6617
6615
if (!EVP_CIPHER_CTX_ctrl (cipher_ctx , mode -> aead_set_tag_flag , tag_len , NULL )) {
6618
6616
php_error_docref (NULL , E_WARNING , "Setting tag length for AEAD cipher failed" );
6619
6617
return FAILURE ;
0 commit comments