Fix stack buffer overflow in aes_ccm_encr for partial blocks (#11347)

* Fix out-of-bounds write in aes_ccm_encr for partial blocks

aes_ccm_encr() writes a full 16-byte AES block to the output before XOR-ing with
the input, so a trailing partial block writes up to 15 bytes past the length the
caller asked for. Every caller in the tree passes a buffer with enough slack, so
nothing misbehaves today, but the decrypt path clears it by only a few bytes.

Encrypt into a temporary block and XOR out of it, matching what
aes_ccm_encr_auth() and aes_ccm_decr_auth() already do in this same file. The
ciphertext is unchanged.

* Add regression test for the CCM partial-block write and drop stale workarounds

The guard bytes past the caller's buffer catch the overflow without relying on a
sanitizer, so the test is meaningful in the native environment too.

encryptCurve25519() no longer needs to write extraNonce before aes_ccm_ae(): the
call stays inside numBytes now, so the copy after it is the only one required.
The comment warning about the 15-byte overshoot no longer describes the code.
This commit is contained in:
Matias Denda
2026-08-04 22:31:38 +00:00
committed by GitHub
parent 39e7aa6a6c
commit 1dde97f807
3 changed files with 42 additions and 6 deletions
+3 -2
View File
@@ -111,11 +111,12 @@ static void aes_ccm_encr(size_t L, const uint8_t *in, size_t len, uint8_t *out,
in += AES_BLOCK_SIZE;
}
if (last) {
uint8_t tmp[AES_BLOCK_SIZE];
WPA_PUT_BE16(&a[AES_BLOCK_SIZE - 2], i);
crypto->aesEncrypt(a, out);
crypto->aesEncrypt(a, tmp);
/* XOR zero-padded last block */
for (i = 0; i < last; i++)
*out++ ^= *in++;
out[i] = tmp[i] ^ in[i];
}
}
static void aes_ccm_encr_auth(size_t M, const uint8_t *x, uint8_t *a, uint8_t *auth)