Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

lib/crypto: chacha20poly1305: Statically check fixed array lengths

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,

Acked-by: Ard Biesheuvel <ardb@kernel.org>
Signed-off-by: "Jason A. Donenfeld" <Jason@zx2c4.com>
Link: https://lore.kernel.org/r/20251123054819.2371989-4-Jason@zx2c4.com
Signed-off-by: Eric Biggers <ebiggers@kernel.org>

authored by

Jason A. Donenfeld and committed by
Eric Biggers
ac653d57 074e16d5

+19 -18
+10 -9
include/crypto/chacha20poly1305.h
··· 18 18 void chacha20poly1305_encrypt(u8 *dst, const u8 *src, const size_t src_len, 19 19 const u8 *ad, const size_t ad_len, 20 20 const u64 nonce, 21 - const u8 key[CHACHA20POLY1305_KEY_SIZE]); 21 + const u8 key[at_least CHACHA20POLY1305_KEY_SIZE]); 22 22 23 23 bool __must_check 24 24 chacha20poly1305_decrypt(u8 *dst, const u8 *src, const size_t src_len, 25 25 const u8 *ad, const size_t ad_len, const u64 nonce, 26 - const u8 key[CHACHA20POLY1305_KEY_SIZE]); 26 + const u8 key[at_least CHACHA20POLY1305_KEY_SIZE]); 27 27 28 28 void xchacha20poly1305_encrypt(u8 *dst, const u8 *src, const size_t src_len, 29 29 const u8 *ad, const size_t ad_len, 30 - const u8 nonce[XCHACHA20POLY1305_NONCE_SIZE], 31 - const u8 key[CHACHA20POLY1305_KEY_SIZE]); 30 + const u8 nonce[at_least XCHACHA20POLY1305_NONCE_SIZE], 31 + const u8 key[at_least CHACHA20POLY1305_KEY_SIZE]); 32 32 33 33 bool __must_check xchacha20poly1305_decrypt( 34 - u8 *dst, const u8 *src, const size_t src_len, const u8 *ad, 35 - const size_t ad_len, const u8 nonce[XCHACHA20POLY1305_NONCE_SIZE], 36 - const u8 key[CHACHA20POLY1305_KEY_SIZE]); 34 + u8 *dst, const u8 *src, const size_t src_len, 35 + const u8 *ad, const size_t ad_len, 36 + const u8 nonce[at_least XCHACHA20POLY1305_NONCE_SIZE], 37 + const u8 key[at_least CHACHA20POLY1305_KEY_SIZE]); 37 38 38 39 bool chacha20poly1305_encrypt_sg_inplace(struct scatterlist *src, size_t src_len, 39 40 const u8 *ad, const size_t ad_len, 40 41 const u64 nonce, 41 - const u8 key[CHACHA20POLY1305_KEY_SIZE]); 42 + const u8 key[at_least CHACHA20POLY1305_KEY_SIZE]); 42 43 43 44 bool chacha20poly1305_decrypt_sg_inplace(struct scatterlist *src, size_t src_len, 44 45 const u8 *ad, const size_t ad_len, 45 46 const u64 nonce, 46 - const u8 key[CHACHA20POLY1305_KEY_SIZE]); 47 + const u8 key[at_least CHACHA20POLY1305_KEY_SIZE]); 47 48 48 49 bool chacha20poly1305_selftest(void); 49 50
+9 -9
lib/crypto/chacha20poly1305.c
··· 89 89 void chacha20poly1305_encrypt(u8 *dst, const u8 *src, const size_t src_len, 90 90 const u8 *ad, const size_t ad_len, 91 91 const u64 nonce, 92 - const u8 key[CHACHA20POLY1305_KEY_SIZE]) 92 + const u8 key[at_least CHACHA20POLY1305_KEY_SIZE]) 93 93 { 94 94 struct chacha_state chacha_state; 95 95 u32 k[CHACHA_KEY_WORDS]; ··· 111 111 112 112 void xchacha20poly1305_encrypt(u8 *dst, const u8 *src, const size_t src_len, 113 113 const u8 *ad, const size_t ad_len, 114 - const u8 nonce[XCHACHA20POLY1305_NONCE_SIZE], 115 - const u8 key[CHACHA20POLY1305_KEY_SIZE]) 114 + const u8 nonce[at_least XCHACHA20POLY1305_NONCE_SIZE], 115 + const u8 key[at_least CHACHA20POLY1305_KEY_SIZE]) 116 116 { 117 117 struct chacha_state chacha_state; 118 118 ··· 170 170 bool chacha20poly1305_decrypt(u8 *dst, const u8 *src, const size_t src_len, 171 171 const u8 *ad, const size_t ad_len, 172 172 const u64 nonce, 173 - const u8 key[CHACHA20POLY1305_KEY_SIZE]) 173 + const u8 key[at_least CHACHA20POLY1305_KEY_SIZE]) 174 174 { 175 175 struct chacha_state chacha_state; 176 176 u32 k[CHACHA_KEY_WORDS]; ··· 195 195 196 196 bool xchacha20poly1305_decrypt(u8 *dst, const u8 *src, const size_t src_len, 197 197 const u8 *ad, const size_t ad_len, 198 - const u8 nonce[XCHACHA20POLY1305_NONCE_SIZE], 199 - const u8 key[CHACHA20POLY1305_KEY_SIZE]) 198 + const u8 nonce[at_least XCHACHA20POLY1305_NONCE_SIZE], 199 + const u8 key[at_least CHACHA20POLY1305_KEY_SIZE]) 200 200 { 201 201 struct chacha_state chacha_state; 202 202 ··· 211 211 const size_t src_len, 212 212 const u8 *ad, const size_t ad_len, 213 213 const u64 nonce, 214 - const u8 key[CHACHA20POLY1305_KEY_SIZE], 214 + const u8 key[at_least CHACHA20POLY1305_KEY_SIZE], 215 215 int encrypt) 216 216 { 217 217 const u8 *pad0 = page_address(ZERO_PAGE(0)); ··· 335 335 bool chacha20poly1305_encrypt_sg_inplace(struct scatterlist *src, size_t src_len, 336 336 const u8 *ad, const size_t ad_len, 337 337 const u64 nonce, 338 - const u8 key[CHACHA20POLY1305_KEY_SIZE]) 338 + const u8 key[at_least CHACHA20POLY1305_KEY_SIZE]) 339 339 { 340 340 return chacha20poly1305_crypt_sg_inplace(src, src_len, ad, ad_len, 341 341 nonce, key, 1); ··· 345 345 bool chacha20poly1305_decrypt_sg_inplace(struct scatterlist *src, size_t src_len, 346 346 const u8 *ad, const size_t ad_len, 347 347 const u64 nonce, 348 - const u8 key[CHACHA20POLY1305_KEY_SIZE]) 348 + const u8 key[at_least CHACHA20POLY1305_KEY_SIZE]) 349 349 { 350 350 if (unlikely(src_len < POLY1305_DIGEST_SIZE)) 351 351 return false;