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