Annotation of qemu/roms/ipxe/src/net/80211/wep.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 2009 Joshua Oreman <[email protected]>.
        !             3:  *
        !             4:  * This program is free software; you can redistribute it and/or
        !             5:  * modify it under the terms of the GNU General Public License as
        !             6:  * published by the Free Software Foundation; either version 2 of the
        !             7:  * License, or any later version.
        !             8:  *
        !             9:  * This program is distributed in the hope that it will be useful, but
        !            10:  * WITHOUT ANY WARRANTY; without even the implied warranty of
        !            11:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
        !            12:  * General Public License for more details.
        !            13:  *
        !            14:  * You should have received a copy of the GNU General Public License
        !            15:  * along with this program; if not, write to the Free Software
        !            16:  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
        !            17:  */
        !            18: 
        !            19: FILE_LICENCE ( GPL2_OR_LATER );
        !            20: 
        !            21: #include <ipxe/net80211.h>
        !            22: #include <ipxe/sec80211.h>
        !            23: #include <ipxe/crypto.h>
        !            24: #include <ipxe/arc4.h>
        !            25: #include <ipxe/crc32.h>
        !            26: #include <stdlib.h>
        !            27: #include <string.h>
        !            28: #include <errno.h>
        !            29: 
        !            30: /** @file
        !            31:  *
        !            32:  * The WEP wireless encryption method (insecure!)
        !            33:  *
        !            34:  * The data field in a WEP-encrypted packet contains a 3-byte
        !            35:  * initialisation vector, one-byte Key ID field (only the bottom two
        !            36:  * bits are ever used), encrypted data, and a 4-byte encrypted CRC of
        !            37:  * the plaintext data, called the ICV. To decrypt it, the IV is
        !            38:  * prepended to the shared key and the data stream (including ICV) is
        !            39:  * run through the ARC4 stream cipher; if the ICV matches a CRC32
        !            40:  * calculated on the plaintext, the packet is valid.
        !            41:  *
        !            42:  * For efficiency and code-size reasons, this file assumes it is
        !            43:  * running on a little-endian machine.
        !            44:  */
        !            45: 
        !            46: /** Length of WEP initialisation vector */
        !            47: #define WEP_IV_LEN     3
        !            48: 
        !            49: /** Length of WEP key ID byte */
        !            50: #define WEP_KID_LEN    1
        !            51: 
        !            52: /** Length of WEP ICV checksum */
        !            53: #define WEP_ICV_LEN    4
        !            54: 
        !            55: /** Maximum length of WEP key */
        !            56: #define WEP_MAX_KEY    16
        !            57: 
        !            58: /** Amount of data placed before the encrypted bytes */
        !            59: #define WEP_HEADER_LEN 4
        !            60: 
        !            61: /** Amount of data placed after the encrypted bytes */
        !            62: #define WEP_TRAILER_LEN        4
        !            63: 
        !            64: /** Total WEP overhead bytes */
        !            65: #define WEP_OVERHEAD   8
        !            66: 
        !            67: /** Context for WEP encryption and decryption */
        !            68: struct wep_ctx
        !            69: {
        !            70:        /** Encoded WEP key
        !            71:         *
        !            72:         * The actual key bytes are stored beginning at offset 3, to
        !            73:         * leave room for easily inserting the IV before a particular
        !            74:         * operation.
        !            75:         */
        !            76:        u8 key[WEP_IV_LEN + WEP_MAX_KEY];
        !            77: 
        !            78:        /** Length of WEP key (not including IV bytes) */
        !            79:        int keylen;
        !            80: 
        !            81:        /** ARC4 context */
        !            82:        struct arc4_ctx arc4;
        !            83: };
        !            84: 
        !            85: /**
        !            86:  * Initialize WEP algorithm
        !            87:  *
        !            88:  * @v crypto   802.11 cryptographic algorithm
        !            89:  * @v key      WEP key to use
        !            90:  * @v keylen   Length of WEP key
        !            91:  * @v rsc      Initial receive sequence counter (unused)
        !            92:  * @ret rc     Return status code
        !            93:  *
        !            94:  * Standard key lengths are 5 and 13 bytes; 16-byte keys are
        !            95:  * occasionally supported as an extension to the standard.
        !            96:  */
        !            97: static int wep_init ( struct net80211_crypto *crypto, const void *key,
        !            98:                      int keylen, const void *rsc __unused )
        !            99: {
        !           100:        struct wep_ctx *ctx = crypto->priv;
        !           101: 
        !           102:        ctx->keylen = ( keylen > WEP_MAX_KEY ? WEP_MAX_KEY : keylen );
        !           103:        memcpy ( ctx->key + WEP_IV_LEN, key, ctx->keylen );
        !           104: 
        !           105:        return 0;
        !           106: }
        !           107: 
        !           108: /**
        !           109:  * Encrypt packet using WEP
        !           110:  *
        !           111:  * @v crypto   802.11 cryptographic algorithm
        !           112:  * @v iob      I/O buffer of plaintext packet
        !           113:  * @ret eiob   Newly allocated I/O buffer for encrypted packet, or NULL
        !           114:  *
        !           115:  * If memory allocation fails, @c NULL is returned.
        !           116:  */
        !           117: static struct io_buffer * wep_encrypt ( struct net80211_crypto *crypto,
        !           118:                                        struct io_buffer *iob )
        !           119: {
        !           120:        struct wep_ctx *ctx = crypto->priv;
        !           121:        struct io_buffer *eiob;
        !           122:        struct ieee80211_frame *hdr;
        !           123:        const int hdrlen = IEEE80211_TYP_FRAME_HEADER_LEN;
        !           124:        int datalen = iob_len ( iob ) - hdrlen;
        !           125:        int newlen = hdrlen + datalen + WEP_OVERHEAD;
        !           126:        u32 iv, icv;
        !           127: 
        !           128:        eiob = alloc_iob ( newlen );
        !           129:        if ( ! eiob )
        !           130:                return NULL;
        !           131: 
        !           132:        memcpy ( iob_put ( eiob, hdrlen ), iob->data, hdrlen );
        !           133:        hdr = eiob->data;
        !           134:        hdr->fc |= IEEE80211_FC_PROTECTED;
        !           135: 
        !           136:        /* Calculate IV, put it in the header (with key ID byte = 0), and
        !           137:           set it up at the start of the encryption key. */
        !           138:        iv = random() & 0xffffff; /* IV in bottom 3 bytes, top byte = KID = 0 */
        !           139:        memcpy ( iob_put ( eiob, WEP_HEADER_LEN ), &iv, WEP_HEADER_LEN );
        !           140:        memcpy ( ctx->key, &iv, WEP_IV_LEN );
        !           141: 
        !           142:        /* Encrypt the data using RC4 */
        !           143:        cipher_setkey ( &arc4_algorithm, &ctx->arc4, ctx->key,
        !           144:                        ctx->keylen + WEP_IV_LEN );
        !           145:        cipher_encrypt ( &arc4_algorithm, &ctx->arc4, iob->data + hdrlen,
        !           146:                         iob_put ( eiob, datalen ), datalen );
        !           147: 
        !           148:        /* Add ICV */
        !           149:        icv = ~crc32_le ( ~0, iob->data + hdrlen, datalen );
        !           150:        cipher_encrypt ( &arc4_algorithm, &ctx->arc4, &icv,
        !           151:                         iob_put ( eiob, WEP_ICV_LEN ), WEP_ICV_LEN );
        !           152: 
        !           153:        return eiob;
        !           154: }
        !           155: 
        !           156: /**
        !           157:  * Decrypt packet using WEP
        !           158:  *
        !           159:  * @v crypto   802.11 cryptographic algorithm
        !           160:  * @v eiob     I/O buffer of encrypted packet
        !           161:  * @ret iob    Newly allocated I/O buffer for plaintext packet, or NULL
        !           162:  *
        !           163:  * If a consistency check for the decryption fails (usually indicating
        !           164:  * an invalid key), @c NULL is returned.
        !           165:  */
        !           166: static struct io_buffer * wep_decrypt ( struct net80211_crypto *crypto,
        !           167:                                        struct io_buffer *eiob )
        !           168: {
        !           169:        struct wep_ctx *ctx = crypto->priv;
        !           170:        struct io_buffer *iob;
        !           171:        struct ieee80211_frame *hdr;
        !           172:        const int hdrlen = IEEE80211_TYP_FRAME_HEADER_LEN;
        !           173:        int datalen = iob_len ( eiob ) - hdrlen - WEP_OVERHEAD;
        !           174:        int newlen = hdrlen + datalen;
        !           175:        u32 iv, icv, crc;
        !           176: 
        !           177:        iob = alloc_iob ( newlen );
        !           178:        if ( ! iob )
        !           179:                return NULL;
        !           180: 
        !           181:        memcpy ( iob_put ( iob, hdrlen ), eiob->data, hdrlen );
        !           182:        hdr = iob->data;
        !           183:        hdr->fc &= ~IEEE80211_FC_PROTECTED;
        !           184: 
        !           185:        /* Strip off IV and use it to initialize cryptosystem */
        !           186:        memcpy ( &iv, eiob->data + hdrlen, 4 );
        !           187:        iv &= 0xffffff;         /* ignore key ID byte */
        !           188:        memcpy ( ctx->key, &iv, WEP_IV_LEN );
        !           189: 
        !           190:        /* Decrypt the data using RC4 */
        !           191:        cipher_setkey ( &arc4_algorithm, &ctx->arc4, ctx->key,
        !           192:                        ctx->keylen + WEP_IV_LEN );
        !           193:        cipher_decrypt ( &arc4_algorithm, &ctx->arc4, eiob->data + hdrlen +
        !           194:                         WEP_HEADER_LEN, iob_put ( iob, datalen ), datalen );
        !           195: 
        !           196:        /* Strip off ICV and verify it */
        !           197:        cipher_decrypt ( &arc4_algorithm, &ctx->arc4, eiob->data + hdrlen +
        !           198:                         WEP_HEADER_LEN + datalen, &icv, WEP_ICV_LEN );
        !           199:        crc = ~crc32_le ( ~0, iob->data + hdrlen, datalen );
        !           200:        if ( crc != icv ) {
        !           201:                DBGC ( crypto, "WEP %p CRC mismatch: expect %08x, get %08x\n",
        !           202:                       crypto, icv, crc );
        !           203:                free_iob ( iob );
        !           204:                return NULL;
        !           205:        }
        !           206:        return iob;
        !           207: }
        !           208: 
        !           209: /** WEP cryptosystem for 802.11 */
        !           210: struct net80211_crypto wep_crypto __net80211_crypto = {
        !           211:        .algorithm = NET80211_CRYPT_WEP,
        !           212:        .init = wep_init,
        !           213:        .encrypt = wep_encrypt,
        !           214:        .decrypt = wep_decrypt,
        !           215:        .priv_len = sizeof ( struct wep_ctx ),
        !           216: };
        !           217: 
        !           218: /**
        !           219:  * Initialize trivial 802.11 security handshaker
        !           220:  *
        !           221:  * @v dev      802.11 device
        !           222:  * @v ctx      Security handshaker
        !           223:  *
        !           224:  * This simply fetches a WEP key from netX/key, and if it exists,
        !           225:  * installs WEP cryptography on the 802.11 device. No real handshaking
        !           226:  * is performed.
        !           227:  */
        !           228: static int trivial_init ( struct net80211_device *dev )
        !           229: {
        !           230:        u8 key[WEP_MAX_KEY];    /* support up to 128-bit keys */
        !           231:        int len;
        !           232:        int rc;
        !           233: 
        !           234:        if ( dev->associating &&
        !           235:             dev->associating->crypto == NET80211_CRYPT_NONE )
        !           236:                return 0;       /* no crypto? OK. */
        !           237: 
        !           238:        len = fetch_setting ( netdev_settings ( dev->netdev ),
        !           239:                              &net80211_key_setting, key, WEP_MAX_KEY );
        !           240: 
        !           241:        if ( len <= 0 ) {
        !           242:                DBGC ( dev, "802.11 %p cannot do WEP without a key\n", dev );
        !           243:                return -EACCES;
        !           244:        }
        !           245: 
        !           246:        /* Full 128-bit keys are a nonstandard extension, but they're
        !           247:           utterly trivial to support, so we do. */
        !           248:        if ( len != 5 && len != 13 && len != 16 ) {
        !           249:                DBGC ( dev, "802.11 %p invalid WEP key length %d\n",
        !           250:                       dev, len );
        !           251:                return -EINVAL;
        !           252:        }
        !           253: 
        !           254:        DBGC ( dev, "802.11 %p installing %d-bit WEP\n", dev, len * 8 );
        !           255: 
        !           256:        rc = sec80211_install ( &dev->crypto, NET80211_CRYPT_WEP, key, len,
        !           257:                                NULL );
        !           258:        if ( rc < 0 )
        !           259:                return rc;
        !           260: 
        !           261:        return 0;
        !           262: }
        !           263: 
        !           264: /**
        !           265:  * Check for key change on trivial 802.11 security handshaker
        !           266:  *
        !           267:  * @v dev      802.11 device
        !           268:  * @v ctx      Security handshaker
        !           269:  */
        !           270: static int trivial_change_key ( struct net80211_device *dev )
        !           271: {
        !           272:        u8 key[WEP_MAX_KEY];
        !           273:        int len;
        !           274:        int change = 0;
        !           275: 
        !           276:        /* If going from WEP to clear, or something else to WEP, reassociate. */
        !           277:        if ( ! dev->crypto || ( dev->crypto->init != wep_init ) )
        !           278:                change ^= 1;
        !           279: 
        !           280:        len = fetch_setting ( netdev_settings ( dev->netdev ),
        !           281:                              &net80211_key_setting, key, WEP_MAX_KEY );
        !           282:        if ( len <= 0 )
        !           283:                change ^= 1;
        !           284: 
        !           285:        /* Changing crypto type => return nonzero to reassociate. */
        !           286:        if ( change )
        !           287:                return -EINVAL;
        !           288: 
        !           289:        /* Going from no crypto to still no crypto => nothing to do. */
        !           290:        if ( len <= 0 )
        !           291:                return 0;
        !           292: 
        !           293:        /* Otherwise, reinitialise WEP with new key. */
        !           294:        return wep_init ( dev->crypto, key, len, NULL );
        !           295: }
        !           296: 
        !           297: /** Trivial 802.11 security handshaker */
        !           298: struct net80211_handshaker trivial_handshaker __net80211_handshaker = {
        !           299:        .protocol = NET80211_SECPROT_NONE,
        !           300:        .init = trivial_init,
        !           301:        .change_key = trivial_change_key,
        !           302:        .priv_len = 0,
        !           303: };

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.