Home | History | Annotate | Line # | Download | only in net80211
ieee80211_crypto_wep.c revision 1.3.6.3
      1  1.3.6.2     skrll /*-
      2  1.3.6.2     skrll  * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
      3  1.3.6.2     skrll  * All rights reserved.
      4  1.3.6.2     skrll  *
      5  1.3.6.2     skrll  * Redistribution and use in source and binary forms, with or without
      6  1.3.6.2     skrll  * modification, are permitted provided that the following conditions
      7  1.3.6.2     skrll  * are met:
      8  1.3.6.2     skrll  * 1. Redistributions of source code must retain the above copyright
      9  1.3.6.2     skrll  *    notice, this list of conditions and the following disclaimer.
     10  1.3.6.2     skrll  * 2. Redistributions in binary form must reproduce the above copyright
     11  1.3.6.2     skrll  *    notice, this list of conditions and the following disclaimer in the
     12  1.3.6.2     skrll  *    documentation and/or other materials provided with the distribution.
     13  1.3.6.2     skrll  * 3. The name of the author may not be used to endorse or promote products
     14  1.3.6.2     skrll  *    derived from this software without specific prior written permission.
     15  1.3.6.2     skrll  *
     16  1.3.6.2     skrll  * Alternatively, this software may be distributed under the terms of the
     17  1.3.6.2     skrll  * GNU General Public License ("GPL") version 2 as published by the Free
     18  1.3.6.2     skrll  * Software Foundation.
     19  1.3.6.2     skrll  *
     20  1.3.6.2     skrll  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     21  1.3.6.2     skrll  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     22  1.3.6.2     skrll  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     23  1.3.6.2     skrll  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     24  1.3.6.2     skrll  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     25  1.3.6.2     skrll  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     26  1.3.6.2     skrll  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     27  1.3.6.2     skrll  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     28  1.3.6.2     skrll  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     29  1.3.6.2     skrll  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     30  1.3.6.2     skrll  */
     31  1.3.6.2     skrll 
     32  1.3.6.2     skrll #include <sys/cdefs.h>
     33  1.3.6.2     skrll #ifdef __FreeBSD__
     34  1.3.6.2     skrll __FBSDID("$FreeBSD: src/sys/net80211/ieee80211_crypto_wep.c,v 1.7 2005/06/10 16:11:24 sam Exp $");
     35  1.3.6.2     skrll #endif
     36  1.3.6.2     skrll #ifdef __NetBSD__
     37  1.3.6.3  christos __KERNEL_RCSID(0, "$NetBSD: ieee80211_crypto_wep.c,v 1.3.6.3 2005/12/11 10:29:22 christos Exp $");
     38  1.3.6.2     skrll #endif
     39  1.3.6.2     skrll 
     40  1.3.6.2     skrll /*
     41  1.3.6.2     skrll  * IEEE 802.11 WEP crypto support.
     42  1.3.6.2     skrll  */
     43  1.3.6.2     skrll #include <sys/param.h>
     44  1.3.6.2     skrll #include <sys/systm.h>
     45  1.3.6.2     skrll #include <sys/mbuf.h>
     46  1.3.6.2     skrll #include <sys/malloc.h>
     47  1.3.6.2     skrll #include <sys/kernel.h>
     48  1.3.6.2     skrll #include <sys/endian.h>
     49  1.3.6.2     skrll 
     50  1.3.6.2     skrll #include <sys/socket.h>
     51  1.3.6.2     skrll 
     52  1.3.6.2     skrll #include <net/if.h>
     53  1.3.6.2     skrll #include <net/if_media.h>
     54  1.3.6.2     skrll 
     55  1.3.6.2     skrll #include <net80211/ieee80211_var.h>
     56  1.3.6.2     skrll 
     57  1.3.6.2     skrll static	void *wep_attach(struct ieee80211com *, struct ieee80211_key *);
     58  1.3.6.2     skrll static	void wep_detach(struct ieee80211_key *);
     59  1.3.6.2     skrll static	int wep_setkey(struct ieee80211_key *);
     60  1.3.6.2     skrll static	int wep_encap(struct ieee80211_key *, struct mbuf *, u_int8_t keyid);
     61  1.3.6.2     skrll static	int wep_decap(struct ieee80211_key *, struct mbuf *, int hdrlen);
     62  1.3.6.2     skrll static	int wep_enmic(struct ieee80211_key *, struct mbuf *, int);
     63  1.3.6.2     skrll static	int wep_demic(struct ieee80211_key *, struct mbuf *, int);
     64  1.3.6.2     skrll 
     65  1.3.6.2     skrll const struct ieee80211_cipher ieee80211_cipher_wep = {
     66  1.3.6.2     skrll 	.ic_name	= "WEP",
     67  1.3.6.2     skrll 	.ic_cipher	= IEEE80211_CIPHER_WEP,
     68  1.3.6.2     skrll 	.ic_header	= IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN,
     69  1.3.6.2     skrll 	.ic_trailer	= IEEE80211_WEP_CRCLEN,
     70  1.3.6.2     skrll 	.ic_miclen	= 0,
     71  1.3.6.2     skrll 	.ic_attach	= wep_attach,
     72  1.3.6.2     skrll 	.ic_detach	= wep_detach,
     73  1.3.6.2     skrll 	.ic_setkey	= wep_setkey,
     74  1.3.6.2     skrll 	.ic_encap	= wep_encap,
     75  1.3.6.2     skrll 	.ic_decap	= wep_decap,
     76  1.3.6.2     skrll 	.ic_enmic	= wep_enmic,
     77  1.3.6.2     skrll 	.ic_demic	= wep_demic,
     78  1.3.6.2     skrll };
     79  1.3.6.2     skrll 
     80  1.3.6.2     skrll #define	wep	ieee80211_cipher_wep
     81  1.3.6.2     skrll 
     82  1.3.6.2     skrll static	int wep_encrypt(struct ieee80211_key *, struct mbuf *, int hdrlen);
     83  1.3.6.2     skrll static	int wep_decrypt(struct ieee80211_key *, struct mbuf *, int hdrlen);
     84  1.3.6.2     skrll 
     85  1.3.6.2     skrll struct wep_ctx {
     86  1.3.6.2     skrll 	struct ieee80211com *wc_ic;	/* for diagnostics */
     87  1.3.6.2     skrll 	u_int32_t	wc_iv;		/* initial vector for crypto */
     88  1.3.6.2     skrll };
     89  1.3.6.2     skrll 
     90  1.3.6.2     skrll static void *
     91  1.3.6.2     skrll wep_attach(struct ieee80211com *ic, struct ieee80211_key *k)
     92  1.3.6.2     skrll {
     93  1.3.6.2     skrll 	struct wep_ctx *ctx;
     94  1.3.6.2     skrll 
     95  1.3.6.2     skrll 	MALLOC(ctx, struct wep_ctx *, sizeof(struct wep_ctx),
     96  1.3.6.2     skrll 		M_DEVBUF, M_NOWAIT | M_ZERO);
     97  1.3.6.2     skrll 	if (ctx == NULL) {
     98  1.3.6.2     skrll 		ic->ic_stats.is_crypto_nomem++;
     99  1.3.6.2     skrll 		return NULL;
    100  1.3.6.2     skrll 	}
    101  1.3.6.2     skrll 
    102  1.3.6.2     skrll 	ctx->wc_ic = ic;
    103  1.3.6.2     skrll 	get_random_bytes(&ctx->wc_iv, sizeof(ctx->wc_iv));
    104  1.3.6.2     skrll 	return ctx;
    105  1.3.6.2     skrll }
    106  1.3.6.2     skrll 
    107  1.3.6.2     skrll static void
    108  1.3.6.2     skrll wep_detach(struct ieee80211_key *k)
    109  1.3.6.2     skrll {
    110  1.3.6.2     skrll 	struct wep_ctx *ctx = k->wk_private;
    111  1.3.6.2     skrll 
    112  1.3.6.2     skrll 	FREE(ctx, M_DEVBUF);
    113  1.3.6.2     skrll }
    114  1.3.6.2     skrll 
    115  1.3.6.2     skrll static int
    116  1.3.6.2     skrll wep_setkey(struct ieee80211_key *k)
    117  1.3.6.2     skrll {
    118  1.3.6.2     skrll 	return k->wk_keylen >= 40/NBBY;
    119  1.3.6.2     skrll }
    120  1.3.6.2     skrll 
    121  1.3.6.2     skrll /*
    122  1.3.6.2     skrll  * Add privacy headers appropriate for the specified key.
    123  1.3.6.2     skrll  */
    124  1.3.6.2     skrll static int
    125  1.3.6.2     skrll wep_encap(struct ieee80211_key *k, struct mbuf *m, u_int8_t keyid)
    126  1.3.6.2     skrll {
    127  1.3.6.2     skrll 	struct wep_ctx *ctx = k->wk_private;
    128  1.3.6.2     skrll 	struct ieee80211com *ic = ctx->wc_ic;
    129  1.3.6.2     skrll 	u_int32_t iv;
    130  1.3.6.2     skrll 	u_int8_t *ivp;
    131  1.3.6.2     skrll 	int hdrlen;
    132  1.3.6.2     skrll 
    133  1.3.6.2     skrll 	hdrlen = ieee80211_hdrspace(ic, mtod(m, void *));
    134  1.3.6.2     skrll 
    135  1.3.6.2     skrll 	/*
    136  1.3.6.2     skrll 	 * Copy down 802.11 header and add the IV + KeyID.
    137  1.3.6.2     skrll 	 */
    138  1.3.6.2     skrll 	M_PREPEND(m, wep.ic_header, M_NOWAIT);
    139  1.3.6.2     skrll 	if (m == NULL)
    140  1.3.6.2     skrll 		return 0;
    141  1.3.6.2     skrll 	ivp = mtod(m, u_int8_t *);
    142  1.3.6.2     skrll 	ovbcopy(ivp + wep.ic_header, ivp, hdrlen);
    143  1.3.6.2     skrll 	ivp += hdrlen;
    144  1.3.6.2     skrll 
    145  1.3.6.2     skrll 	/*
    146  1.3.6.2     skrll 	 * XXX
    147  1.3.6.2     skrll 	 * IV must not duplicate during the lifetime of the key.
    148  1.3.6.2     skrll 	 * But no mechanism to renew keys is defined in IEEE 802.11
    149  1.3.6.2     skrll 	 * for WEP.  And the IV may be duplicated at other stations
    150  1.3.6.2     skrll 	 * because the session key itself is shared.  So we use a
    151  1.3.6.2     skrll 	 * pseudo random IV for now, though it is not the right way.
    152  1.3.6.2     skrll 	 *
    153  1.3.6.2     skrll 	 * NB: Rather than use a strictly random IV we select a
    154  1.3.6.2     skrll 	 * random one to start and then increment the value for
    155  1.3.6.2     skrll 	 * each frame.  This is an explicit tradeoff between
    156  1.3.6.2     skrll 	 * overhead and security.  Given the basic insecurity of
    157  1.3.6.2     skrll 	 * WEP this seems worthwhile.
    158  1.3.6.2     skrll 	 */
    159  1.3.6.2     skrll 
    160  1.3.6.2     skrll 	/*
    161  1.3.6.2     skrll 	 * Skip 'bad' IVs from Fluhrer/Mantin/Shamir:
    162  1.3.6.2     skrll 	 * (B, 255, N) with 3 <= B < 16 and 0 <= N <= 255
    163  1.3.6.2     skrll 	 */
    164  1.3.6.2     skrll 	iv = ctx->wc_iv;
    165  1.3.6.2     skrll 	if ((iv & 0xff00) == 0xff00) {
    166  1.3.6.2     skrll 		int B = (iv & 0xff0000) >> 16;
    167  1.3.6.2     skrll 		if (3 <= B && B < 16)
    168  1.3.6.2     skrll 			iv += 0x0100;
    169  1.3.6.2     skrll 	}
    170  1.3.6.2     skrll 	ctx->wc_iv = iv + 1;
    171  1.3.6.2     skrll 
    172  1.3.6.2     skrll 	/*
    173  1.3.6.2     skrll 	 * NB: Preserve byte order of IV for packet
    174  1.3.6.2     skrll 	 *     sniffers; it doesn't matter otherwise.
    175  1.3.6.2     skrll 	 */
    176  1.3.6.2     skrll #if _BYTE_ORDER == _BIG_ENDIAN
    177  1.3.6.2     skrll 	ivp[0] = iv >> 0;
    178  1.3.6.2     skrll 	ivp[1] = iv >> 8;
    179  1.3.6.2     skrll 	ivp[2] = iv >> 16;
    180  1.3.6.2     skrll #else
    181  1.3.6.2     skrll 	ivp[2] = iv >> 0;
    182  1.3.6.2     skrll 	ivp[1] = iv >> 8;
    183  1.3.6.2     skrll 	ivp[0] = iv >> 16;
    184  1.3.6.2     skrll #endif
    185  1.3.6.2     skrll 	ivp[3] = keyid;
    186  1.3.6.2     skrll 
    187  1.3.6.2     skrll 	/*
    188  1.3.6.2     skrll 	 * Finally, do software encrypt if neeed.
    189  1.3.6.2     skrll 	 */
    190  1.3.6.2     skrll 	if ((k->wk_flags & IEEE80211_KEY_SWCRYPT) &&
    191  1.3.6.2     skrll 	    !wep_encrypt(k, m, hdrlen))
    192  1.3.6.2     skrll 		return 0;
    193  1.3.6.2     skrll 
    194  1.3.6.2     skrll 	return 1;
    195  1.3.6.2     skrll }
    196  1.3.6.2     skrll 
    197  1.3.6.2     skrll /*
    198  1.3.6.2     skrll  * Add MIC to the frame as needed.
    199  1.3.6.2     skrll  */
    200  1.3.6.2     skrll static int
    201  1.3.6.2     skrll wep_enmic(struct ieee80211_key *k, struct mbuf *m, int force)
    202  1.3.6.2     skrll {
    203  1.3.6.2     skrll 
    204  1.3.6.2     skrll 	return 1;
    205  1.3.6.2     skrll }
    206  1.3.6.2     skrll 
    207  1.3.6.2     skrll /*
    208  1.3.6.2     skrll  * Validate and strip privacy headers (and trailer) for a
    209  1.3.6.2     skrll  * received frame.  If necessary, decrypt the frame using
    210  1.3.6.2     skrll  * the specified key.
    211  1.3.6.2     skrll  */
    212  1.3.6.2     skrll static int
    213  1.3.6.2     skrll wep_decap(struct ieee80211_key *k, struct mbuf *m, int hdrlen)
    214  1.3.6.2     skrll {
    215  1.3.6.2     skrll 	struct wep_ctx *ctx = k->wk_private;
    216  1.3.6.2     skrll 	struct ieee80211_frame *wh;
    217  1.3.6.2     skrll 
    218  1.3.6.2     skrll 	wh = mtod(m, struct ieee80211_frame *);
    219  1.3.6.2     skrll 
    220  1.3.6.2     skrll 	/*
    221  1.3.6.2     skrll 	 * Check if the device handled the decrypt in hardware.
    222  1.3.6.2     skrll 	 * If so we just strip the header; otherwise we need to
    223  1.3.6.2     skrll 	 * handle the decrypt in software.
    224  1.3.6.2     skrll 	 */
    225  1.3.6.2     skrll 	if ((k->wk_flags & IEEE80211_KEY_SWCRYPT) &&
    226  1.3.6.2     skrll 	    !wep_decrypt(k, m, hdrlen)) {
    227  1.3.6.2     skrll 		IEEE80211_DPRINTF(ctx->wc_ic, IEEE80211_MSG_CRYPTO,
    228  1.3.6.2     skrll 		    "[%s] WEP ICV mismatch on decrypt\n",
    229  1.3.6.2     skrll 		    ether_sprintf(wh->i_addr2));
    230  1.3.6.2     skrll 		ctx->wc_ic->ic_stats.is_rx_wepfail++;
    231  1.3.6.2     skrll 		return 0;
    232  1.3.6.2     skrll 	}
    233  1.3.6.2     skrll 
    234  1.3.6.2     skrll 	/*
    235  1.3.6.2     skrll 	 * Copy up 802.11 header and strip crypto bits.
    236  1.3.6.2     skrll 	 */
    237  1.3.6.2     skrll 	ovbcopy(mtod(m, void *), mtod(m, u_int8_t *) + wep.ic_header, hdrlen);
    238  1.3.6.2     skrll 	m_adj(m, wep.ic_header);
    239  1.3.6.2     skrll 	m_adj(m, -wep.ic_trailer);
    240  1.3.6.2     skrll 
    241  1.3.6.2     skrll 	return 1;
    242  1.3.6.2     skrll }
    243  1.3.6.2     skrll 
    244  1.3.6.2     skrll /*
    245  1.3.6.2     skrll  * Verify and strip MIC from the frame.
    246  1.3.6.2     skrll  */
    247  1.3.6.2     skrll static int
    248  1.3.6.2     skrll wep_demic(struct ieee80211_key *k, struct mbuf *skb, int force)
    249  1.3.6.2     skrll {
    250  1.3.6.2     skrll 	return 1;
    251  1.3.6.2     skrll }
    252  1.3.6.2     skrll 
    253  1.3.6.2     skrll static const uint32_t crc32_table[256] = {
    254  1.3.6.2     skrll 	0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
    255  1.3.6.2     skrll 	0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
    256  1.3.6.2     skrll 	0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
    257  1.3.6.2     skrll 	0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
    258  1.3.6.2     skrll 	0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
    259  1.3.6.2     skrll 	0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
    260  1.3.6.2     skrll 	0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
    261  1.3.6.2     skrll 	0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
    262  1.3.6.2     skrll 	0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
    263  1.3.6.2     skrll 	0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
    264  1.3.6.2     skrll 	0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
    265  1.3.6.2     skrll 	0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
    266  1.3.6.2     skrll 	0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
    267  1.3.6.2     skrll 	0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
    268  1.3.6.2     skrll 	0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
    269  1.3.6.2     skrll 	0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
    270  1.3.6.2     skrll 	0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
    271  1.3.6.2     skrll 	0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
    272  1.3.6.2     skrll 	0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
    273  1.3.6.2     skrll 	0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
    274  1.3.6.2     skrll 	0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
    275  1.3.6.2     skrll 	0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
    276  1.3.6.2     skrll 	0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
    277  1.3.6.2     skrll 	0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
    278  1.3.6.2     skrll 	0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
    279  1.3.6.2     skrll 	0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
    280  1.3.6.2     skrll 	0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
    281  1.3.6.2     skrll 	0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
    282  1.3.6.2     skrll 	0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
    283  1.3.6.2     skrll 	0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
    284  1.3.6.2     skrll 	0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
    285  1.3.6.2     skrll 	0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
    286  1.3.6.2     skrll 	0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
    287  1.3.6.2     skrll 	0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
    288  1.3.6.2     skrll 	0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
    289  1.3.6.2     skrll 	0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
    290  1.3.6.2     skrll 	0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
    291  1.3.6.2     skrll 	0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
    292  1.3.6.2     skrll 	0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
    293  1.3.6.2     skrll 	0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
    294  1.3.6.2     skrll 	0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
    295  1.3.6.2     skrll 	0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
    296  1.3.6.2     skrll 	0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
    297  1.3.6.2     skrll 	0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
    298  1.3.6.2     skrll 	0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
    299  1.3.6.2     skrll 	0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
    300  1.3.6.2     skrll 	0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
    301  1.3.6.2     skrll 	0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
    302  1.3.6.2     skrll 	0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
    303  1.3.6.2     skrll 	0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
    304  1.3.6.2     skrll 	0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
    305  1.3.6.2     skrll 	0x2d02ef8dL
    306  1.3.6.2     skrll };
    307  1.3.6.2     skrll 
    308  1.3.6.2     skrll static int
    309  1.3.6.2     skrll wep_encrypt(struct ieee80211_key *key, struct mbuf *m0, int hdrlen)
    310  1.3.6.2     skrll {
    311  1.3.6.2     skrll #define S_SWAP(a,b) do { uint8_t t = S[a]; S[a] = S[b]; S[b] = t; } while(0)
    312  1.3.6.2     skrll 	struct wep_ctx *ctx = key->wk_private;
    313  1.3.6.2     skrll 	struct mbuf *m = m0;
    314  1.3.6.2     skrll 	u_int8_t rc4key[IEEE80211_WEP_IVLEN + IEEE80211_KEYBUF_SIZE];
    315  1.3.6.2     skrll 	uint8_t icv[IEEE80211_WEP_CRCLEN];
    316  1.3.6.2     skrll 	uint32_t i, j, k, crc;
    317  1.3.6.2     skrll 	size_t buflen, data_len;
    318  1.3.6.2     skrll 	uint8_t S[256];
    319  1.3.6.2     skrll 	uint8_t *pos;
    320  1.3.6.2     skrll 	u_int off, keylen;
    321  1.3.6.2     skrll 
    322  1.3.6.2     skrll 	ctx->wc_ic->ic_stats.is_crypto_wep++;
    323  1.3.6.2     skrll 
    324  1.3.6.2     skrll 	/* NB: this assumes the header was pulled up */
    325  1.3.6.2     skrll 	memcpy(rc4key, mtod(m, u_int8_t *) + hdrlen, IEEE80211_WEP_IVLEN);
    326  1.3.6.2     skrll 	memcpy(rc4key + IEEE80211_WEP_IVLEN, key->wk_key, key->wk_keylen);
    327  1.3.6.2     skrll 
    328  1.3.6.2     skrll 	/* Setup RC4 state */
    329  1.3.6.2     skrll 	for (i = 0; i < 256; i++)
    330  1.3.6.2     skrll 		S[i] = i;
    331  1.3.6.2     skrll 	j = 0;
    332  1.3.6.2     skrll 	keylen = key->wk_keylen + IEEE80211_WEP_IVLEN;
    333  1.3.6.2     skrll 	for (i = 0; i < 256; i++) {
    334  1.3.6.2     skrll 		j = (j + S[i] + rc4key[i % keylen]) & 0xff;
    335  1.3.6.2     skrll 		S_SWAP(i, j);
    336  1.3.6.2     skrll 	}
    337  1.3.6.2     skrll 
    338  1.3.6.2     skrll 	off = hdrlen + wep.ic_header;
    339  1.3.6.2     skrll 	data_len = m->m_pkthdr.len - off;
    340  1.3.6.2     skrll 
    341  1.3.6.2     skrll 	/* Compute CRC32 over unencrypted data and apply RC4 to data */
    342  1.3.6.2     skrll 	crc = ~0;
    343  1.3.6.2     skrll 	i = j = 0;
    344  1.3.6.2     skrll 	pos = mtod(m, uint8_t *) + off;
    345  1.3.6.2     skrll 	buflen = m->m_len - off;
    346  1.3.6.2     skrll 	for (;;) {
    347  1.3.6.2     skrll 		if (buflen > data_len)
    348  1.3.6.2     skrll 			buflen = data_len;
    349  1.3.6.2     skrll 		data_len -= buflen;
    350  1.3.6.2     skrll 		for (k = 0; k < buflen; k++) {
    351  1.3.6.2     skrll 			crc = crc32_table[(crc ^ *pos) & 0xff] ^ (crc >> 8);
    352  1.3.6.2     skrll 			i = (i + 1) & 0xff;
    353  1.3.6.2     skrll 			j = (j + S[i]) & 0xff;
    354  1.3.6.2     skrll 			S_SWAP(i, j);
    355  1.3.6.2     skrll 			*pos++ ^= S[(S[i] + S[j]) & 0xff];
    356  1.3.6.2     skrll 		}
    357  1.3.6.2     skrll 		if (m->m_next == NULL) {
    358  1.3.6.2     skrll 			if (data_len != 0) {		/* out of data */
    359  1.3.6.2     skrll 				IEEE80211_DPRINTF(ctx->wc_ic,
    360  1.3.6.2     skrll 				    IEEE80211_MSG_CRYPTO,
    361  1.3.6.2     skrll 				    "[%s] out of data for WEP (data_len %zu)\n",
    362  1.3.6.2     skrll 				    ether_sprintf(mtod(m0,
    363  1.3.6.2     skrll 					struct ieee80211_frame *)->i_addr2),
    364  1.3.6.2     skrll 				    data_len);
    365  1.3.6.2     skrll 				return 0;
    366  1.3.6.2     skrll 			}
    367  1.3.6.2     skrll 			break;
    368  1.3.6.2     skrll 		}
    369  1.3.6.2     skrll 		m = m->m_next;
    370  1.3.6.2     skrll 		pos = mtod(m, uint8_t *);
    371  1.3.6.2     skrll 		buflen = m->m_len;
    372  1.3.6.2     skrll 	}
    373  1.3.6.2     skrll 	crc = ~crc;
    374  1.3.6.2     skrll 
    375  1.3.6.2     skrll 	/* Append little-endian CRC32 and encrypt it to produce ICV */
    376  1.3.6.2     skrll 	icv[0] = crc;
    377  1.3.6.2     skrll 	icv[1] = crc >> 8;
    378  1.3.6.2     skrll 	icv[2] = crc >> 16;
    379  1.3.6.2     skrll 	icv[3] = crc >> 24;
    380  1.3.6.2     skrll 	for (k = 0; k < IEEE80211_WEP_CRCLEN; k++) {
    381  1.3.6.2     skrll 		i = (i + 1) & 0xff;
    382  1.3.6.2     skrll 		j = (j + S[i]) & 0xff;
    383  1.3.6.2     skrll 		S_SWAP(i, j);
    384  1.3.6.2     skrll 		icv[k] ^= S[(S[i] + S[j]) & 0xff];
    385  1.3.6.2     skrll 	}
    386  1.3.6.2     skrll 	return m_append(m0, IEEE80211_WEP_CRCLEN, icv);
    387  1.3.6.2     skrll #undef S_SWAP
    388  1.3.6.2     skrll }
    389  1.3.6.2     skrll 
    390  1.3.6.2     skrll static int
    391  1.3.6.2     skrll wep_decrypt(struct ieee80211_key *key, struct mbuf *m0, int hdrlen)
    392  1.3.6.2     skrll {
    393  1.3.6.2     skrll #define S_SWAP(a,b) do { uint8_t t = S[a]; S[a] = S[b]; S[b] = t; } while(0)
    394  1.3.6.2     skrll 	struct wep_ctx *ctx = key->wk_private;
    395  1.3.6.2     skrll 	struct mbuf *m = m0;
    396  1.3.6.2     skrll 	u_int8_t rc4key[IEEE80211_WEP_IVLEN + IEEE80211_KEYBUF_SIZE];
    397  1.3.6.2     skrll 	uint8_t icv[IEEE80211_WEP_CRCLEN];
    398  1.3.6.2     skrll 	uint32_t i, j, k, crc;
    399  1.3.6.2     skrll 	size_t buflen, data_len;
    400  1.3.6.2     skrll 	uint8_t S[256];
    401  1.3.6.2     skrll 	uint8_t *pos;
    402  1.3.6.2     skrll 	u_int off, keylen;
    403  1.3.6.2     skrll 
    404  1.3.6.2     skrll 	ctx->wc_ic->ic_stats.is_crypto_wep++;
    405  1.3.6.2     skrll 
    406  1.3.6.2     skrll 	/* NB: this assumes the header was pulled up */
    407  1.3.6.2     skrll 	memcpy(rc4key, mtod(m, u_int8_t *) + hdrlen, IEEE80211_WEP_IVLEN);
    408  1.3.6.2     skrll 	memcpy(rc4key + IEEE80211_WEP_IVLEN, key->wk_key, key->wk_keylen);
    409  1.3.6.2     skrll 
    410  1.3.6.2     skrll 	/* Setup RC4 state */
    411  1.3.6.2     skrll 	for (i = 0; i < 256; i++)
    412  1.3.6.2     skrll 		S[i] = i;
    413  1.3.6.2     skrll 	j = 0;
    414  1.3.6.2     skrll 	keylen = key->wk_keylen + IEEE80211_WEP_IVLEN;
    415  1.3.6.2     skrll 	for (i = 0; i < 256; i++) {
    416  1.3.6.2     skrll 		j = (j + S[i] + rc4key[i % keylen]) & 0xff;
    417  1.3.6.2     skrll 		S_SWAP(i, j);
    418  1.3.6.2     skrll 	}
    419  1.3.6.2     skrll 
    420  1.3.6.2     skrll 	off = hdrlen + wep.ic_header;
    421  1.3.6.2     skrll 	data_len = m->m_pkthdr.len - (off + wep.ic_trailer),
    422  1.3.6.2     skrll 
    423  1.3.6.2     skrll 	/* Compute CRC32 over unencrypted data and apply RC4 to data */
    424  1.3.6.2     skrll 	crc = ~0;
    425  1.3.6.2     skrll 	i = j = 0;
    426  1.3.6.2     skrll 	pos = mtod(m, uint8_t *) + off;
    427  1.3.6.2     skrll 	buflen = m->m_len - off;
    428  1.3.6.2     skrll 	for (;;) {
    429  1.3.6.2     skrll 		if (buflen > data_len)
    430  1.3.6.2     skrll 			buflen = data_len;
    431  1.3.6.2     skrll 		data_len -= buflen;
    432  1.3.6.2     skrll 		for (k = 0; k < buflen; k++) {
    433  1.3.6.2     skrll 			i = (i + 1) & 0xff;
    434  1.3.6.2     skrll 			j = (j + S[i]) & 0xff;
    435  1.3.6.2     skrll 			S_SWAP(i, j);
    436  1.3.6.2     skrll 			*pos ^= S[(S[i] + S[j]) & 0xff];
    437  1.3.6.2     skrll 			crc = crc32_table[(crc ^ *pos) & 0xff] ^ (crc >> 8);
    438  1.3.6.2     skrll 			pos++;
    439  1.3.6.2     skrll 		}
    440  1.3.6.2     skrll 		m = m->m_next;
    441  1.3.6.2     skrll 		if (m == NULL) {
    442  1.3.6.2     skrll 			if (data_len != 0) {		/* out of data */
    443  1.3.6.2     skrll 				IEEE80211_DPRINTF(ctx->wc_ic,
    444  1.3.6.2     skrll 				    IEEE80211_MSG_CRYPTO,
    445  1.3.6.2     skrll 				    "[%s] out of data for WEP (data_len %zu)\n",
    446  1.3.6.2     skrll 				    ether_sprintf(mtod(m0,
    447  1.3.6.2     skrll 					struct ieee80211_frame *)->i_addr2),
    448  1.3.6.2     skrll 				    data_len);
    449  1.3.6.2     skrll 				return 0;
    450  1.3.6.2     skrll 			}
    451  1.3.6.2     skrll 			break;
    452  1.3.6.2     skrll 		}
    453  1.3.6.2     skrll 		pos = mtod(m, uint8_t *);
    454  1.3.6.2     skrll 		buflen = m->m_len;
    455  1.3.6.2     skrll 	}
    456  1.3.6.2     skrll 	crc = ~crc;
    457  1.3.6.2     skrll 
    458  1.3.6.2     skrll 	/* Encrypt little-endian CRC32 and verify that it matches with
    459  1.3.6.2     skrll 	 * received ICV */
    460  1.3.6.2     skrll 	icv[0] = crc;
    461  1.3.6.2     skrll 	icv[1] = crc >> 8;
    462  1.3.6.2     skrll 	icv[2] = crc >> 16;
    463  1.3.6.2     skrll 	icv[3] = crc >> 24;
    464  1.3.6.2     skrll 	for (k = 0; k < IEEE80211_WEP_CRCLEN; k++) {
    465  1.3.6.2     skrll 		i = (i + 1) & 0xff;
    466  1.3.6.2     skrll 		j = (j + S[i]) & 0xff;
    467  1.3.6.2     skrll 		S_SWAP(i, j);
    468  1.3.6.2     skrll 		/* XXX assumes ICV is contiguous in mbuf */
    469  1.3.6.2     skrll 		if ((icv[k] ^ S[(S[i] + S[j]) & 0xff]) != *pos++) {
    470  1.3.6.2     skrll 			/* ICV mismatch - drop frame */
    471  1.3.6.2     skrll 			return 0;
    472  1.3.6.2     skrll 		}
    473  1.3.6.2     skrll 	}
    474  1.3.6.2     skrll 	return 1;
    475  1.3.6.2     skrll #undef S_SWAP
    476  1.3.6.2     skrll }
    477  1.3.6.3  christos 
    478  1.3.6.3  christos IEEE80211_CRYPTO_SETUP(wep_register)
    479  1.3.6.3  christos {
    480  1.3.6.3  christos 	ieee80211_crypto_register(&wep);
    481  1.3.6.3  christos }
    482