@@ -6483,6 +6483,7 @@ 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 ;
6486
6487
zend_bool is_single_run_aead ;
6487
6488
int aead_get_tag_flag ;
6488
6489
int aead_set_tag_flag ;
@@ -6491,24 +6492,41 @@ struct php_openssl_cipher_mode {
6491
6492
6492
6493
static void php_openssl_load_cipher_mode (struct php_openssl_cipher_mode * mode , const EVP_CIPHER * cipher_type ) /* {{{ */
6493
6494
{
6494
- switch (EVP_CIPHER_mode (cipher_type )) {
6495
- #ifdef EVP_CIPH_GCM_MODE
6495
+ int cipher_mode = EVP_CIPHER_mode (cipher_type );
6496
+ switch (cipher_mode ) {
6497
+ #if PHP_OPENSSL_API_VERSION >= 0x10100
6498
+ case EVP_CIPH_GCM_MODE :
6499
+ case EVP_CIPH_OCB_MODE :
6500
+ case EVP_CIPH_CCM_MODE :
6501
+ mode -> is_aead = 1 ;
6502
+ mode -> should_set_tag_length =
6503
+ cipher_mode == EVP_CIPH_CCM_MODE || cipher_mode == EVP_CIPH_OCB_MODE ;
6504
+ mode -> is_single_run_aead = cipher_mode == EVP_CIPH_CCM_MODE ;
6505
+ mode -> aead_get_tag_flag = EVP_CTRL_AEAD_GET_TAG ;
6506
+ mode -> aead_set_tag_flag = EVP_CTRL_AEAD_SET_TAG ;
6507
+ mode -> aead_ivlen_flag = EVP_CTRL_AEAD_SET_IVLEN ;
6508
+ break ;
6509
+ #else
6510
+ # ifdef EVP_CIPH_GCM_MODE
6496
6511
case EVP_CIPH_GCM_MODE :
6497
6512
mode -> is_aead = 1 ;
6513
+ mode -> should_set_tag_length = 0 ;
6498
6514
mode -> is_single_run_aead = 0 ;
6499
6515
mode -> aead_get_tag_flag = EVP_CTRL_GCM_GET_TAG ;
6500
6516
mode -> aead_set_tag_flag = EVP_CTRL_GCM_SET_TAG ;
6501
6517
mode -> aead_ivlen_flag = EVP_CTRL_GCM_SET_IVLEN ;
6502
6518
break ;
6503
- #endif
6504
- #ifdef EVP_CIPH_CCM_MODE
6519
+ # endif
6520
+ # ifdef EVP_CIPH_CCM_MODE
6505
6521
case EVP_CIPH_CCM_MODE :
6506
6522
mode -> is_aead = 1 ;
6523
+ mode -> should_set_tag_length = 1 ;
6507
6524
mode -> is_single_run_aead = 1 ;
6508
6525
mode -> aead_get_tag_flag = EVP_CTRL_CCM_GET_TAG ;
6509
6526
mode -> aead_set_tag_flag = EVP_CTRL_CCM_SET_TAG ;
6510
6527
mode -> aead_ivlen_flag = EVP_CTRL_CCM_SET_IVLEN ;
6511
6528
break ;
6529
+ # endif
6512
6530
#endif
6513
6531
default :
6514
6532
memset (mode , 0 , sizeof (struct php_openssl_cipher_mode ));
@@ -6593,12 +6611,15 @@ static int php_openssl_cipher_init(const EVP_CIPHER *cipher_type,
6593
6611
if (php_openssl_validate_iv (piv , piv_len , max_iv_len , free_iv , cipher_ctx , mode ) == FAILURE ) {
6594
6612
return FAILURE ;
6595
6613
}
6596
- if (mode -> is_single_run_aead && enc ) {
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. */
6597
6617
if (!EVP_CIPHER_CTX_ctrl (cipher_ctx , mode -> aead_set_tag_flag , tag_len , NULL )) {
6598
6618
php_error_docref (NULL , E_WARNING , "Setting tag length for AEAD cipher failed" );
6599
6619
return FAILURE ;
6600
6620
}
6601
- } else if (!enc && tag && tag_len > 0 ) {
6621
+ }
6622
+ if (!enc && tag && tag_len > 0 ) {
6602
6623
if (!mode -> is_aead ) {
6603
6624
php_error_docref (NULL , E_WARNING , "The tag cannot be used because the cipher method does not support AEAD" );
6604
6625
} else if (!EVP_CIPHER_CTX_ctrl (cipher_ctx , mode -> aead_set_tag_flag , tag_len , (unsigned char * ) tag )) {
0 commit comments