aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorMark Johnston <markj@FreeBSD.org>2021-08-30 18:22:20 +0000
committerMark Johnston <markj@FreeBSD.org>2021-09-06 16:29:51 +0000
commit9ca533bfb45aa45d95e434d2682d5c5b667fb022 (patch)
tree31706b06bc504c642508d9e3fa71be9b43f6b96a /sys
parent2ea6ae7cc8146d2c05e266f80f00d35e9dc6dc24 (diff)
downloadsrc-9ca533bfb45aa45d95e434d2682d5c5b667fb022.tar.gz
src-9ca533bfb45aa45d95e434d2682d5c5b667fb022.zip
aesni: Avoid a potential out-of-bounds load in aes_encrypt_icm()
Given a partial block at the end of a payload, aes_encrypt_icm() would perform a 16-byte load of the residual into a temporary variable. This is unsafe in principle since the full block may cross a page boundary. Fix the problem by copying the residual into a stack buffer first. Reported by: syzbot+b7e44cde9e2e89f0f6c9@syzkaller.appspotmail.com Reported by: syzbot+4b5eaf123a99456b5160@syzkaller.appspotmail.com Reported by: syzbot+70c74c1aa232633355ca@syzkaller.appspotmail.com Reported by: syzbot+2c663776a52828373d41@syzkaller.appspotmail.com Reviewed by: cem, jhb Sponsored by: The FreeBSD Foundation (cherry picked from commit 564b6aa7fccd98654207447f870b82659b895e7b)
Diffstat (limited to 'sys')
-rw-r--r--sys/crypto/aesni/aesni_wrap.c18
1 files changed, 13 insertions, 5 deletions
diff --git a/sys/crypto/aesni/aesni_wrap.c b/sys/crypto/aesni/aesni_wrap.c
index a8a8ae749c77..f3ba09131c1e 100644
--- a/sys/crypto/aesni/aesni_wrap.c
+++ b/sys/crypto/aesni/aesni_wrap.c
@@ -213,9 +213,10 @@ aesni_encrypt_icm(int rounds, const void *key_schedule, size_t len,
__m128i ctr5, ctr6, ctr7, ctr8;
__m128i BSWAP_EPI64;
__m128i tout[8];
+ __m128i block;
struct blocks8 *top;
const struct blocks8 *blks;
- size_t i, cnt;
+ size_t i, cnt, resid;
BSWAP_EPI64 = _mm_set_epi8(8,9,10,11,12,13,14,15,0,1,2,3,4,5,6,7);
@@ -273,12 +274,19 @@ aesni_encrypt_icm(int rounds, const void *key_schedule, size_t len,
to += AES_BLOCK_LEN;
}
- /* handle remaining partial round */
- if (len % AES_BLOCK_LEN != 0) {
+ /*
+ * Handle remaining partial round. Copy the remaining payload onto the
+ * stack to ensure that the full block can be loaded safely.
+ */
+ resid = len % AES_BLOCK_LEN;
+ if (resid != 0) {
tmp1 = _mm_shuffle_epi8(ctr1, BSWAP_EPI64);
tot = aesni_enc(rounds - 1, key_schedule, tmp1);
- tot = tot ^ _mm_loadu_si128((const __m128i *)from);
- memcpy(to, &tot, len % AES_BLOCK_LEN);
+ block = _mm_setzero_si128();
+ memcpy(&block, from, resid);
+ tot = tot ^ _mm_loadu_si128(&block);
+ memcpy(to, &tot, resid);
+ explicit_bzero(&block, sizeof(block));
}
}