[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <CAMj1kXGtDxf+GWx8xNQZcdvqfgJ+xL8m3U3TCoOypTGw7_-t3Q@mail.gmail.com>
Date: Fri, 21 Nov 2025 12:04:12 +0100
From: Ard Biesheuvel <ardb@...nel.org>
To: "Jason A. Donenfeld" <Jason@...c4.com>
Cc: Linus Torvalds <torvalds@...ux-foundation.org>, Eric Biggers <ebiggers@...nel.org>,
Kees Cook <kees@...nel.org>, linux-crypto@...r.kernel.org,
linux-kernel@...r.kernel.org
Subject: Re: [PATCH libcrypto v2 3/3] crypto: chacha20poly1305: statically
check fixed array lengths
On Thu, 20 Nov 2025 at 02:11, Jason A. Donenfeld <Jason@...c4.com> wrote:
>
> Several parameters of the chacha20poly1305 functions require arrays of
> an exact length. Use the new at_least keyword to instruct gcc and
> clang to statically check that the caller is passing an object of at
> least that length.
>
> Here it is in action, with this faulty patch to wireguard's cookie.h:
>
> struct cookie_checker {
> u8 secret[NOISE_HASH_LEN];
> - u8 cookie_encryption_key[NOISE_SYMMETRIC_KEY_LEN];
> + u8 cookie_encryption_key[NOISE_SYMMETRIC_KEY_LEN - 1];
> u8 message_mac1_key[NOISE_SYMMETRIC_KEY_LEN];
>
> If I try compiling this code, I get this helpful warning:
>
> CC drivers/net/wireguard/cookie.o
> drivers/net/wireguard/cookie.c: In function ‘wg_cookie_message_create’:
> drivers/net/wireguard/cookie.c:193:9: warning: ‘xchacha20poly1305_encrypt’ reading 32 bytes from a region of size 31 [-Wstringop-overread]
> 193 | xchacha20poly1305_encrypt(dst->encrypted_cookie, cookie, COOKIE_LEN,
> | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> 194 | macs->mac1, COOKIE_LEN, dst->nonce,
> | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> 195 | checker->cookie_encryption_key);
> | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> drivers/net/wireguard/cookie.c:193:9: note: referencing argument 7 of type ‘const u8 *’ {aka ‘const unsigned char *’}
> In file included from drivers/net/wireguard/messages.h:10,
> from drivers/net/wireguard/cookie.h:9,
> from drivers/net/wireguard/cookie.c:6:
> include/crypto/chacha20poly1305.h:28:6: note: in a call to function ‘xchacha20poly1305_encrypt’
> 28 | void xchacha20poly1305_encrypt(u8 *dst, const u8 *src, const size_t src_len,
>
> Signed-off-by: Jason A. Donenfeld <Jason@...c4.com>
> ---
> include/crypto/chacha20poly1305.h | 16 ++++++++--------
> lib/crypto/chacha20poly1305.c | 18 +++++++++---------
> 2 files changed, 17 insertions(+), 17 deletions(-)
>
Acked-by: Ard Biesheuvel <ardb@...nel.org>
> diff --git a/include/crypto/chacha20poly1305.h b/include/crypto/chacha20poly1305.h
> index d2ac3ff7dc1e..7617366f8218 100644
> --- a/include/crypto/chacha20poly1305.h
> +++ b/include/crypto/chacha20poly1305.h
> @@ -18,32 +18,32 @@ enum chacha20poly1305_lengths {
> void chacha20poly1305_encrypt(u8 *dst, const u8 *src, const size_t src_len,
> const u8 *ad, const size_t ad_len,
> const u64 nonce,
> - const u8 key[CHACHA20POLY1305_KEY_SIZE]);
> + const u8 key[at_least CHACHA20POLY1305_KEY_SIZE]);
>
> bool __must_check
> chacha20poly1305_decrypt(u8 *dst, const u8 *src, const size_t src_len,
> const u8 *ad, const size_t ad_len, const u64 nonce,
> - const u8 key[CHACHA20POLY1305_KEY_SIZE]);
> + const u8 key[at_least CHACHA20POLY1305_KEY_SIZE]);
>
> void xchacha20poly1305_encrypt(u8 *dst, const u8 *src, const size_t src_len,
> const u8 *ad, const size_t ad_len,
> - const u8 nonce[XCHACHA20POLY1305_NONCE_SIZE],
> - const u8 key[CHACHA20POLY1305_KEY_SIZE]);
> + const u8 nonce[at_least XCHACHA20POLY1305_NONCE_SIZE],
> + const u8 key[at_least CHACHA20POLY1305_KEY_SIZE]);
>
> bool __must_check xchacha20poly1305_decrypt(
> u8 *dst, const u8 *src, const size_t src_len, const u8 *ad,
> - const size_t ad_len, const u8 nonce[XCHACHA20POLY1305_NONCE_SIZE],
> - const u8 key[CHACHA20POLY1305_KEY_SIZE]);
> + const size_t ad_len, const u8 nonce[at_least XCHACHA20POLY1305_NONCE_SIZE],
> + const u8 key[at_least CHACHA20POLY1305_KEY_SIZE]);
>
> bool chacha20poly1305_encrypt_sg_inplace(struct scatterlist *src, size_t src_len,
> const u8 *ad, const size_t ad_len,
> const u64 nonce,
> - const u8 key[CHACHA20POLY1305_KEY_SIZE]);
> + const u8 key[at_least CHACHA20POLY1305_KEY_SIZE]);
>
> bool chacha20poly1305_decrypt_sg_inplace(struct scatterlist *src, size_t src_len,
> const u8 *ad, const size_t ad_len,
> const u64 nonce,
> - const u8 key[CHACHA20POLY1305_KEY_SIZE]);
> + const u8 key[at_least CHACHA20POLY1305_KEY_SIZE]);
>
> bool chacha20poly1305_selftest(void);
>
> diff --git a/lib/crypto/chacha20poly1305.c b/lib/crypto/chacha20poly1305.c
> index 0b49d6aedefd..212ce33562af 100644
> --- a/lib/crypto/chacha20poly1305.c
> +++ b/lib/crypto/chacha20poly1305.c
> @@ -89,7 +89,7 @@ __chacha20poly1305_encrypt(u8 *dst, const u8 *src, const size_t src_len,
> void chacha20poly1305_encrypt(u8 *dst, const u8 *src, const size_t src_len,
> const u8 *ad, const size_t ad_len,
> const u64 nonce,
> - const u8 key[CHACHA20POLY1305_KEY_SIZE])
> + const u8 key[at_least CHACHA20POLY1305_KEY_SIZE])
> {
> struct chacha_state chacha_state;
> u32 k[CHACHA_KEY_WORDS];
> @@ -111,8 +111,8 @@ EXPORT_SYMBOL(chacha20poly1305_encrypt);
>
> void xchacha20poly1305_encrypt(u8 *dst, const u8 *src, const size_t src_len,
> const u8 *ad, const size_t ad_len,
> - const u8 nonce[XCHACHA20POLY1305_NONCE_SIZE],
> - const u8 key[CHACHA20POLY1305_KEY_SIZE])
> + const u8 nonce[at_least XCHACHA20POLY1305_NONCE_SIZE],
> + const u8 key[at_least CHACHA20POLY1305_KEY_SIZE])
> {
> struct chacha_state chacha_state;
>
> @@ -170,7 +170,7 @@ __chacha20poly1305_decrypt(u8 *dst, const u8 *src, const size_t src_len,
> bool chacha20poly1305_decrypt(u8 *dst, const u8 *src, const size_t src_len,
> const u8 *ad, const size_t ad_len,
> const u64 nonce,
> - const u8 key[CHACHA20POLY1305_KEY_SIZE])
> + const u8 key[at_least CHACHA20POLY1305_KEY_SIZE])
> {
> struct chacha_state chacha_state;
> u32 k[CHACHA_KEY_WORDS];
> @@ -195,8 +195,8 @@ EXPORT_SYMBOL(chacha20poly1305_decrypt);
>
> bool xchacha20poly1305_decrypt(u8 *dst, const u8 *src, const size_t src_len,
> const u8 *ad, const size_t ad_len,
> - const u8 nonce[XCHACHA20POLY1305_NONCE_SIZE],
> - const u8 key[CHACHA20POLY1305_KEY_SIZE])
> + const u8 nonce[at_least XCHACHA20POLY1305_NONCE_SIZE],
> + const u8 key[at_least CHACHA20POLY1305_KEY_SIZE])
> {
> struct chacha_state chacha_state;
>
> @@ -211,7 +211,7 @@ bool chacha20poly1305_crypt_sg_inplace(struct scatterlist *src,
> const size_t src_len,
> const u8 *ad, const size_t ad_len,
> const u64 nonce,
> - const u8 key[CHACHA20POLY1305_KEY_SIZE],
> + const u8 key[at_least CHACHA20POLY1305_KEY_SIZE],
> int encrypt)
> {
> const u8 *pad0 = page_address(ZERO_PAGE(0));
> @@ -335,7 +335,7 @@ bool chacha20poly1305_crypt_sg_inplace(struct scatterlist *src,
> bool chacha20poly1305_encrypt_sg_inplace(struct scatterlist *src, size_t src_len,
> const u8 *ad, const size_t ad_len,
> const u64 nonce,
> - const u8 key[CHACHA20POLY1305_KEY_SIZE])
> + const u8 key[at_least CHACHA20POLY1305_KEY_SIZE])
> {
> return chacha20poly1305_crypt_sg_inplace(src, src_len, ad, ad_len,
> nonce, key, 1);
> @@ -345,7 +345,7 @@ EXPORT_SYMBOL(chacha20poly1305_encrypt_sg_inplace);
> bool chacha20poly1305_decrypt_sg_inplace(struct scatterlist *src, size_t src_len,
> const u8 *ad, const size_t ad_len,
> const u64 nonce,
> - const u8 key[CHACHA20POLY1305_KEY_SIZE])
> + const u8 key[at_least CHACHA20POLY1305_KEY_SIZE])
> {
> if (unlikely(src_len < POLY1305_DIGEST_SIZE))
> return false;
> --
> 2.52.0
>
Powered by blists - more mailing lists