[BACK]Return to ieee80211_crypto.c CVS log [TXT][DIR] Up to [local] / sys / net80211

Annotation of sys/net80211/ieee80211_crypto.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: ieee80211_crypto.c,v 1.31 2007/08/03 16:51:06 damien Exp $    */
        !             2: /*     $NetBSD: ieee80211_crypto.c,v 1.5 2003/12/14 09:56:53 dyoung Exp $      */
        !             3:
        !             4: /*-
        !             5:  * Copyright (c) 2001 Atsushi Onoe
        !             6:  * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting
        !             7:  * Copyright (c) 2007 Damien Bergamini
        !             8:  * All rights reserved.
        !             9:  *
        !            10:  * Redistribution and use in source and binary forms, with or without
        !            11:  * modification, are permitted provided that the following conditions
        !            12:  * are met:
        !            13:  * 1. Redistributions of source code must retain the above copyright
        !            14:  *    notice, this list of conditions and the following disclaimer.
        !            15:  * 2. Redistributions in binary form must reproduce the above copyright
        !            16:  *    notice, this list of conditions and the following disclaimer in the
        !            17:  *    documentation and/or other materials provided with the distribution.
        !            18:  * 3. The name of the author may not be used to endorse or promote products
        !            19:  *    derived from this software without specific prior written permission.
        !            20:  *
        !            21:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
        !            22:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
        !            23:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
        !            24:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
        !            25:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
        !            26:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
        !            27:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
        !            28:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
        !            29:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
        !            30:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
        !            31:  */
        !            32:
        !            33: #include "bpfilter.h"
        !            34:
        !            35: #include <sys/param.h>
        !            36: #include <sys/systm.h>
        !            37: #include <sys/mbuf.h>
        !            38: #include <sys/malloc.h>
        !            39: #include <sys/kernel.h>
        !            40: #include <sys/socket.h>
        !            41: #include <sys/sockio.h>
        !            42: #include <sys/endian.h>
        !            43: #include <sys/errno.h>
        !            44: #include <sys/proc.h>
        !            45: #include <sys/sysctl.h>
        !            46:
        !            47: #include <net/if.h>
        !            48: #include <net/if_dl.h>
        !            49: #include <net/if_media.h>
        !            50: #include <net/if_arp.h>
        !            51: #include <net/if_llc.h>
        !            52:
        !            53: #if NBPFILTER > 0
        !            54: #include <net/bpf.h>
        !            55: #endif
        !            56:
        !            57: #ifdef INET
        !            58: #include <netinet/in.h>
        !            59: #include <netinet/if_ether.h>
        !            60: #endif
        !            61:
        !            62: #include <net80211/ieee80211_var.h>
        !            63:
        !            64: #include <dev/rndvar.h>
        !            65: #include <crypto/arc4.h>
        !            66: #include <crypto/md5.h>
        !            67: #include <crypto/sha1.h>
        !            68: #include <crypto/rijndael.h>
        !            69:
        !            70: struct vector {
        !            71:        const void      *base;
        !            72:        size_t          len;
        !            73: };
        !            74:
        !            75: void   ieee80211_crc_init(void);
        !            76: u_int32_t ieee80211_crc_update(u_int32_t, const u_int8_t *, int);
        !            77: struct mbuf *ieee80211_ccmp_encrypt(struct ieee80211com *, struct mbuf *,
        !            78:            struct ieee80211_key *);
        !            79: struct mbuf *ieee80211_ccmp_decrypt(struct ieee80211com *, struct mbuf *,
        !            80:            struct ieee80211_key *);
        !            81: struct mbuf *ieee80211_tkip_encrypt(struct ieee80211com *, struct mbuf *,
        !            82:            struct ieee80211_key *);
        !            83: struct mbuf *ieee80211_tkip_decrypt(struct ieee80211com *, struct mbuf *,
        !            84:            struct ieee80211_key *);
        !            85: void   ieee80211_aes_key_wrap(const u_int8_t *, size_t, const u_int8_t *,
        !            86:            size_t, u_int8_t *);
        !            87: int    ieee80211_aes_key_unwrap(const u_int8_t *, size_t, const u_int8_t *,
        !            88:            u_int8_t *, size_t);
        !            89: void   ieee80211_hmac_md5_v(const struct vector *, int, const u_int8_t *,
        !            90:            size_t, u_int8_t digest[]);
        !            91: void   ieee80211_hmac_md5(const u_int8_t *, size_t, const u_int8_t *, size_t,
        !            92:            u_int8_t digest[]);
        !            93: void   ieee80211_hmac_sha1_v(const struct vector *, int, const u_int8_t *,
        !            94:            size_t, u_int8_t digest[]);
        !            95: void   ieee80211_hmac_sha1(const u_int8_t *, size_t, const u_int8_t *, size_t,
        !            96:            u_int8_t digest[]);
        !            97: void   ieee80211_prf(const u_int8_t *, size_t, struct vector *, int,
        !            98:            u_int8_t *, size_t);
        !            99: void   ieee80211_derive_pmkid(const u_int8_t *, size_t, const u_int8_t *,
        !           100:            const u_int8_t *, u_int8_t *);
        !           101: void   ieee80211_derive_gtk(const u_int8_t *, size_t, const u_int8_t *,
        !           102:            const u_int8_t *, u_int8_t *, size_t);
        !           103:
        !           104: void
        !           105: ieee80211_crypto_attach(struct ifnet *ifp)
        !           106: {
        !           107:        struct ieee80211com *ic = (void *)ifp;
        !           108:
        !           109:        ieee80211_crc_init();
        !           110:
        !           111:        /* initialize 256-bit global key counter to a random value */
        !           112:        get_random_bytes(ic->ic_globalcnt, EAPOL_KEY_NONCE_LEN);
        !           113: }
        !           114:
        !           115: void
        !           116: ieee80211_crypto_detach(struct ifnet *ifp)
        !           117: {
        !           118:        struct ieee80211com *ic = (void *)ifp;
        !           119:
        !           120:        if (ic->ic_wep_ctx != NULL) {
        !           121:                free(ic->ic_wep_ctx, M_DEVBUF);
        !           122:                ic->ic_wep_ctx = NULL;
        !           123:        }
        !           124: }
        !           125:
        !           126: struct mbuf *
        !           127: ieee80211_encrypt(struct ieee80211com *ic, struct mbuf *m0,
        !           128:     struct ieee80211_node *ni)
        !           129: {
        !           130:        struct ieee80211_frame *wh;
        !           131:        struct ieee80211_key *k;
        !           132:
        !           133:        /* select the key for encryption */
        !           134:        wh = mtod(m0, struct ieee80211_frame *);
        !           135:        if (IEEE80211_IS_MULTICAST(wh->i_addr1) ||
        !           136:            ni->ni_pairwise_cipher == IEEE80211_CIPHER_USEGROUP)
        !           137:                k = &ic->ic_nw_keys[ic->ic_wep_txkey];
        !           138:        else
        !           139:                k = &ni->ni_pairwise_key;
        !           140:
        !           141:        switch (k->k_cipher) {
        !           142:        case IEEE80211_CIPHER_WEP40:
        !           143:        case IEEE80211_CIPHER_WEP104:
        !           144:                m0 = ieee80211_wep_crypt(&ic->ic_if, m0, 1);
        !           145:                break;
        !           146:        case IEEE80211_CIPHER_TKIP:
        !           147:                m0 = ieee80211_tkip_encrypt(ic, m0, k);
        !           148:                break;
        !           149:        case IEEE80211_CIPHER_CCMP:
        !           150:                m0 = ieee80211_ccmp_encrypt(ic, m0, k);
        !           151:                break;
        !           152:        default:
        !           153:                /* should not get there */
        !           154:                m_freem(m0);
        !           155:                m0 = NULL;
        !           156:        }
        !           157:        return m0;
        !           158: }
        !           159:
        !           160: struct mbuf *
        !           161: ieee80211_decrypt(struct ieee80211com *ic, struct mbuf *m0,
        !           162:     struct ieee80211_node *ni)
        !           163: {
        !           164:        struct ieee80211_frame *wh;
        !           165:        struct ieee80211_key *k;
        !           166:
        !           167:        /* select the key for decryption */
        !           168:        wh = mtod(m0, struct ieee80211_frame *);
        !           169:        if (IEEE80211_IS_MULTICAST(wh->i_addr1) ||
        !           170:            ni->ni_pairwise_cipher == IEEE80211_CIPHER_USEGROUP) {
        !           171:                size_t hdrlen = sizeof(*wh);    /* XXX QoS */
        !           172:                u_int8_t *ivp = (u_int8_t *)wh + hdrlen;
        !           173:                /* key identifier is always located at the same index */
        !           174:                int kid = ivp[IEEE80211_WEP_IVLEN] >> 6;
        !           175:                k = &ic->ic_nw_keys[kid];
        !           176:        } else
        !           177:                k = &ni->ni_pairwise_key;
        !           178:
        !           179:        switch (k->k_cipher) {
        !           180:        case IEEE80211_CIPHER_WEP40:
        !           181:        case IEEE80211_CIPHER_WEP104:
        !           182:                m0 = ieee80211_wep_crypt(&ic->ic_if, m0, 0);
        !           183:                break;
        !           184:        case IEEE80211_CIPHER_TKIP:
        !           185:                m0 = ieee80211_tkip_decrypt(ic, m0, k);
        !           186:                break;
        !           187:        case IEEE80211_CIPHER_CCMP:
        !           188:                m0 = ieee80211_ccmp_decrypt(ic, m0, k);
        !           189:                break;
        !           190:        default:
        !           191:                /* should not get there */
        !           192:                m_freem(m0);
        !           193:                m0 = NULL;
        !           194:        }
        !           195:        return m0;
        !           196: }
        !           197:
        !           198: #define IEEE80211_CCMP_HDRLEN  8
        !           199: #define IEEE80211_CCMP_MICLEN  8
        !           200:
        !           201: struct mbuf *
        !           202: ieee80211_ccmp_encrypt(struct ieee80211com *ic, struct mbuf *m0,
        !           203:     struct ieee80211_key *k)
        !           204: {
        !           205:        struct ieee80211_frame *wh;
        !           206:        size_t hdrlen = sizeof(*wh);    /* XXX QoS */
        !           207:        u_int8_t *ivp;
        !           208:
        !           209:        M_PREPEND(m0, IEEE80211_CCMP_HDRLEN, M_NOWAIT);
        !           210:        if (m0 == NULL)
        !           211:                return m0;
        !           212:        wh = mtod(m0, struct ieee80211_frame *);
        !           213:        ovbcopy(mtod(m0, u_int8_t *) + IEEE80211_CCMP_HDRLEN, wh, hdrlen);
        !           214:        ivp = (u_int8_t *)wh + hdrlen;
        !           215:
        !           216:        k->k_tsc++;     /* increment the 48-bit PN */
        !           217:        ivp[0] = k->k_tsc;              /* PN0 */
        !           218:        ivp[1] = k->k_tsc >> 8;         /* PN1 */
        !           219:        ivp[2] = 0;                     /* Rsvd */
        !           220:        ivp[3] = k->k_id << 6 | IEEE80211_WEP_EXTIV;    /* KeyID | ExtIV */
        !           221:        ivp[4] = k->k_tsc >> 16;        /* PN2 */
        !           222:        ivp[5] = k->k_tsc >> 24;        /* PN3 */
        !           223:        ivp[6] = k->k_tsc >> 32;        /* PN4 */
        !           224:        ivp[7] = k->k_tsc >> 40;        /* PN5 */
        !           225:
        !           226:        /* XXX encrypt payload if HW encryption not supported */
        !           227:
        !           228:        return m0;
        !           229: }
        !           230:
        !           231: struct mbuf *
        !           232: ieee80211_ccmp_decrypt(struct ieee80211com *ic, struct mbuf *m0,
        !           233:     struct ieee80211_key *k)
        !           234: {
        !           235:        struct ieee80211_frame *wh;
        !           236:        size_t hdrlen = sizeof(*wh);    /* XXX QoS */
        !           237:        u_int64_t pn;
        !           238:        u_int8_t *ivp;
        !           239:
        !           240:        wh = mtod(m0, struct ieee80211_frame *);
        !           241:        ivp = (u_int8_t *)wh + hdrlen;
        !           242:
        !           243:        /* check that ExtIV bit is be set */
        !           244:        if (!(ivp[3] & IEEE80211_WEP_EXTIV)) {
        !           245:                m_freem(m0);
        !           246:                return NULL;
        !           247:        }
        !           248:        /* extract the 48-bit PN from the CCMP header */
        !           249:        pn = (u_int64_t)ivp[0]       |
        !           250:             (u_int64_t)ivp[1] <<  8 |
        !           251:             (u_int64_t)ivp[4] << 16 |
        !           252:             (u_int64_t)ivp[5] << 24 |
        !           253:             (u_int64_t)ivp[6] << 32 |
        !           254:             (u_int64_t)ivp[7] << 40;
        !           255:        /* NB: the keys are refreshed, we'll never overflow the 48 bits */
        !           256:        if (pn <= k->k_rsc) {
        !           257:                /* replayed frame, discard */
        !           258:                /* XXX statistics */
        !           259:                m_freem(m0);
        !           260:                return NULL;
        !           261:        }
        !           262:
        !           263:        /* XXX decrypt payload if HW encryption not supported */
        !           264:
        !           265:        ovbcopy(mtod(m0, u_int8_t *),
        !           266:            mtod(m0, u_int8_t *) + IEEE80211_CCMP_HDRLEN, hdrlen);
        !           267:        m_adj(m0, IEEE80211_CCMP_HDRLEN);
        !           268:        m_adj(m0, -IEEE80211_CCMP_MICLEN);
        !           269:
        !           270:        /* update last seen packet number */
        !           271:        k->k_rsc = pn;
        !           272:
        !           273:        return m0;
        !           274: }
        !           275:
        !           276: #define IEEE80211_TKIP_HDRLEN  8
        !           277: #define IEEE80211_TKIP_MICLEN  8
        !           278: #define IEEE80211_TKIP_ICVLEN  4
        !           279:
        !           280: struct mbuf *
        !           281: ieee80211_tkip_encrypt(struct ieee80211com *ic, struct mbuf *m0,
        !           282:     struct ieee80211_key *k)
        !           283: {
        !           284:        struct ieee80211_frame *wh;
        !           285:        size_t hdrlen = sizeof(*wh);    /* XXX QoS */
        !           286:        u_int8_t *ivp;
        !           287:
        !           288:        M_PREPEND(m0, IEEE80211_TKIP_HDRLEN, M_NOWAIT);
        !           289:        if (m0 == NULL)
        !           290:                return m0;
        !           291:        wh = mtod(m0, struct ieee80211_frame *);
        !           292:        ovbcopy(mtod(m0, u_int8_t *) + IEEE80211_TKIP_HDRLEN, wh, hdrlen);
        !           293:        ivp = (u_int8_t *)wh + hdrlen;
        !           294:
        !           295:        ivp[0] = k->k_tsc >> 8;         /* TSC1 */
        !           296:        /* WEP Seed = (TSC1 | 0x20) & 0x7f (see 8.3.2.2) */
        !           297:        ivp[1] = (ivp[0] | 0x20) & 0x7f;
        !           298:        ivp[2] = k->k_tsc;              /* TSC0 */
        !           299:        ivp[3] = k->k_id << 6 | IEEE80211_WEP_EXTIV;    /* KeyID | ExtIV */
        !           300:        ivp[4] = k->k_tsc >> 16;        /* TSC2 */
        !           301:        ivp[5] = k->k_tsc >> 24;        /* TSC3 */
        !           302:        ivp[6] = k->k_tsc >> 32;        /* TSC4 */
        !           303:        ivp[7] = k->k_tsc >> 40;        /* TSC5 */
        !           304:
        !           305:        /* XXX encrypt payload if HW encryption not supported */
        !           306:
        !           307:        k->k_tsc++;     /* increment the 48-bit TSC */
        !           308:
        !           309:        return m0;
        !           310: }
        !           311:
        !           312: struct mbuf *
        !           313: ieee80211_tkip_decrypt(struct ieee80211com *ic, struct mbuf *m0,
        !           314:     struct ieee80211_key *k)
        !           315: {
        !           316:        struct ieee80211_frame *wh;
        !           317:        size_t hdrlen = sizeof(*wh);    /* XXX QoS */
        !           318:        u_int64_t tsc;
        !           319:        u_int8_t *ivp;
        !           320:
        !           321:        wh = mtod(m0, struct ieee80211_frame *);
        !           322:        ivp = (u_int8_t *)wh + hdrlen;
        !           323:
        !           324:        /* check that ExtIV bit is be set */
        !           325:        if (!(ivp[3] & IEEE80211_WEP_EXTIV)) {
        !           326:                m_freem(m0);
        !           327:                return NULL;
        !           328:        }
        !           329:        /* extract the 48-bit TSC from the TKIP header */
        !           330:        tsc = (u_int64_t)ivp[2]       |
        !           331:              (u_int64_t)ivp[0] <<  8 |
        !           332:              (u_int64_t)ivp[4] << 16 |
        !           333:              (u_int64_t)ivp[5] << 24 |
        !           334:              (u_int64_t)ivp[6] << 32 |
        !           335:              (u_int64_t)ivp[7] << 40;
        !           336:        /* NB: the keys are refreshed, we'll never overflow the 48 bits */
        !           337:        if (tsc <= k->k_rsc) {
        !           338:                /* replayed frame, discard */
        !           339:                /* XXX statistics */
        !           340:                m_freem(m0);
        !           341:                return NULL;
        !           342:        }
        !           343:
        !           344:        /* XXX decrypt payload if HW encryption not supported */
        !           345:
        !           346:        ovbcopy(mtod(m0, u_int8_t *),
        !           347:            mtod(m0, u_int8_t *) + IEEE80211_TKIP_HDRLEN, hdrlen);
        !           348:        m_adj(m0, IEEE80211_TKIP_HDRLEN);
        !           349:        m_adj(m0, -IEEE80211_TKIP_ICVLEN);
        !           350:
        !           351:        /* update last seen packet number */
        !           352:        k->k_rsc = tsc;
        !           353:
        !           354:        return m0;
        !           355: }
        !           356:
        !           357: /* Round up to a multiple of IEEE80211_WEP_KEYLEN + IEEE80211_WEP_IVLEN */
        !           358: #define klen_round(x)                                                  \
        !           359:        (((x) + (IEEE80211_WEP_KEYLEN + IEEE80211_WEP_IVLEN - 1)) &     \
        !           360:        ~(IEEE80211_WEP_KEYLEN + IEEE80211_WEP_IVLEN - 1))
        !           361:
        !           362: struct mbuf *
        !           363: ieee80211_wep_crypt(struct ifnet *ifp, struct mbuf *m0, int txflag)
        !           364: {
        !           365:        struct ieee80211com *ic = (void *)ifp;
        !           366:        struct mbuf *m, *n, *n0;
        !           367:        struct ieee80211_frame *wh;
        !           368:        int i, left, len, moff, noff, kid;
        !           369:        u_int32_t iv, crc;
        !           370:        u_int8_t *ivp;
        !           371:        void *ctx;
        !           372:        u_int8_t keybuf[klen_round(IEEE80211_WEP_IVLEN + IEEE80211_KEYBUF_SIZE)];
        !           373:        u_int8_t crcbuf[IEEE80211_WEP_CRCLEN];
        !           374:
        !           375:        n0 = NULL;
        !           376:        if ((ctx = ic->ic_wep_ctx) == NULL) {
        !           377:                ctx = malloc(sizeof(struct rc4_ctx), M_DEVBUF, M_NOWAIT);
        !           378:                if (ctx == NULL) {
        !           379:                        ic->ic_stats.is_crypto_nomem++;
        !           380:                        goto fail;
        !           381:                }
        !           382:                ic->ic_wep_ctx = ctx;
        !           383:        }
        !           384:        m = m0;
        !           385:        left = m->m_pkthdr.len;
        !           386:        MGET(n, M_DONTWAIT, m->m_type);
        !           387:        n0 = n;
        !           388:        if (n == NULL) {
        !           389:                if (txflag)
        !           390:                        ic->ic_stats.is_tx_nombuf++;
        !           391:                else
        !           392:                        ic->ic_stats.is_rx_nombuf++;
        !           393:                goto fail;
        !           394:        }
        !           395:        M_DUP_PKTHDR(n, m);
        !           396:        len = IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN + IEEE80211_WEP_CRCLEN;
        !           397:        if (txflag) {
        !           398:                n->m_pkthdr.len += len;
        !           399:        } else {
        !           400:                n->m_pkthdr.len -= len;
        !           401:                left -= len;
        !           402:        }
        !           403:        n->m_len = MHLEN;
        !           404:        if (n->m_pkthdr.len >= MINCLSIZE) {
        !           405:                MCLGET(n, M_DONTWAIT);
        !           406:                if (n->m_flags & M_EXT)
        !           407:                        n->m_len = n->m_ext.ext_size;
        !           408:        }
        !           409:        wh = mtod(m, struct ieee80211_frame *);
        !           410:        if ((wh->i_fc[0] &
        !           411:             (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_QOS)) ==
        !           412:            (IEEE80211_FC0_TYPE_DATA | IEEE80211_FC0_SUBTYPE_QOS))
        !           413:                len = sizeof(struct ieee80211_qosframe);
        !           414:        else
        !           415:                len = sizeof(struct ieee80211_frame);
        !           416:        memcpy(mtod(n, caddr_t), wh, len);
        !           417:        wh = mtod(n, struct ieee80211_frame *);
        !           418:        left -= len;
        !           419:        moff = len;
        !           420:        noff = len;
        !           421:        if (txflag) {
        !           422:                kid = ic->ic_wep_txkey;
        !           423:                wh->i_fc[1] |= IEEE80211_FC1_WEP;
        !           424:                iv = ic->ic_iv ? ic->ic_iv : arc4random();
        !           425:                /*
        !           426:                 * Skip 'bad' IVs from Fluhrer/Mantin/Shamir:
        !           427:                 * (B, 255, N) with 3 <= B < 8
        !           428:                 */
        !           429:                if (iv >= 0x03ff00 &&
        !           430:                    (iv & 0xf8ff00) == 0x00ff00)
        !           431:                        iv += 0x000100;
        !           432:                ic->ic_iv = iv + 1;
        !           433:                /* put iv in little endian to prepare 802.11i */
        !           434:                ivp = mtod(n, u_int8_t *) + noff;
        !           435:                for (i = 0; i < IEEE80211_WEP_IVLEN; i++) {
        !           436:                        ivp[i] = iv & 0xff;
        !           437:                        iv >>= 8;
        !           438:                }
        !           439:                ivp[IEEE80211_WEP_IVLEN] = kid << 6;    /* pad and keyid */
        !           440:                noff += IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN;
        !           441:        } else {
        !           442:                wh->i_fc[1] &= ~IEEE80211_FC1_WEP;
        !           443:                ivp = mtod(m, u_int8_t *) + moff;
        !           444:                kid = ivp[IEEE80211_WEP_IVLEN] >> 6;
        !           445:                moff += IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN;
        !           446:        }
        !           447:
        !           448:        /*
        !           449:         * Copy the IV and the key material.  The input key has been padded
        !           450:         * with zeros by the ioctl.  The output key buffer length is rounded
        !           451:         * to a multiple of 64bit to allow variable length keys padded by
        !           452:         * zeros.
        !           453:         */
        !           454:        bzero(&keybuf, sizeof(keybuf));
        !           455:        memcpy(keybuf, ivp, IEEE80211_WEP_IVLEN);
        !           456:        memcpy(keybuf + IEEE80211_WEP_IVLEN, ic->ic_nw_keys[kid].k_key,
        !           457:            ic->ic_nw_keys[kid].k_len);
        !           458:        len = klen_round(IEEE80211_WEP_IVLEN + ic->ic_nw_keys[kid].k_len);
        !           459:        rc4_keysetup(ctx, keybuf, len);
        !           460:
        !           461:        /* encrypt with calculating CRC */
        !           462:        crc = ~0;
        !           463:        while (left > 0) {
        !           464:                len = m->m_len - moff;
        !           465:                if (len == 0) {
        !           466:                        m = m->m_next;
        !           467:                        moff = 0;
        !           468:                        continue;
        !           469:                }
        !           470:                if (len > n->m_len - noff) {
        !           471:                        len = n->m_len - noff;
        !           472:                        if (len == 0) {
        !           473:                                MGET(n->m_next, M_DONTWAIT, n->m_type);
        !           474:                                if (n->m_next == NULL) {
        !           475:                                        if (txflag)
        !           476:                                                ic->ic_stats.is_tx_nombuf++;
        !           477:                                        else
        !           478:                                                ic->ic_stats.is_rx_nombuf++;
        !           479:                                        goto fail;
        !           480:                                }
        !           481:                                n = n->m_next;
        !           482:                                n->m_len = MLEN;
        !           483:                                if (left >= MINCLSIZE) {
        !           484:                                        MCLGET(n, M_DONTWAIT);
        !           485:                                        if (n->m_flags & M_EXT)
        !           486:                                                n->m_len = n->m_ext.ext_size;
        !           487:                                }
        !           488:                                noff = 0;
        !           489:                                continue;
        !           490:                        }
        !           491:                }
        !           492:                if (len > left)
        !           493:                        len = left;
        !           494:                rc4_crypt(ctx, mtod(m, caddr_t) + moff,
        !           495:                    mtod(n, caddr_t) + noff, len);
        !           496:                if (txflag)
        !           497:                        crc = ieee80211_crc_update(crc,
        !           498:                            mtod(m, u_int8_t *) + moff, len);
        !           499:                else
        !           500:                        crc = ieee80211_crc_update(crc,
        !           501:                            mtod(n, u_int8_t *) + noff, len);
        !           502:                left -= len;
        !           503:                moff += len;
        !           504:                noff += len;
        !           505:        }
        !           506:        crc = ~crc;
        !           507:        if (txflag) {
        !           508:                *(u_int32_t *)crcbuf = htole32(crc);
        !           509:                if (n->m_len >= noff + sizeof(crcbuf))
        !           510:                        n->m_len = noff + sizeof(crcbuf);
        !           511:                else {
        !           512:                        n->m_len = noff;
        !           513:                        MGET(n->m_next, M_DONTWAIT, n->m_type);
        !           514:                        if (n->m_next == NULL) {
        !           515:                                ic->ic_stats.is_tx_nombuf++;
        !           516:                                goto fail;
        !           517:                        }
        !           518:                        n = n->m_next;
        !           519:                        n->m_len = sizeof(crcbuf);
        !           520:                        noff = 0;
        !           521:                }
        !           522:                rc4_crypt(ctx, crcbuf, mtod(n, caddr_t) + noff,
        !           523:                    sizeof(crcbuf));
        !           524:        } else {
        !           525:                n->m_len = noff;
        !           526:                for (noff = 0; noff < sizeof(crcbuf); noff += len) {
        !           527:                        len = sizeof(crcbuf) - noff;
        !           528:                        if (len > m->m_len - moff)
        !           529:                                len = m->m_len - moff;
        !           530:                        if (len > 0)
        !           531:                                rc4_crypt(ctx, mtod(m, caddr_t) + moff,
        !           532:                                    crcbuf + noff, len);
        !           533:                        m = m->m_next;
        !           534:                        moff = 0;
        !           535:                }
        !           536:                if (crc != letoh32(*(u_int32_t *)crcbuf)) {
        !           537: #ifdef IEEE80211_DEBUG
        !           538:                        if (ieee80211_debug) {
        !           539:                                printf("%s: decrypt CRC error\n",
        !           540:                                    ifp->if_xname);
        !           541:                                if (ieee80211_debug > 1)
        !           542:                                        ieee80211_dump_pkt(n0->m_data,
        !           543:                                            n0->m_len, -1, -1);
        !           544:                        }
        !           545: #endif
        !           546:                        ic->ic_stats.is_rx_decryptcrc++;
        !           547:                        goto fail;
        !           548:                }
        !           549:        }
        !           550:        m_freem(m0);
        !           551:        return n0;
        !           552:
        !           553:  fail:
        !           554:        m_freem(m0);
        !           555:        m_freem(n0);
        !           556:        return NULL;
        !           557: }
        !           558:
        !           559: /*
        !           560:  * CRC 32 -- routine from RFC 2083
        !           561:  */
        !           562:
        !           563: /* Table of CRCs of all 8-bit messages */
        !           564: static u_int32_t ieee80211_crc_table[256];
        !           565:
        !           566: /* Make the table for a fast CRC. */
        !           567: void
        !           568: ieee80211_crc_init(void)
        !           569: {
        !           570:        u_int32_t c;
        !           571:        int n, k;
        !           572:
        !           573:        for (n = 0; n < 256; n++) {
        !           574:                c = (u_int32_t)n;
        !           575:                for (k = 0; k < 8; k++) {
        !           576:                        if (c & 1)
        !           577:                                c = 0xedb88320UL ^ (c >> 1);
        !           578:                        else
        !           579:                                c = c >> 1;
        !           580:                }
        !           581:                ieee80211_crc_table[n] = c;
        !           582:        }
        !           583: }
        !           584:
        !           585: /*
        !           586:  * Update a running CRC with the bytes buf[0..len-1]--the CRC
        !           587:  * should be initialized to all 1's, and the transmitted value
        !           588:  * is the 1's complement of the final running CRC
        !           589:  */
        !           590: u_int32_t
        !           591: ieee80211_crc_update(u_int32_t crc, const u_int8_t *buf, int len)
        !           592: {
        !           593:        const u_int8_t *endbuf;
        !           594:
        !           595:        for (endbuf = buf + len; buf < endbuf; buf++)
        !           596:                crc = ieee80211_crc_table[(crc ^ *buf) & 0xff] ^ (crc >> 8);
        !           597:        return crc;
        !           598: }
        !           599:
        !           600: /*
        !           601:  * AES Key Wrap Algorithm (see RFC 3394).
        !           602:  */
        !           603: static const u_int8_t aes_key_wrap_iv[8] =
        !           604:        { 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6 };
        !           605:
        !           606: void
        !           607: ieee80211_aes_key_wrap(const u_int8_t *kek, size_t kek_len, const u_int8_t *pt,
        !           608:     size_t len, u_int8_t *ct)
        !           609: {
        !           610:        rijndael_ctx ctx;
        !           611:        u_int8_t *a, *r, ar[16];
        !           612:        u_int64_t t, b[2];
        !           613:        size_t i;
        !           614:        int j;
        !           615:
        !           616:        /* allow ciphertext and plaintext to overlap (ct == pt) */
        !           617:        ovbcopy(pt, ct + 8, len * 8);
        !           618:        a = ct;
        !           619:        memcpy(a, aes_key_wrap_iv, 8);  /* default IV */
        !           620:
        !           621:        rijndael_set_key_enc_only(&ctx, (u_int8_t *)kek, kek_len * 8);
        !           622:
        !           623:        for (j = 0, t = 1; j < 6; j++) {
        !           624:                r = ct + 8;
        !           625:                for (i = 0; i < len; i++, t++) {
        !           626:                        memcpy(ar, a, 8);
        !           627:                        memcpy(ar + 8, r, 8);
        !           628:                        rijndael_encrypt(&ctx, ar, (u_int8_t *)b);
        !           629:                        b[0] ^= htobe64(t);
        !           630:                        memcpy(a, &b[0], 8);
        !           631:                        memcpy(r, &b[1], 8);
        !           632:
        !           633:                        r += 8;
        !           634:                }
        !           635:        }
        !           636: }
        !           637:
        !           638: int
        !           639: ieee80211_aes_key_unwrap(const u_int8_t *kek, size_t kek_len,
        !           640:     const u_int8_t *ct, u_int8_t *pt, size_t len)
        !           641: {
        !           642:        rijndael_ctx ctx;
        !           643:        u_int8_t a[8], *r, b[16];
        !           644:        u_int64_t t, ar[2];
        !           645:        size_t i;
        !           646:        int j;
        !           647:
        !           648:        memcpy(a, ct, 8);
        !           649:        /* allow ciphertext and plaintext to overlap (ct == pt) */
        !           650:        ovbcopy(ct + 8, pt, len * 8);
        !           651:
        !           652:        rijndael_set_key(&ctx, (u_int8_t *)kek, kek_len * 8);
        !           653:
        !           654:        for (j = 0, t = 6 * len; j < 6; j++) {
        !           655:                r = pt + (len - 1) * 8;
        !           656:                for (i = 0; i < len; i++, t--) {
        !           657:                        memcpy(&ar[0], a, 8);
        !           658:                        ar[0] ^= htobe64(t);
        !           659:                        memcpy(&ar[1], r, 8);
        !           660:                        rijndael_decrypt(&ctx, (u_int8_t *)ar, b);
        !           661:                        memcpy(a, b, 8);
        !           662:                        memcpy(r, b + 8, 8);
        !           663:
        !           664:                        r -= 8;
        !           665:                }
        !           666:        }
        !           667:        return memcmp(a, aes_key_wrap_iv, 8) != 0;
        !           668: }
        !           669:
        !           670: void
        !           671: ieee80211_hmac_md5_v(const struct vector *vec, int vcnt, const u_int8_t *key,
        !           672:     size_t key_len, u_int8_t digest[MD5_DIGEST_LENGTH])
        !           673: {
        !           674:        MD5_CTX ctx;
        !           675:        u_int8_t k_pad[MD5_BLOCK_LENGTH];
        !           676:        u_int8_t tk[MD5_DIGEST_LENGTH];
        !           677:        int i;
        !           678:
        !           679:        if (key_len > MD5_BLOCK_LENGTH) {
        !           680:                MD5Init(&ctx);
        !           681:                MD5Update(&ctx, (u_int8_t *)key, key_len);
        !           682:                MD5Final(tk, &ctx);
        !           683:
        !           684:                key = tk;
        !           685:                key_len = MD5_DIGEST_LENGTH;
        !           686:        }
        !           687:
        !           688:        bzero(k_pad, sizeof k_pad);
        !           689:        bcopy(key, k_pad, key_len);
        !           690:        for (i = 0; i < MD5_BLOCK_LENGTH; i++)
        !           691:                k_pad[i] ^= 0x36;
        !           692:
        !           693:        MD5Init(&ctx);
        !           694:        MD5Update(&ctx, k_pad, MD5_BLOCK_LENGTH);
        !           695:        for (i = 0; i < vcnt; i++)
        !           696:                MD5Update(&ctx, (u_int8_t *)vec[i].base, vec[i].len);
        !           697:        MD5Final(digest, &ctx);
        !           698:
        !           699:        bzero(k_pad, sizeof k_pad);
        !           700:        bcopy(key, k_pad, key_len);
        !           701:        for (i = 0; i < MD5_BLOCK_LENGTH; i++)
        !           702:                k_pad[i] ^= 0x5c;
        !           703:
        !           704:        MD5Init(&ctx);
        !           705:        MD5Update(&ctx, k_pad, MD5_BLOCK_LENGTH);
        !           706:        MD5Update(&ctx, digest, MD5_DIGEST_LENGTH);
        !           707:        MD5Final(digest, &ctx);
        !           708: }
        !           709:
        !           710: void
        !           711: ieee80211_hmac_md5(const u_int8_t *text, size_t text_len, const u_int8_t *key,
        !           712:     size_t key_len, u_int8_t digest[MD5_DIGEST_LENGTH])
        !           713: {
        !           714:        struct vector vec;
        !           715:        vec.base = text;
        !           716:        vec.len  = text_len;
        !           717:        ieee80211_hmac_md5_v(&vec, 1, key, key_len, digest);
        !           718: }
        !           719:
        !           720: void
        !           721: ieee80211_hmac_sha1_v(const struct vector *vec, int vcnt, const u_int8_t *key,
        !           722:     size_t key_len, u_int8_t digest[SHA1_DIGEST_LENGTH])
        !           723: {
        !           724:        SHA1_CTX ctx;
        !           725:        u_int8_t k_pad[SHA1_BLOCK_LENGTH];
        !           726:        u_int8_t tk[SHA1_DIGEST_LENGTH];
        !           727:        int i;
        !           728:
        !           729:        if (key_len > SHA1_BLOCK_LENGTH) {
        !           730:                SHA1Init(&ctx);
        !           731:                SHA1Update(&ctx, (u_int8_t *)key, key_len);
        !           732:                SHA1Final(tk, &ctx);
        !           733:
        !           734:                key = tk;
        !           735:                key_len = SHA1_DIGEST_LENGTH;
        !           736:        }
        !           737:
        !           738:        bzero(k_pad, sizeof k_pad);
        !           739:        bcopy(key, k_pad, key_len);
        !           740:        for (i = 0; i < SHA1_BLOCK_LENGTH; i++)
        !           741:                k_pad[i] ^= 0x36;
        !           742:
        !           743:        SHA1Init(&ctx);
        !           744:        SHA1Update(&ctx, k_pad, SHA1_BLOCK_LENGTH);
        !           745:        for (i = 0; i < vcnt; i++)
        !           746:                SHA1Update(&ctx, (u_int8_t *)vec[i].base, vec[i].len);
        !           747:        SHA1Final(digest, &ctx);
        !           748:
        !           749:        bzero(k_pad, sizeof k_pad);
        !           750:        bcopy(key, k_pad, key_len);
        !           751:        for (i = 0; i < SHA1_BLOCK_LENGTH; i++)
        !           752:                k_pad[i] ^= 0x5c;
        !           753:
        !           754:        SHA1Init(&ctx);
        !           755:        SHA1Update(&ctx, k_pad, SHA1_BLOCK_LENGTH);
        !           756:        SHA1Update(&ctx, digest, SHA1_DIGEST_LENGTH);
        !           757:        SHA1Final(digest, &ctx);
        !           758: }
        !           759:
        !           760: void
        !           761: ieee80211_hmac_sha1(const u_int8_t *text, size_t text_len, const u_int8_t *key,
        !           762:     size_t key_len, u_int8_t digest[SHA1_DIGEST_LENGTH])
        !           763: {
        !           764:        struct vector vec;
        !           765:        vec.base = text;
        !           766:        vec.len  = text_len;
        !           767:        ieee80211_hmac_sha1_v(&vec, 1, key, key_len, digest);
        !           768: }
        !           769:
        !           770: /*
        !           771:  * SHA1-based Pseudo-Random Function (see 8.5.1.1).
        !           772:  */
        !           773: void
        !           774: ieee80211_prf(const u_int8_t *key, size_t key_len, struct vector *vec,
        !           775:     int vcnt, u_int8_t *output, size_t len)
        !           776: {
        !           777:        u_int8_t hash[SHA1_DIGEST_LENGTH];
        !           778:        u_int8_t count = 0;
        !           779:
        !           780:        /* single octet count, starts at 0 */
        !           781:        vec[vcnt].base = &count;
        !           782:        vec[vcnt].len  = 1;
        !           783:        vcnt++;
        !           784:
        !           785:        while (len > SHA1_DIGEST_LENGTH) {
        !           786:                ieee80211_hmac_sha1_v(vec, vcnt, key, key_len, output);
        !           787:                count++;
        !           788:
        !           789:                output += SHA1_DIGEST_LENGTH;
        !           790:                len -= SHA1_DIGEST_LENGTH;
        !           791:        }
        !           792:        if (len > 0) {
        !           793:                ieee80211_hmac_sha1_v(vec, vcnt, key, key_len, hash);
        !           794:                /* truncate HMAC-SHA1 to len bytes */
        !           795:                memcpy(output, hash, len);
        !           796:        }
        !           797: }
        !           798:
        !           799: /*
        !           800:  * Derive Pairwise Transient Key (PTK) (see 8.5.1.2).
        !           801:  */
        !           802: void
        !           803: ieee80211_derive_ptk(const u_int8_t *pmk, size_t pmk_len, const u_int8_t *aa,
        !           804:     const u_int8_t *spa, const u_int8_t *anonce, const u_int8_t *snonce,
        !           805:     u_int8_t *ptk, size_t ptk_len)
        !           806: {
        !           807:        struct vector vec[6];   /* +1 for PRF */
        !           808:        int ret;
        !           809:
        !           810:        vec[0].base = "Pairwise key expansion";
        !           811:        vec[0].len  = 23;       /* include trailing '\0' */
        !           812:
        !           813:        ret = memcmp(aa, spa, IEEE80211_ADDR_LEN) < 0;
        !           814:        /* Min(AA,SPA) */
        !           815:        vec[1].base = ret ? aa : spa;
        !           816:        vec[1].len  = IEEE80211_ADDR_LEN;
        !           817:        /* Max(AA,SPA) */
        !           818:        vec[2].base = ret ? spa : aa;
        !           819:        vec[2].len  = IEEE80211_ADDR_LEN;
        !           820:
        !           821:        ret = memcmp(anonce, snonce, EAPOL_KEY_NONCE_LEN) < 0;
        !           822:        /* Min(ANonce,SNonce) */
        !           823:        vec[3].base = ret ? anonce : snonce;
        !           824:        vec[3].len  = EAPOL_KEY_NONCE_LEN;
        !           825:        /* Max(ANonce,SNonce) */
        !           826:        vec[4].base = ret ? snonce : anonce;
        !           827:        vec[4].len  = EAPOL_KEY_NONCE_LEN;
        !           828:
        !           829:        ieee80211_prf(pmk, pmk_len, vec, 5, ptk, ptk_len);
        !           830: }
        !           831:
        !           832: /*
        !           833:  * Derive Pairwise Master Key Identifier (PMKID) (see 8.5.1.2).
        !           834:  */
        !           835: void
        !           836: ieee80211_derive_pmkid(const u_int8_t *pmk, size_t pmk_len, const u_int8_t *aa,
        !           837:     const u_int8_t *spa, u_int8_t *pmkid)
        !           838: {
        !           839:        struct vector vec[3];
        !           840:        u_int8_t hash[SHA1_DIGEST_LENGTH];
        !           841:
        !           842:        vec[0].base = "PMK Name";
        !           843:        vec[0].len  = 8;        /* does *not* include trailing '\0' */
        !           844:        vec[1].base = aa;
        !           845:        vec[1].len  = IEEE80211_ADDR_LEN;
        !           846:        vec[2].base = spa;
        !           847:        vec[2].len  = IEEE80211_ADDR_LEN;
        !           848:
        !           849:        ieee80211_hmac_sha1_v(vec, 3, pmk, pmk_len, hash);
        !           850:        /* use the first 128 bits of the HMAC-SHA1 */
        !           851:        memcpy(pmkid, hash, IEEE80211_PMKID_LEN);
        !           852: }
        !           853:
        !           854: /*
        !           855:  * Derive Group Temporal Key (GTK) (see 8.5.1.3).
        !           856:  */
        !           857: void
        !           858: ieee80211_derive_gtk(const u_int8_t *gmk, size_t gmk_len, const u_int8_t *aa,
        !           859:     const u_int8_t *gnonce, u_int8_t *gtk, size_t gtk_len)
        !           860: {
        !           861:        struct vector vec[4];   /* +1 for PRF */
        !           862:
        !           863:        vec[0].base = "Group key expansion";
        !           864:        vec[0].len  = 20;       /* include trailing '\0' */
        !           865:        vec[1].base = aa;
        !           866:        vec[1].len  = IEEE80211_ADDR_LEN;
        !           867:        vec[2].base = gnonce;
        !           868:        vec[2].len  = EAPOL_KEY_NONCE_LEN;
        !           869:
        !           870:        ieee80211_prf(gmk, gmk_len, vec, 3, gtk, gtk_len);
        !           871: }
        !           872:
        !           873: /* unaligned big endian access */
        !           874: #define BE_READ_2(p)                           \
        !           875:        ((u_int16_t)                            \
        !           876:          ((((const u_int8_t *)(p))[0] << 8) |  \
        !           877:           (((const u_int8_t *)(p))[1])))
        !           878:
        !           879: #define BE_WRITE_2(p, v) do {                  \
        !           880:        ((u_int8_t *)(p))[0] = (v) >> 8;        \
        !           881:        ((u_int8_t *)(p))[1] = (v) & 0xff;      \
        !           882: } while (0)
        !           883:
        !           884: /*
        !           885:  * Compute the Key MIC field of an EAPOL-Key frame using the specified Key
        !           886:  * Confirmation Key (KCK).  The hash function can be either HMAC-MD5 or
        !           887:  * HMAC-SHA1 depending on the EAPOL-Key Key Descriptor Version.
        !           888:  */
        !           889: void
        !           890: ieee80211_eapol_key_mic(struct ieee80211_eapol_key *key, const u_int8_t *kck)
        !           891: {
        !           892:        u_int8_t hash[SHA1_DIGEST_LENGTH];
        !           893:        u_int16_t len, info;
        !           894:
        !           895:        len  = BE_READ_2(key->len) + 4;
        !           896:        info = BE_READ_2(key->info);
        !           897:
        !           898:        switch (info & EAPOL_KEY_VERSION_MASK) {
        !           899:        case EAPOL_KEY_DESC_V1:
        !           900:                ieee80211_hmac_md5((u_int8_t *)key, len, kck, 16, key->mic);
        !           901:                break;
        !           902:        case EAPOL_KEY_DESC_V2:
        !           903:                ieee80211_hmac_sha1((u_int8_t *)key, len, kck, 16, hash);
        !           904:                /* truncate HMAC-SHA1 to its 128 MSBs */
        !           905:                memcpy(key->mic, hash, EAPOL_KEY_MIC_LEN);
        !           906:                break;
        !           907:        }
        !           908: }
        !           909:
        !           910: /*
        !           911:  * Check the MIC of a received EAPOL-Key frame using the specified Key
        !           912:  * Confirmation Key (KCK).
        !           913:  */
        !           914: int
        !           915: ieee80211_eapol_key_check_mic(struct ieee80211_eapol_key *key,
        !           916:     const u_int8_t *kck)
        !           917: {
        !           918:        u_int8_t mic[EAPOL_KEY_MIC_LEN];
        !           919:
        !           920:        memcpy(mic, key->mic, EAPOL_KEY_MIC_LEN);
        !           921:        memset(key->mic, 0, EAPOL_KEY_MIC_LEN);
        !           922:        ieee80211_eapol_key_mic(key, kck);
        !           923:
        !           924:        return memcmp(key->mic, mic, EAPOL_KEY_MIC_LEN) != 0;
        !           925: }
        !           926:
        !           927: /*
        !           928:  * Encrypt the Key Data field of an EAPOL-Key frame using the specified Key
        !           929:  * Encryption Key (KEK).  The encryption algorithm can be either ARC4 or
        !           930:  * AES Key Wrap depending on the EAPOL-Key Key Descriptor Version.
        !           931:  */
        !           932: void
        !           933: ieee80211_eapol_key_encrypt(struct ieee80211com *ic,
        !           934:     struct ieee80211_eapol_key *key, const u_int8_t *kek)
        !           935: {
        !           936:        struct rc4_ctx ctx;
        !           937:        u_int8_t keybuf[EAPOL_KEY_IV_LEN + 16];
        !           938:        u_int16_t len, info;
        !           939:        u_int8_t *data;
        !           940:        int n;
        !           941:
        !           942:        len  = BE_READ_2(key->paylen);
        !           943:        info = BE_READ_2(key->info);
        !           944:        data = (u_int8_t *)(key + 1);
        !           945:
        !           946:        switch (info & EAPOL_KEY_VERSION_MASK) {
        !           947:        case EAPOL_KEY_DESC_V1:
        !           948:                /* set IV to the lower 16 octets of our global key counter */
        !           949:                memcpy(key->iv, ic->ic_globalcnt + 16, 16);
        !           950:                /* increment our global key counter (256-bit, big-endian) */
        !           951:                for (n = 31; n >= 0 && ++ic->ic_globalcnt[n] == 0; n--);
        !           952:
        !           953:                /* concatenate the EAPOL-Key IV field and the KEK */
        !           954:                memcpy(keybuf, key->iv, EAPOL_KEY_IV_LEN);
        !           955:                memcpy(keybuf + EAPOL_KEY_IV_LEN, kek, 16);
        !           956:
        !           957:                rc4_keysetup(&ctx, keybuf, sizeof keybuf);
        !           958:                /* discard the first 256 octets of the ARC4 key stream */
        !           959:                rc4_skip(&ctx, RC4STATE);
        !           960:                rc4_crypt(&ctx, data, data, len);
        !           961:                break;
        !           962:        case EAPOL_KEY_DESC_V2:
        !           963:                if (len < 16 || (len & 7) != 0) {
        !           964:                        /* insert padding */
        !           965:                        n = (len < 16) ? 16 - len : 8 - (len & 7);
        !           966:                        data[len++] = IEEE80211_ELEMID_VENDOR;
        !           967:                        memset(&data[len], 0, n - 1);
        !           968:                        len += n - 1;
        !           969:                }
        !           970:                ieee80211_aes_key_wrap(kek, 16, data, len / 8, data);
        !           971:                len += 8;       /* AES Key Wrap adds 8 bytes */
        !           972:                /* update key data length */
        !           973:                BE_WRITE_2(key->paylen, len);
        !           974:                /* update packet body length */
        !           975:                BE_WRITE_2(key->len, sizeof(*key) + len - 4);
        !           976:                break;
        !           977:        }
        !           978: }
        !           979:
        !           980: /*
        !           981:  * Decrypt the Key Data field of an EAPOL-Key frame using the specified Key
        !           982:  * Encryption Key (KEK).  The encryption algorithm can be either ARC4 or
        !           983:  * AES Key Wrap depending on the EAPOL-Key Key Descriptor Version.
        !           984:  */
        !           985: int
        !           986: ieee80211_eapol_key_decrypt(struct ieee80211_eapol_key *key,
        !           987:     const u_int8_t *kek)
        !           988: {
        !           989:        struct rc4_ctx ctx;
        !           990:        u_int8_t keybuf[EAPOL_KEY_IV_LEN + 16];
        !           991:        u_int16_t len, info;
        !           992:        u_int8_t *data;
        !           993:
        !           994:        len  = BE_READ_2(key->paylen);
        !           995:        info = BE_READ_2(key->info);
        !           996:        data = (u_int8_t *)(key + 1);
        !           997:
        !           998:        switch (info & EAPOL_KEY_VERSION_MASK) {
        !           999:        case EAPOL_KEY_DESC_V1:
        !          1000:                /* concatenate the EAPOL-Key IV field and the KEK */
        !          1001:                memcpy(keybuf, key->iv, EAPOL_KEY_IV_LEN);
        !          1002:                memcpy(keybuf + EAPOL_KEY_IV_LEN, kek, 16);
        !          1003:
        !          1004:                rc4_keysetup(&ctx, keybuf, sizeof keybuf);
        !          1005:                /* discard the first 256 octets of the ARC4 key stream */
        !          1006:                rc4_skip(&ctx, RC4STATE);
        !          1007:                rc4_crypt(&ctx, data, data, len);
        !          1008:                return 0;
        !          1009:        case EAPOL_KEY_DESC_V2:
        !          1010:                /* Key Data Length must be a multiple of 8 */
        !          1011:                if (len < 16 + 8 || (len & 7) != 0)
        !          1012:                        return 1;
        !          1013:                len -= 8;       /* AES Key Wrap adds 8 bytes */
        !          1014:                return ieee80211_aes_key_unwrap(kek, 16, data, data, len / 8);
        !          1015:        }
        !          1016:
        !          1017:        return 1;       /* unknown Key Descriptor Version */
        !          1018: }
        !          1019:
        !          1020: /*
        !          1021:  * Return the length in bytes of a cipher suite key (see Table 60).
        !          1022:  */
        !          1023: int
        !          1024: ieee80211_cipher_keylen(enum ieee80211_cipher cipher)
        !          1025: {
        !          1026:        switch (cipher) {
        !          1027:        case IEEE80211_CIPHER_WEP40:
        !          1028:                return 5;
        !          1029:        case IEEE80211_CIPHER_TKIP:
        !          1030:                return 32;
        !          1031:        case IEEE80211_CIPHER_CCMP:
        !          1032:                return 16;
        !          1033:        case IEEE80211_CIPHER_WEP104:
        !          1034:                return 13;
        !          1035:        default:        /* unknown cipher */
        !          1036:                return 0;
        !          1037:        }
        !          1038: }

CVSweb