Commit ce58c02c5b for openssl.org
commit ce58c02c5ba30efc0d020bb79a38d8a0b679cbea
Author: Daniel Kubec <kubec@openssl.foundation>
Date: Sat Oct 31 19:16:53 2026 +0100
AES-GCM-SIV: no-op on zero-length update and clear stale AAD on reuse
The default-provider AES-GCM-SIV implementation treated a zero-length
AAD update as a reset: aes_gcm_siv_aad() freed the AAD accumulated
so far, cleared its length, and returned success. This meant
that an application passing AAD in multiple chunks, of which some
might have zero length, would have the previous AAD chunks effectively
unauthenticated. Remove the AAD reset logic for zero-length updates.
Also, on context reinitialization, the AAD was not reset, which meant
that any AAD accumulated from the previous context usage were also
included in the AAD of the new message. This applied
to a reinitialization with a new key or nonce, as well as
to a reinitialization without either after a completed operation, which
restarts the operation under the same key and nonce. Reset the AAD
reset in both cases. A parameters-only reinitialization before
the payload still keeps the AAD accumulated so far.
Fixes: CVE-2026-88823
Fixes: 0113ec8460a9 "Implement AES-GCM-SIV (RFC8452)"
Co-authored-by: Mounir IDRASSI <mounir.idrassi@amcrypto.jp>
Reviewed-by: Mounir Idrassi <mounir.idrassi@idrix.fr>
Reviewed-by: Tomas Mraz <tomas@openssl.foundation>
Reviewed-by: Norbert Pocs <norbertp@openssl.org>
Reviewed-by: Eugene Syromiatnikov <esyr@openssl.org>
Merge-date: Wed Nov 4 12:15:48 2026
Merged-from: https://github.com/openssl/openssl/pull/33456
diff --git a/providers/implementations/ciphers/cipher_aes_gcm_siv.c b/providers/implementations/ciphers/cipher_aes_gcm_siv.c
index 371caddb1d..aecaa7d8b7 100644
--- a/providers/implementations/ciphers/cipher_aes_gcm_siv.c
+++ b/providers/implementations/ciphers/cipher_aes_gcm_siv.c
@@ -100,6 +100,16 @@ static int ossl_aes_gcm_siv_init(void *vctx, const unsigned char *key, size_t ke
ctx->enc = enc;
+ /*
+ * Clear AAD when starting a new message or restarting after payload
+ * processing. Preserve pending AAD during parameter adjustments.
+ */
+ if (key != NULL || iv != NULL || ctx->used_enc || ctx->used_dec) {
+ OPENSSL_clear_free(ctx->aad, ctx->aad_len);
+ ctx->aad = NULL;
+ ctx->aad_len = 0;
+ }
+
if (key != NULL) {
if (keylen != ctx->key_len) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
diff --git a/providers/implementations/ciphers/cipher_aes_gcm_siv_hw.c b/providers/implementations/ciphers/cipher_aes_gcm_siv_hw.c
index d387973894..d38c508bb9 100644
--- a/providers/implementations/ciphers/cipher_aes_gcm_siv_hw.c
+++ b/providers/implementations/ciphers/cipher_aes_gcm_siv_hw.c
@@ -115,13 +115,8 @@ static int aes_gcm_siv_aad(PROV_AES_GCM_SIV_CTX *ctx,
uint8_t *ptr;
uint64_t len64;
- /* length of 0 resets the AAD */
- if (len == 0) {
- OPENSSL_free(ctx->aad);
- ctx->aad = NULL;
- ctx->aad_len = 0;
+ if (len == 0)
return 1;
- }
to_alloc = UP16(ctx->aad_len + len);
/* need to check the size of the AAD per RFC8452 */
len64 = to_alloc;