summaryrefslogtreecommitdiffstats
path: root/sys/net80211
diff options
context:
space:
mode:
authorsam <sam@FreeBSD.org>2008-08-29 05:02:10 +0000
committersam <sam@FreeBSD.org>2008-08-29 05:02:10 +0000
commite920342cd46a6e2b57b701fa655a92aa3159605e (patch)
tree7ef0bd12ae3bcd01e5d30b34292ae8dcc3623118 /sys/net80211
parent743ae14c809633e69d2ef724ef9ec1d47c62f73f (diff)
downloadFreeBSD-src-e920342cd46a6e2b57b701fa655a92aa3159605e.zip
FreeBSD-src-e920342cd46a6e2b57b701fa655a92aa3159605e.tar.gz
Fix mic calculation when final data is entirely in a trailing mbuf;
it's unclear if this can happen on freebsd but does appear on netbsd. Identified by Matthias Drochner who came up with an initial change that we then revised together. Reviewed by: thompsa, sephe, avatar MFC after: 2 weeks
Diffstat (limited to 'sys/net80211')
-rw-r--r--sys/net80211/ieee80211_crypto_tkip.c20
1 files changed, 19 insertions, 1 deletions
diff --git a/sys/net80211/ieee80211_crypto_tkip.c b/sys/net80211/ieee80211_crypto_tkip.c
index 0e6bc78..fc963ca 100644
--- a/sys/net80211/ieee80211_crypto_tkip.c
+++ b/sys/net80211/ieee80211_crypto_tkip.c
@@ -831,7 +831,17 @@ michael_mic(struct tkip_ctx *ctx, const u8 *key,
data += sizeof(uint32_t), space -= sizeof(uint32_t);
data_len -= sizeof(uint32_t);
}
- if (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 == 0 ||
+ (data_len < sizeof(uint32_t) && space != 0))
break;
m = m->m_next;
if (m == NULL) {
@@ -878,6 +888,14 @@ michael_mic(struct tkip_ctx *ctx, const u8 *key,
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,
+ ("not enough data, data_len %u space %u\n", data_len, space));
+
/* Last block and padding (0x5a, 4..7 x 0) */
switch (data_len) {
case 0:
OpenPOWER on IntegriCloud