From 6a50ce0af5c91fd665d65d357af8ae55db1df7d0 Mon Sep 17 00:00:00 2001 From: Mohamad Raizudeen Date: Mon, 5 Oct 2026 20:33:24 +0530 Subject: [PATCH] lib/crypto: chacha20poly1305: zeroize state in __chacha20poly1305_decrypt The `__chacha20poly1305_decrypt` function does not zeroize the chacha state, unlike its encrypt counterpart. The regular `chacha20poly1305_decrypt` function handles this by manually calling chacha_zeroize_state(). However, `xchacha20poly1305_decrypt` returns the result directly without clearing the state, leaving the derived chacha20 subkey on the stack. Because this function is EXPORT_SYMBOL()ed, this is an ABI robustness improvement. To ensure consistent and safe cleanup for any future callers, move the chacha_zeroize_state() call into `__chacha20poly1305_decrypt()` itself, so the helper cleans up after its own state just like `__chacha20poly1305_encrypt()` does. Additionally, moved the src_len check to the callers so the state is not initialized on invalid inputs, matching the logic in chacha20poly1305_crypt_sg_inplace(). Suggested-by: Ard Biesheuvel Signed-off-by: Mohamad Raizudeen Link: https://patch.msgid.link/20261005150324.5621-1-raizudeen.kerneldev@gmail.com Signed-off-by: Eric Biggers --- lib/crypto/chacha20poly1305.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/lib/crypto/chacha20poly1305.c b/lib/crypto/chacha20poly1305.c index ea42a28f4ff7..c3995ac8acb7 100644 --- a/lib/crypto/chacha20poly1305.c +++ b/lib/crypto/chacha20poly1305.c @@ -137,9 +137,6 @@ __chacha20poly1305_decrypt(u8 *dst, const u8 *src, const size_t src_len, __le64 lens[2]; } b; - if (unlikely(src_len < POLY1305_DIGEST_SIZE)) - return false; - chacha20_crypt(chacha_state, b.block0, pad0, sizeof(b.block0)); poly1305_init(&poly1305_state, b.block0); @@ -162,6 +159,7 @@ __chacha20poly1305_decrypt(u8 *dst, const u8 *src, const size_t src_len, if (likely(!ret)) chacha20_crypt(chacha_state, dst, src, dst_len); + chacha_zeroize_state(chacha_state); memzero_explicit(&b, sizeof(b)); return !ret; @@ -177,6 +175,9 @@ bool chacha20poly1305_decrypt(u8 *dst, const u8 *src, const size_t src_len, __le64 iv[2]; bool ret; + if (unlikely(src_len < POLY1305_DIGEST_SIZE)) + return false; + chacha_load_key(k, key); iv[0] = 0; @@ -186,7 +187,6 @@ bool chacha20poly1305_decrypt(u8 *dst, const u8 *src, const size_t src_len, ret = __chacha20poly1305_decrypt(dst, src, src_len, ad, ad_len, &chacha_state); - chacha_zeroize_state(&chacha_state); memzero_explicit(iv, sizeof(iv)); memzero_explicit(k, sizeof(k)); return ret; @@ -200,6 +200,9 @@ bool xchacha20poly1305_decrypt(u8 *dst, const u8 *src, const size_t src_len, { struct chacha_state chacha_state; + if (unlikely(src_len < POLY1305_DIGEST_SIZE)) + return false; + xchacha_init(&chacha_state, key, nonce); return __chacha20poly1305_decrypt(dst, src, src_len, ad, ad_len, &chacha_state);