From a2f83d3075a645bd66eaec257823943a65050961 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 12 Jun 2026 16:14:48 +0200 Subject: [PATCH] aesni: Fix memory leak on failed ICV verification if not using in-place decryption The `aead_t` interface states that `decrypt()` only allocates a plaintext buffer if successful, so callers might not free it if the call failed. Fixes: 313811b72d28 ("aesni: Add a GCM AEAD based on the AES-NI key schedule") --- src/libstrongswan/plugins/aesni/aesni_ccm.c | 9 +++++++-- src/libstrongswan/plugins/aesni/aesni_gcm.c | 8 +++++++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/libstrongswan/plugins/aesni/aesni_ccm.c b/src/libstrongswan/plugins/aesni/aesni_ccm.c index 86aad97ed..c0b48f35a 100644 --- a/src/libstrongswan/plugins/aesni/aesni_ccm.c +++ b/src/libstrongswan/plugins/aesni/aesni_ccm.c @@ -760,6 +760,7 @@ METHOD(aead_t, decrypt, bool, chunk_t *plain) { u_char *out, icv[this->icv_size]; + bool valid; if (!this->key || iv.len != IV_SIZE || encr.len < this->icv_size) { @@ -772,10 +773,14 @@ METHOD(aead_t, decrypt, bool, *plain = chunk_alloc(encr.len); out = plain->ptr; } - this->decrypt(this, encr.len, encr.ptr, out, iv.ptr, assoc.len, assoc.ptr, icv); - return memeq_const(icv, encr.ptr + encr.len, this->icv_size); + valid = memeq_const(icv, encr.ptr + encr.len, this->icv_size); + if (!valid && plain) + { + chunk_free(plain); + } + return valid; } METHOD(aead_t, get_block_size, size_t, diff --git a/src/libstrongswan/plugins/aesni/aesni_gcm.c b/src/libstrongswan/plugins/aesni/aesni_gcm.c index 45620cd55..5f48c22f4 100644 --- a/src/libstrongswan/plugins/aesni/aesni_gcm.c +++ b/src/libstrongswan/plugins/aesni/aesni_gcm.c @@ -1268,6 +1268,7 @@ METHOD(aead_t, decrypt, bool, chunk_t *plain) { u_char *out, icv[this->icv_size]; + bool valid; if (!this->key || iv.len != IV_SIZE || encr.len < this->icv_size) { @@ -1282,7 +1283,12 @@ METHOD(aead_t, decrypt, bool, } this->decrypt(this, encr.len, encr.ptr, out, iv.ptr, assoc.len, assoc.ptr, icv); - return memeq_const(icv, encr.ptr + encr.len, this->icv_size); + valid = memeq_const(icv, encr.ptr + encr.len, this->icv_size); + if (!valid && plain) + { + chunk_free(plain); + } + return valid; } METHOD(aead_t, get_block_size, size_t,