[BACK]Return to awi_wep.c CVS log [TXT][DIR] Up to [local] / sys / dev / ic

Annotation of sys/dev/ic/awi_wep.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: awi_wep.c,v 1.13 2005/02/21 11:16:00 dlg Exp $        */
                      2: /*     $NetBSD: awi_wep.c,v 1.2 2000/07/04 14:47:58 onoe Exp $ */
                      3:
                      4: /*
                      5:  * Copyright (c) 2000 The NetBSD Foundation, Inc.
                      6:  * All rights reserved.
                      7:  *
                      8:  * This code is derived from software contributed to The NetBSD Foundation
                      9:  * by Atsushi Onoe.
                     10:  *
                     11:  * Redistribution and use in source and binary forms, with or without
                     12:  * modification, are permitted provided that the following conditions
                     13:  * are met:
                     14:  * 1. Redistributions of source code must retain the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer.
                     16:  * 2. Redistributions in binary form must reproduce the above copyright
                     17:  *    notice, this list of conditions and the following disclaimer in the
                     18:  *    documentation and/or other materials provided with the distribution.
                     19:  * 3. All advertising materials mentioning features or use of this software
                     20:  *    must display the following acknowledgement:
                     21:  *     This product includes software developed by the NetBSD
                     22:  *     Foundation, Inc. and its contributors.
                     23:  * 4. Neither the name of The NetBSD Foundation nor the names of its
                     24:  *    contributors may be used to endorse or promote products derived
                     25:  *    from this software without specific prior written permission.
                     26:  *
                     27:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     28:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     29:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     30:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     31:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     32:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     33:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     34:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     35:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     36:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     37:  * POSSIBILITY OF SUCH DAMAGE.
                     38:  */
                     39:
                     40: /*
                     41:  * WEP support framework for the awi driver.
                     42:  *
                     43:  * No actual encryption capability is provided here, but any can be added
                     44:  * to awi_wep_algo table below.
                     45:  *
                     46:  * Note that IEEE802.11 specification states WEP uses RC4 with 40bit key,
                     47:  * which is a proprietary encryption algorithm available under license
                     48:  * from RSA Data Security Inc.  Using another algorithm, includes null
                     49:  * encryption provided here, the awi driver cannot be able to communicate
                     50:  * with other stations.
                     51:  */
                     52:
                     53: #include <sys/param.h>
                     54: #include <sys/systm.h>
                     55: #include <sys/kernel.h>
                     56: #include <sys/mbuf.h>
                     57: #include <sys/malloc.h>
                     58: #include <sys/proc.h>
                     59: #include <sys/socket.h>
                     60: #include <sys/errno.h>
                     61: #include <sys/sockio.h>
                     62: #if defined(__FreeBSD__) && __FreeBSD__ >= 4
                     63: #include <sys/bus.h>
                     64: #else
                     65: #include <sys/device.h>
                     66: #endif
                     67:
                     68: #include <net/if.h>
                     69: #include <net/if_dl.h>
                     70: #ifdef __FreeBSD__
                     71: #include <net/ethernet.h>
                     72: #include <net/if_arp.h>
                     73: #elif defined(__OpenBSD__)
                     74: #include <netinet/in.h>
                     75: #include <netinet/if_ether.h>
                     76: #else
                     77: #include <net/if_ether.h>
                     78: #endif
                     79: #include <net/if_media.h>
                     80: #include <net80211/ieee80211.h>
                     81: #include <net80211/ieee80211_ioctl.h>
                     82:
                     83: #include <machine/cpu.h>
                     84: #include <machine/bus.h>
                     85: #ifdef __FreeBSD__
                     86: #include <machine/clock.h>
                     87: #endif
                     88:
                     89: #if defined(__NetBSD__) || defined(__OpenBSD__)
                     90: #include <dev/ic/am79c930reg.h>
                     91: #include <dev/ic/am79c930var.h>
                     92: #include <dev/ic/awireg.h>
                     93: #include <dev/ic/awivar.h>
                     94: #include <dev/rndvar.h>
                     95: #endif
                     96:
                     97: #ifdef __OpenBSD__
                     98: #include <dev/rndvar.h>
                     99: #endif
                    100:
                    101: #ifdef __OpenBSD__
                    102: #include <dev/rndvar.h>
                    103: #endif
                    104:
                    105: #ifdef __NetBSD__
                    106: #include <crypto/arc4/arc4.h>
                    107: #endif
                    108:
                    109: #ifdef __FreeBSD__
                    110: #include <dev/awi/am79c930reg.h>
                    111: #include <dev/awi/am79c930var.h>
                    112: #include <dev/awi/awireg.h>
                    113: #include <dev/awi/awivar.h>
                    114:
                    115: #include <crypto/rc4/rc4.h>
                    116: static __inline int
                    117: arc4_ctxlen(void)
                    118: {
                    119:         return sizeof(struct rc4_state);
                    120: }
                    121:
                    122: static __inline void
                    123: arc4_setkey(void *ctx, u_int8_t *key, int keylen)
                    124: {
                    125:        rc4_init(ctx, key, keylen);
                    126: }
                    127:
                    128: static __inline void
                    129: arc4_encrypt(void *ctx, u_int8_t *dst, u_int8_t *src, int len)
                    130: {
                    131:        rc4_crypt(ctx, dst, src, len);
                    132: }
                    133: #endif
                    134:
                    135: static void awi_crc_init(void);
                    136: static u_int32_t awi_crc_update(u_int32_t crc, u_int8_t *buf, int len);
                    137:
                    138: static int awi_null_ctxlen(void);
                    139: static void awi_null_setkey(void *ctx, u_int8_t *key, int keylen);
                    140: static void awi_null_copy(void *ctx, u_int8_t *dst, u_int8_t *src, int len);
                    141:
                    142: /* XXX: the order should be known to wiconfig/user */
                    143:
                    144: static struct awi_wep_algo awi_wep_algo[] = {
                    145: /* 0: no wep */
                    146:        { "no" },       /* dummy for no wep */
                    147:
                    148: #if 0
                    149: /* 1: normal wep (arc4) */
                    150:        { "arc4", arc4_ctxlen, arc4_setkey,
                    151:            arc4_encrypt, arc4_encrypt },
                    152: #endif
                    153: /* 2: debug wep (null) */
                    154:        { "null", awi_null_ctxlen, awi_null_setkey,
                    155:            awi_null_copy, awi_null_copy },
                    156:                        /* dummy for wep without encryption */
                    157: };
                    158:
                    159: int
                    160: awi_wep_setnwkey(sc, nwkey)
                    161:        struct awi_softc *sc;
                    162:        struct ieee80211_nwkey *nwkey;
                    163: {
                    164:        int i, len, error;
                    165:        u_int8_t keybuf[AWI_MAX_KEYLEN];
                    166:
                    167:        if (nwkey->i_defkid <= 0 ||
                    168:            nwkey->i_defkid > IEEE80211_WEP_NKID)
                    169:                return EINVAL;
                    170:        error = 0;
                    171:        for (i = 0; i < IEEE80211_WEP_NKID; i++) {
                    172:                if (nwkey->i_key[i].i_keydat == NULL)
                    173:                        continue;
                    174:                len = nwkey->i_key[i].i_keylen;
                    175:                if (len > sizeof(keybuf)) {
                    176:                        error = EINVAL;
                    177:                        break;
                    178:                }
                    179:                error = copyin(nwkey->i_key[i].i_keydat, keybuf, len);
                    180:                if (error)
                    181:                        break;
                    182:                error = awi_wep_setkey(sc, i, keybuf, len);
                    183:                if (error)
                    184:                        break;
                    185:        }
                    186:        if (error == 0) {
                    187:                sc->sc_wep_defkid = nwkey->i_defkid - 1;
                    188:                error = awi_wep_setalgo(sc, nwkey->i_wepon);
                    189:                if (error == 0 && sc->sc_enabled) {
                    190:                        awi_stop(sc);
                    191:                        error = awi_init(sc);
                    192:                }
                    193:        }
                    194:        return error;
                    195: }
                    196:
                    197: int
                    198: awi_wep_getnwkey(sc, nwkey)
                    199:        struct awi_softc *sc;
                    200:        struct ieee80211_nwkey *nwkey;
                    201: {
                    202:        int i, len, error, suerr;
                    203:        u_int8_t keybuf[AWI_MAX_KEYLEN];
                    204:
                    205:        nwkey->i_wepon = awi_wep_getalgo(sc);
                    206:        nwkey->i_defkid = sc->sc_wep_defkid + 1;
                    207:        /* do not show any keys to non-root user */
                    208: #ifdef __FreeBSD__
                    209:        suerr = suser(curproc);
                    210: #else
                    211: #ifdef __OpenBSD__
                    212:        suerr = suser(curproc, 0);
                    213: #else
                    214:        suerr = suser(curproc->p_ucred, &curproc->p_acflag);
                    215: #endif
                    216: #endif
                    217:        error = 0;
                    218:        for (i = 0; i < IEEE80211_WEP_NKID; i++) {
                    219:                if (nwkey->i_key[i].i_keydat == NULL)
                    220:                        continue;
                    221:                if (suerr) {
                    222:                        error = suerr;
                    223:                        break;
                    224:                }
                    225:                len = sizeof(keybuf);
                    226:                error = awi_wep_getkey(sc, i, keybuf, &len);
                    227:                if (error)
                    228:                        break;
                    229:                if (nwkey->i_key[i].i_keylen < len) {
                    230:                        error = ENOSPC;
                    231:                        break;
                    232:                }
                    233:                nwkey->i_key[i].i_keylen = len;
                    234:                error = copyout(keybuf, nwkey->i_key[i].i_keydat, len);
                    235:                if (error)
                    236:                        break;
                    237:        }
                    238:        return error;
                    239: }
                    240:
                    241: int
                    242: awi_wep_getalgo(sc)
                    243:        struct awi_softc *sc;
                    244: {
                    245:
                    246:        if (sc->sc_wep_algo == NULL)
                    247:                return 0;
                    248:        return sc->sc_wep_algo - awi_wep_algo;
                    249: }
                    250:
                    251: int
                    252: awi_wep_setalgo(sc, algo)
                    253:        struct awi_softc *sc;
                    254:        int algo;
                    255: {
                    256:        struct awi_wep_algo *awa;
                    257:        int ctxlen;
                    258:
                    259:        awi_crc_init(); /* XXX: not belongs here */
                    260:        if (algo < 0 || algo >= sizeof(awi_wep_algo)/sizeof(awi_wep_algo[0]))
                    261:                return EINVAL;
                    262:        awa = &awi_wep_algo[algo];
                    263:        if (awa->awa_name == NULL)
                    264:                return EINVAL;
                    265:        if (awa->awa_ctxlen == NULL) {
                    266:                awa = NULL;
                    267:                ctxlen = 0;
                    268:        } else
                    269:                ctxlen = awa->awa_ctxlen();
                    270:        if (sc->sc_wep_ctx != NULL) {
                    271:                free(sc->sc_wep_ctx, M_DEVBUF);
                    272:                sc->sc_wep_ctx = NULL;
                    273:        }
                    274:        if (ctxlen) {
                    275:                sc->sc_wep_ctx = malloc(ctxlen, M_DEVBUF, M_NOWAIT);
                    276:                if (sc->sc_wep_ctx == NULL)
                    277:                        return ENOMEM;
                    278:        }
                    279:        sc->sc_wep_algo = awa;
                    280:        return 0;
                    281: }
                    282:
                    283: int
                    284: awi_wep_setkey(sc, kid, key, keylen)
                    285:        struct awi_softc *sc;
                    286:        int kid;
                    287:        unsigned char *key;
                    288:        int keylen;
                    289: {
                    290:
                    291:        if (kid < 0 || kid >= IEEE80211_WEP_NKID)
                    292:                return EINVAL;
                    293:        if (keylen < 0 || keylen + IEEE80211_WEP_IVLEN > AWI_MAX_KEYLEN)
                    294:                return EINVAL;
                    295:        sc->sc_wep_keylen[kid] = keylen;
                    296:        if (keylen > 0)
                    297:                memcpy(sc->sc_wep_key[kid] + IEEE80211_WEP_IVLEN, key, keylen);
                    298:        return 0;
                    299: }
                    300:
                    301: int
                    302: awi_wep_getkey(sc, kid, key, keylen)
                    303:        struct awi_softc *sc;
                    304:        int kid;
                    305:        unsigned char *key;
                    306:        int *keylen;
                    307: {
                    308:
                    309:        if (kid < 0 || kid >= IEEE80211_WEP_NKID)
                    310:                return EINVAL;
                    311:        if (*keylen < sc->sc_wep_keylen[kid])
                    312:                return ENOSPC;
                    313:        *keylen = sc->sc_wep_keylen[kid];
                    314:        if (*keylen > 0)
                    315:                memcpy(key, sc->sc_wep_key[kid] + IEEE80211_WEP_IVLEN, *keylen);
                    316:        return 0;
                    317: }
                    318:
                    319: struct mbuf *
                    320: awi_wep_encrypt(sc, m0, txflag)
                    321:        struct awi_softc *sc;
                    322:        struct mbuf *m0;
                    323:        int txflag;
                    324: {
                    325:        struct mbuf *m, *n, *n0;
                    326:        struct ieee80211_frame *wh;
                    327:        struct awi_wep_algo *awa;
                    328:        int left, len, moff, noff, keylen, kid;
                    329:        u_int32_t iv, crc;
                    330:        u_int8_t *key, *ivp;
                    331:        void *ctx;
                    332:        u_int8_t crcbuf[IEEE80211_WEP_CRCLEN];
                    333:
                    334:        n0 = NULL;
                    335:        awa = sc->sc_wep_algo;
                    336:        if (awa == NULL)
                    337:                goto fail;
                    338:        ctx = sc->sc_wep_ctx;
                    339:        m = m0;
                    340:        left = m->m_pkthdr.len;
                    341:        MGET(n, M_DONTWAIT, m->m_type);
                    342:        n0 = n;
                    343:        if (n == NULL)
                    344:                goto fail;
                    345:        M_DUP_PKTHDR(n, m);
                    346:        len = IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN +
                    347:              IEEE80211_WEP_CRCLEN;
                    348:        if (txflag) {
                    349:                n->m_pkthdr.len += len;
                    350:        } else {
                    351:                wh = mtod(n, struct ieee80211_frame *);
                    352:                n->m_pkthdr.len -= len;
                    353:                left -= len;
                    354:        }
                    355:        n->m_len = MHLEN;
                    356:        if (n->m_pkthdr.len >= MINCLSIZE) {
                    357:                MCLGET(n, M_DONTWAIT);
                    358:                if (n->m_flags & M_EXT)
                    359:                        n->m_len = n->m_ext.ext_size;
                    360:        }
                    361:        len = sizeof(struct ieee80211_frame);
                    362:        memcpy(mtod(n, caddr_t), mtod(m, caddr_t), len);
                    363:        left -= len;
                    364:        moff = len;
                    365:        noff = len;
                    366:        if (txflag) {
                    367:                kid = sc->sc_wep_defkid;
                    368:                wh = mtod(n, struct ieee80211_frame *);
                    369:                wh->i_fc[1] |= IEEE80211_FC1_WEP;
                    370:                iv = arc4random();
                    371:                /*
                    372:                 * store IV, byte order is not the matter since it's random.
                    373:                 * assuming IEEE80211_WEP_IVLEN is 3
                    374:                 */
                    375:                ivp = mtod(n, u_int8_t *) + noff;
                    376:                ivp[0] = (iv >> 16) & 0xff;
                    377:                ivp[1] = (iv >> 8) & 0xff;
                    378:                ivp[2] = iv & 0xff;
                    379:                ivp[3] = kid & 0x03;    /* clear pad and keyid */
                    380:                noff += IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN;
                    381:        } else {
                    382:                ivp = mtod(m, u_int8_t *) + moff;
                    383:                moff += IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN;
                    384:                kid = ivp[IEEE80211_WEP_IVLEN] & 0x03;
                    385:        }
                    386:        key = sc->sc_wep_key[kid];
                    387:        keylen = sc->sc_wep_keylen[kid];
                    388:        /* assuming IEEE80211_WEP_IVLEN is 3 */
                    389:        key[0] = ivp[0];
                    390:        key[1] = ivp[1];
                    391:        key[2] = ivp[2];
                    392:        awa->awa_setkey(ctx, key, IEEE80211_WEP_IVLEN + keylen);
                    393:
                    394:        /* encrypt with calculating CRC */
                    395:        crc = ~0;
                    396:        while (left > 0) {
                    397:                len = m->m_len - moff;
                    398:                if (len == 0) {
                    399:                        m = m->m_next;
                    400:                        moff = 0;
                    401:                        continue;
                    402:                }
                    403:                if (len > n->m_len - noff) {
                    404:                        len = n->m_len - noff;
                    405:                        if (len == 0) {
                    406:                                MGET(n->m_next, M_DONTWAIT, n->m_type);
                    407:                                if (n->m_next == NULL)
                    408:                                        goto fail;
                    409:                                n = n->m_next;
                    410:                                n->m_len = MLEN;
                    411:                                if (left >= MINCLSIZE) {
                    412:                                        MCLGET(n, M_DONTWAIT);
                    413:                                        if (n->m_flags & M_EXT)
                    414:                                                n->m_len = n->m_ext.ext_size;
                    415:                                }
                    416:                                noff = 0;
                    417:                                continue;
                    418:                        }
                    419:                }
                    420:                if (len > left)
                    421:                        len = left;
                    422:                if (txflag) {
                    423:                        awa->awa_encrypt(ctx, mtod(n, caddr_t) + noff,
                    424:                            mtod(m, caddr_t) + moff, len);
                    425:                        crc = awi_crc_update(crc, mtod(m, caddr_t) + moff, len);
                    426:                } else {
                    427:                        awa->awa_decrypt(ctx, mtod(n, caddr_t) + noff,
                    428:                            mtod(m, caddr_t) + moff, len);
                    429:                        crc = awi_crc_update(crc, mtod(n, caddr_t) + noff, len);
                    430:                }
                    431:                left -= len;
                    432:                moff += len;
                    433:                noff += len;
                    434:        }
                    435:        crc = ~crc;
                    436:        if (txflag) {
                    437:                LE_WRITE_4(crcbuf, crc);
                    438:                if (n->m_len >= noff + sizeof(crcbuf))
                    439:                        n->m_len = noff + sizeof(crcbuf);
                    440:                else {
                    441:                        n->m_len = noff;
                    442:                        MGET(n->m_next, M_DONTWAIT, n->m_type);
                    443:                        if (n->m_next == NULL)
                    444:                                goto fail;
                    445:                        n = n->m_next;
                    446:                        n->m_len = sizeof(crcbuf);
                    447:                        noff = 0;
                    448:                }
                    449:                awa->awa_encrypt(ctx, mtod(n, caddr_t) + noff, crcbuf,
                    450:                    sizeof(crcbuf));
                    451:        } else {
                    452:                n->m_len = noff;
                    453:                noff = 0;
                    454:                for (; noff < sizeof(crcbuf); noff += len, m = m->m_next) {
                    455:                        if (m->m_len < moff + len)
                    456:                                len = m->m_len - moff;
                    457:                        if (len == 0)
                    458:                                continue;
                    459:                        awa->awa_decrypt(ctx, crcbuf + noff,
                    460:                            mtod(m, caddr_t) + moff, len);
                    461:                }
                    462:                if (crc != LE_READ_4(crcbuf))
                    463:                        goto fail;
                    464:        }
                    465:        m_freem(m0);
                    466:        return n0;
                    467:
                    468:   fail:
                    469:        m_freem(m0);
                    470:        m_freem(n0);
                    471:        return NULL;
                    472: }
                    473:
                    474: /*
                    475:  * CRC 32 -- routine from RFC 2083
                    476:  */
                    477:
                    478: /* Table of CRCs of all 8-bit messages */
                    479: static u_int32_t awi_crc_table[256];
                    480: static int awi_crc_table_computed = 0;
                    481:
                    482: /* Make the table for a fast CRC. */
                    483: static void
                    484: awi_crc_init()
                    485: {
                    486:        u_int32_t c;
                    487:        int n, k;
                    488:
                    489:        if (awi_crc_table_computed)
                    490:                return;
                    491:        for (n = 0; n < 256; n++) {
                    492:                c = (u_int32_t)n;
                    493:                for (k = 0; k < 8; k++) {
                    494:                        if (c & 1)
                    495:                                c = 0xedb88320UL ^ (c >> 1);
                    496:                        else
                    497:                                c = c >> 1;
                    498:                }
                    499:                awi_crc_table[n] = c;
                    500:        }
                    501:        awi_crc_table_computed = 1;
                    502: }
                    503:
                    504: /*
                    505:  * Update a running CRC with the bytes buf[0..len-1]--the CRC
                    506:  * should be initialized to all 1's, and the transmitted value
                    507:  * is the 1's complement of the final running CRC
                    508:  */
                    509:
                    510: static u_int32_t
                    511: awi_crc_update(crc, buf, len)
                    512:        u_int32_t crc;
                    513:        u_int8_t *buf;
                    514:        int len;
                    515: {
                    516:        u_int8_t *endbuf;
                    517:
                    518:        for (endbuf = buf + len; buf < endbuf; buf++)
                    519:                crc = awi_crc_table[(crc ^ *buf) & 0xff] ^ (crc >> 8);
                    520:        return crc;
                    521: }
                    522:
                    523: /*
                    524:  * Null -- do nothing but copy.
                    525:  */
                    526:
                    527: static int
                    528: awi_null_ctxlen()
                    529: {
                    530:
                    531:        return 0;
                    532: }
                    533:
                    534: static void
                    535: awi_null_setkey(ctx, key, keylen)
                    536:        void *ctx;
                    537:        u_char *key;
                    538:        int keylen;
                    539: {
                    540: }
                    541:
                    542: static void
                    543: awi_null_copy(ctx, dst, src, len)
                    544:        void *ctx;
                    545:        u_char *dst;
                    546:        u_char *src;
                    547:        int len;
                    548: {
                    549:
                    550:        memcpy(dst, src, len);
                    551: }

CVSweb