[PATCH v1 1/3] lib: aes: reject a ciphertext length that is not a whole number of blocks
Pranav Rajendran <[email protected]>
| Newsgroups | gmane.comp.boot-loaders.u-boot |
|---|---|
| Message-ID | <20260815220754.11724-2-pranavkasthuri__10115.1800643251$1786834145$gmane$org@gmail.com> |
image_aes_decrypt() allocates cipher_len bytes for the plaintext but
then asks aes_cbc_decrypt_blocks() to write
DIV_ROUND_UP(cipher_len, AES_BLOCK_LENGTH) blocks into it. For a
cipher_len that is not a multiple of AES_BLOCK_LENGTH the rounding up
adds one block, so the last block is written up to AES_BLOCK_LENGTH - 1
bytes past the end of the allocation, and read the same distance past
the end of the ciphertext.
cipher_len is the size of the image data in the FIT, so an image with a
'data' property whose length is not block aligned is enough to reach
this. The overflowing bytes are decryption output, i.e. they depend on
the key, but the length itself is not covered by anything that would
stop the image from being parsed this far.
A CBC ciphertext is a whole number of blocks by construction, so treat
anything else as a malformed image and reject it before allocating.
With that established, compute the block count with a plain division so
the buffer size and the write length cannot drift apart again.
Fixes: 4df3578119b0 ("u-boot: fit: add support to decrypt fit with aes")
Signed-off-by: Pranav Rajendran <[email protected]>
---
lib/aes/aes-decrypt.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/lib/aes/aes-decrypt.c b/lib/aes/aes-decrypt.c
index 741102a4723..85773a9c4f6 100644
--- a/lib/aes/aes-decrypt.c
+++ b/lib/aes/aes-decrypt.c
@@ -17,6 +17,16 @@ int image_aes_decrypt(struct image_cipher_info *info,
unsigned char key_exp[AES256_EXPAND_KEY_LENGTH];
unsigned int aes_blocks, key_len = info->cipher->key_len;
+ /*
+ * The ciphertext is a whole number of AES blocks by construction, and
+ * the decryption below writes one full block at a time, so anything
+ * else would overflow the output buffer.
+ */
+ if (!cipher_len || cipher_len % AES_BLOCK_LENGTH) {
+ printf("Invalid ciphertext length\n");
+ return -EINVAL;
+ }
+
*data = malloc(cipher_len);
if (!*data) {
printf("Can't allocate memory to decrypt\n");
@@ -30,7 +40,7 @@ int image_aes_decrypt(struct image_cipher_info *info,
aes_expand_key((u8 *)info->key, key_len, key_exp);
/* Calculate the number of AES blocks to encrypt. */
- aes_blocks = DIV_ROUND_UP(cipher_len, AES_BLOCK_LENGTH);
+ aes_blocks = cipher_len / AES_BLOCK_LENGTH;
aes_cbc_decrypt_blocks(key_len, key_exp, (u8 *)info->iv,
(u8 *)cipher, *data, aes_blocks);
--
2.50.1 (Apple Git-155)