diff options
-rw-r--r-- | ext/openssl/openssl.c | 20 |
1 files changed, 9 insertions, 11 deletions
diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index b18e5f8d99..dfb0bd3af2 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -6483,8 +6483,9 @@ PHP_FUNCTION(openssl_digest) /* Cipher mode info */ struct php_openssl_cipher_mode { zend_bool is_aead; - zend_bool should_set_tag_length; zend_bool is_single_run_aead; + zend_bool set_tag_length_always; + zend_bool set_tag_length_when_encrypting; int aead_get_tag_flag; int aead_set_tag_flag; int aead_ivlen_flag; @@ -6493,14 +6494,17 @@ struct php_openssl_cipher_mode { static void php_openssl_load_cipher_mode(struct php_openssl_cipher_mode *mode, const EVP_CIPHER *cipher_type) /* {{{ */ { int cipher_mode = EVP_CIPHER_mode(cipher_type); + memset(mode, 0, sizeof(struct php_openssl_cipher_mode)); switch (cipher_mode) { #if PHP_OPENSSL_API_VERSION >= 0x10100 case EVP_CIPH_GCM_MODE: case EVP_CIPH_OCB_MODE: case EVP_CIPH_CCM_MODE: mode->is_aead = 1; - mode->should_set_tag_length = - cipher_mode == EVP_CIPH_CCM_MODE || cipher_mode == EVP_CIPH_OCB_MODE; + /* For OCB mode, explicitly set the tag length even when decrypting, + * see https://github.com/openssl/openssl/issues/8331. */ + mode->set_tag_length_always = cipher_mode == EVP_CIPH_OCB_MODE; + mode->set_tag_length_when_encrypting = cipher_mode == EVP_CIPH_CCM_MODE; mode->is_single_run_aead = cipher_mode == EVP_CIPH_CCM_MODE; mode->aead_get_tag_flag = EVP_CTRL_AEAD_GET_TAG; 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 # ifdef EVP_CIPH_GCM_MODE case EVP_CIPH_GCM_MODE: mode->is_aead = 1; - mode->should_set_tag_length = 0; - mode->is_single_run_aead = 0; mode->aead_get_tag_flag = EVP_CTRL_GCM_GET_TAG; mode->aead_set_tag_flag = EVP_CTRL_GCM_SET_TAG; 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 # ifdef EVP_CIPH_CCM_MODE case EVP_CIPH_CCM_MODE: mode->is_aead = 1; - mode->should_set_tag_length = 1; mode->is_single_run_aead = 1; + mode->set_tag_length_when_encrypting = 1; mode->aead_get_tag_flag = EVP_CTRL_CCM_GET_TAG; mode->aead_set_tag_flag = EVP_CTRL_CCM_SET_TAG; mode->aead_ivlen_flag = EVP_CTRL_CCM_SET_IVLEN; break; # endif #endif - default: - memset(mode, 0, sizeof(struct php_openssl_cipher_mode)); } } /* }}} */ @@ -6611,9 +6611,7 @@ static int php_openssl_cipher_init(const EVP_CIPHER *cipher_type, if (php_openssl_validate_iv(piv, piv_len, max_iv_len, free_iv, cipher_ctx, mode) == FAILURE) { return FAILURE; } - if (mode->should_set_tag_length) { - /* Explicitly set the tag length even when decrypting, - * see https://github.com/openssl/openssl/issues/8331. */ + if (mode->set_tag_length_always || (enc && mode->set_tag_length_when_encrypting)) { if (!EVP_CIPHER_CTX_ctrl(cipher_ctx, mode->aead_set_tag_flag, tag_len, NULL)) { php_error_docref(NULL, E_WARNING, "Setting tag length for AEAD cipher failed"); return FAILURE; |