Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/net80211 make michael_mic() robust against degenerate mb...
details: https://anonhg.NetBSD.org/src/rev/9217fabca167
branches: trunk
changeset: 763759:9217fabca167
user: drochner <drochner%NetBSD.org@localhost>
date: Sun Apr 03 10:04:32 2011 +0000
description:
make michael_mic() robust against degenerate mbuf layouts like
odd sizes in the middle of a chain
diffstat:
sys/net80211/ieee80211_crypto_tkip.c | 109 ++++++++++------------------------
1 files changed, 34 insertions(+), 75 deletions(-)
diffs (144 lines):
diff -r b1894655e955 -r 9217fabca167 sys/net80211/ieee80211_crypto_tkip.c
--- a/sys/net80211/ieee80211_crypto_tkip.c Sun Apr 03 06:54:30 2011 +0000
+++ b/sys/net80211/ieee80211_crypto_tkip.c Sun Apr 03 10:04:32 2011 +0000
@@ -34,7 +34,7 @@
__FBSDID("$FreeBSD: src/sys/net80211/ieee80211_crypto_tkip.c,v 1.10 2005/08/08 18:46:35 sam Exp $");
#endif
#ifdef __NetBSD__
-__KERNEL_RCSID(0, "$NetBSD: ieee80211_crypto_tkip.c,v 1.10 2008/12/17 20:51:37 cegger Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ieee80211_crypto_tkip.c,v 1.11 2011/04/03 10:04:32 drochner Exp $");
#endif
/*
@@ -802,6 +802,8 @@
u32 l, r;
const uint8_t *data;
u_int space;
+ uint8_t spill[4];
+ int nspill = 0;
michael_mic_hdr(mtod(m, struct ieee80211_frame *), hdr);
@@ -824,6 +826,20 @@
for (;;) {
if (space > data_len)
space = data_len;
+ if (nspill) {
+ int n = min(4 - nspill, space);
+ memcpy(spill + nspill, data, n);
+ nspill += n;
+ data += n;
+ space -= n;
+ data_len -= n;
+ if (nspill == 4) {
+ l ^= get_le32(spill);
+ michael_block(l, r);
+ nspill = 0;
+ } else
+ goto next;
+ }
/* collect 32-bit blocks from current buffer */
while (space >= sizeof(uint32_t)) {
l ^= get_le32(data);
@@ -832,84 +848,27 @@
space -= sizeof(uint32_t);
data_len -= sizeof(uint32_t);
}
- /*
- * NB: when space is zero we make one more trip around
- * the loop to advance to the next mbuf where there is
- * data. This handles the case where there are 4*n
- * bytes in an mbuf followed by <4 bytes in a later mbuf.
- * By making an extra trip we'll drop out of the loop
- * with m pointing at the mbuf with 3 bytes and space
- * set as required by the remainder handling below.
- */
- if (!data_len || (data_len < sizeof(uint32_t) && space != 0))
+ if (space) {
+ memcpy(spill, data, space);
+ nspill = space;
+ data_len -= space;
+ }
+next:
+ if (!data_len)
break;
m = m->m_next;
- if (m == NULL) {
- IASSERT(0, ("out of data, data_len %zu\n", data_len));
- break;
- }
- if (space != 0) {
- const uint8_t *data_next;
- /*
- * Block straddles buffers, split references.
- */
- data_next = mtod(m, const uint8_t *);
- IASSERT(m->m_len >= sizeof(uint32_t) - space,
- ("not enough data in following buffer, "
- "m_len %u need %zu\n", m->m_len,
- sizeof(uint32_t) - space));
- switch (space) {
- case 1:
- l ^= get_le32_split(data[0], data_next[0],
- data_next[1], data_next[2]);
- data = data_next + 3;
- space = m->m_len - 3;
- break;
- case 2:
- l ^= get_le32_split(data[0], data[1],
- data_next[0], data_next[1]);
- data = data_next + 2;
- space = m->m_len - 2;
- break;
- case 3:
- l ^= get_le32_split(data[0], data[1],
- data[2], data_next[0]);
- data = data_next + 1;
- space = m->m_len - 1;
- break;
- }
- michael_block(l, r);
- data_len -= sizeof(uint32_t);
- } else {
- /*
- * Setup for next buffer.
- */
- data = mtod(m, const uint8_t *);
- space = m->m_len;
- }
+ KASSERT(m);
+ /*
+ * Setup for next buffer.
+ */
+ data = mtod(m, const uint8_t *);
+ space = m->m_len;
}
- /*
- * Catch degenerate cases like mbuf[4*n+1 bytes] followed by
- * mbuf[2 bytes]. I don't believe these should happen; if they
- * do then we'll need more involved logic.
- */
- KASSERT(data_len <= space);
-
/* Last block and padding (0x5a, 4..7 x 0) */
- switch (data_len) {
- case 0:
- l ^= get_le32_split(0x5a, 0, 0, 0);
- break;
- case 1:
- l ^= get_le32_split(data[0], 0x5a, 0, 0);
- break;
- case 2:
- l ^= get_le32_split(data[0], data[1], 0x5a, 0);
- break;
- case 3:
- l ^= get_le32_split(data[0], data[1], data[2], 0x5a);
- break;
- }
+ spill[nspill++] = 0x5a;
+ for (; nspill < 4; nspill++)
+ spill[nspill] = 0;
+ l ^= get_le32(spill);
michael_block(l, r);
/* l ^= 0; */
michael_block(l, r);
Home |
Main Index |
Thread Index |
Old Index