Annotation of qemu/roms/ipxe/src/net/80211/wep.c, revision 1.1.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.