From: Mathias Kresin Date: Sun, 18 Apr 2021 12:26:01 +0000 (+0200) Subject: ltq-deu: aes: do not read/write behind buffer X-Git-Tag: v22.03.0-rc1~827 X-Git-Url: http://git.cdn.openwrt.org/?a=commitdiff_plain;h=ab270c6fbc38f81669529300daee85b809111c39;p=openwrt%2Fstaging%2Fhauke.git ltq-deu: aes: do not read/write behind buffer When handling non-aligned remaining data (not padded to 16 byte [AES_BLOCK_SIZE]), a full 16 byte block is read from the input buffer and written to the output buffer after en-/decryption. While code already assumes that an input buffer could have less than 16 byte remaining, as it can be seen by the code zeroing the remaining bytes till AES_BLOCK_SIZE, the full AES_BLOCK_SIZE is read. An output buffer size of a multiple of AES_BLOCK_SIZE is expected but never validated. To get rid of the read/write behind buffer, use a temporary buffer when dealing with not padded data and only write as much bytes to the output as we read. Do not memcpy directly to the register, to make used of the endian swap macro and to trigger the crypto start operator via the ID0R to trigger the register. Since we might need an endian swap for the output in future, use a temporary buffer for the output as well. The issue could not be observed so far, since all caller of ifx_deu_aes will ignore the padded (remaining) data. Considering that the minimum blocksize for the algorithm is set to AES_BLOCK_SIZE, the behaviour could be called expected. Signed-off-by: Mathias Kresin [fix commit title prefix] Signed-off-by: Daniel Kestrel --- diff --git a/package/kernel/lantiq/ltq-deu/src/ifxmips_aes.c b/package/kernel/lantiq/ltq-deu/src/ifxmips_aes.c index 7ce6df0ac6..62ce563181 100644 --- a/package/kernel/lantiq/ltq-deu/src/ifxmips_aes.c +++ b/package/kernel/lantiq/ltq-deu/src/ifxmips_aes.c @@ -251,23 +251,25 @@ void ifx_deu_aes (void *ctx_arg, u8 *out_arg, const u8 *in_arg, /* To handle all non-aligned bytes (not aligned to 16B size) */ if (byte_cnt) { - aes->ID3R = INPUT_ENDIAN_SWAP(*((u32 *) in_arg + (i * 4) + 0)); - aes->ID2R = INPUT_ENDIAN_SWAP(*((u32 *) in_arg + (i * 4) + 1)); - aes->ID1R = INPUT_ENDIAN_SWAP(*((u32 *) in_arg + (i * 4) + 2)); - aes->ID0R = INPUT_ENDIAN_SWAP(*((u32 *) in_arg + (i * 4) + 3)); /* start crypto */ + u8 *input[16]; + u8 *output[16]; + + memcpy(input, ((u32 *) in_arg + (i * 4)), byte_cnt); + + aes->ID3R = INPUT_ENDIAN_SWAP(*((u32 *) input + (i * 4) + 0)); + aes->ID2R = INPUT_ENDIAN_SWAP(*((u32 *) input + (i * 4) + 1)); + aes->ID1R = INPUT_ENDIAN_SWAP(*((u32 *) input + (i * 4) + 2)); + aes->ID0R = INPUT_ENDIAN_SWAP(*((u32 *) input + (i * 4) + 3)); /* start crypto */ while (aes->controlr.BUS) { } - *((volatile u32 *) out_arg + (i * 4) + 0) = aes->OD3R; - *((volatile u32 *) out_arg + (i * 4) + 1) = aes->OD2R; - *((volatile u32 *) out_arg + (i * 4) + 2) = aes->OD1R; - *((volatile u32 *) out_arg + (i * 4) + 3) = aes->OD0R; - - /* to ensure that the extended pages are clean */ - memset (out_arg + (i * 16) + (nbytes % AES_BLOCK_SIZE), 0, - (AES_BLOCK_SIZE - (nbytes % AES_BLOCK_SIZE))); + *((volatile u32 *) output + (i * 4) + 0) = aes->OD3R; + *((volatile u32 *) output + (i * 4) + 1) = aes->OD2R; + *((volatile u32 *) output + (i * 4) + 2) = aes->OD1R; + *((volatile u32 *) output + (i * 4) + 3) = aes->OD0R; + memcpy(((u32 *) out_arg + (i * 4)), output, byte_cnt); } //tc.chen : copy iv_arg back