Home | History | Annotate | Line # | Download | only in net80211
ieee80211_crypto.c revision 1.2
      1 /*-
      2  * Copyright (c) 2001 Atsushi Onoe
      3  * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting
      4  * All rights reserved.
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  * 1. Redistributions of source code must retain the above copyright
     10  *    notice, this list of conditions and the following disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above copyright
     12  *    notice, this list of conditions and the following disclaimer in the
     13  *    documentation and/or other materials provided with the distribution.
     14  * 3. The name of the author may not be used to endorse or promote products
     15  *    derived from this software without specific prior written permission.
     16  *
     17  * Alternatively, this software may be distributed under the terms of the
     18  * GNU General Public License ("GPL") version 2 as published by the Free
     19  * Software Foundation.
     20  *
     21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     24  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     26  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     31  */
     32 
     33 #include <sys/cdefs.h>
     34 __FBSDID("$FreeBSD: src/sys/net80211/ieee80211_crypto.c,v 1.2 2003/06/27 05:13:52 sam Exp $");
     35 
     36 #include "opt_inet.h"
     37 
     38 #include <sys/param.h>
     39 #include <sys/systm.h>
     40 #include <sys/mbuf.h>
     41 #include <sys/malloc.h>
     42 #include <sys/kernel.h>
     43 #include <sys/socket.h>
     44 #include <sys/sockio.h>
     45 #include <sys/endian.h>
     46 #include <sys/errno.h>
     47 #include <sys/bus.h>
     48 #include <sys/proc.h>
     49 #include <sys/sysctl.h>
     50 
     51 #ifdef __FreeBSD__
     52 #include <machine/atomic.h>
     53 #endif
     54 
     55 #include <net/if.h>
     56 #include <net/if_dl.h>
     57 #include <net/if_media.h>
     58 #include <net/if_arp.h>
     59 #ifdef __FreeBSD__
     60 #include <net/ethernet.h>
     61 #endif
     62 #include <net/if_llc.h>
     63 
     64 #include <net80211/ieee80211_var.h>
     65 
     66 #include <net/bpf.h>
     67 
     68 #ifdef INET
     69 #include <netinet/in.h>
     70 #include <netinet/if_ether.h>
     71 #endif
     72 
     73 #ifdef __FreeBSD__
     74 #include <crypto/rc4/rc4.h>
     75 #define	arc4_ctxlen()			sizeof (struct rc4_state)
     76 #define	arc4_setkey(_c,_k,_l)		rc4_init(_c,_k,_l)
     77 #define	arc4_encrypt(_c,_d,_s,_l)	rc4_crypt(_c,_s,_d,_l)
     78 #else
     79 #include <crypto/arc4/arc4.h>
     80 #endif
     81 
     82 static	void ieee80211_crc_init(void);
     83 static	u_int32_t ieee80211_crc_update(u_int32_t crc, u_int8_t *buf, int len);
     84 
     85 void
     86 ieee80211_crypto_attach(struct ifnet *ifp)
     87 {
     88 	struct ieee80211com *ic = (void *)ifp;
     89 
     90 	/*
     91 	 * Setup crypto support.
     92 	 */
     93 	ieee80211_crc_init();
     94 	ic->ic_iv = arc4random();
     95 }
     96 
     97 void
     98 ieee80211_crypto_detach(struct ifnet *ifp)
     99 {
    100 	struct ieee80211com *ic = (void *)ifp;
    101 
    102 	if (ic->ic_wep_ctx != NULL) {
    103 		free(ic->ic_wep_ctx, M_DEVBUF);
    104 		ic->ic_wep_ctx = NULL;
    105 	}
    106 }
    107 
    108 struct mbuf *
    109 ieee80211_wep_crypt(struct ifnet *ifp, struct mbuf *m0, int txflag)
    110 {
    111 	struct ieee80211com *ic = (void *)ifp;
    112 	struct mbuf *m, *n, *n0;
    113 	struct ieee80211_frame *wh;
    114 	int i, left, len, moff, noff, kid;
    115 	u_int32_t iv, crc;
    116 	u_int8_t *ivp;
    117 	void *ctx;
    118 	u_int8_t keybuf[IEEE80211_WEP_IVLEN + IEEE80211_KEYBUF_SIZE];
    119 	u_int8_t crcbuf[IEEE80211_WEP_CRCLEN];
    120 
    121 	n0 = NULL;
    122 	if ((ctx = ic->ic_wep_ctx) == NULL) {
    123 		ctx = malloc(arc4_ctxlen(), M_DEVBUF, M_NOWAIT);
    124 		if (ctx == NULL)
    125 			goto fail;
    126 		ic->ic_wep_ctx = ctx;
    127 	}
    128 	m = m0;
    129 	left = m->m_pkthdr.len;
    130 	MGET(n, M_DONTWAIT, m->m_type);
    131 	n0 = n;
    132 	if (n == NULL)
    133 		goto fail;
    134 	M_MOVE_PKTHDR(n, m);
    135 	len = IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN + IEEE80211_WEP_CRCLEN;
    136 	if (txflag) {
    137 		n->m_pkthdr.len += len;
    138 	} else {
    139 		n->m_pkthdr.len -= len;
    140 		left -= len;
    141 	}
    142 	n->m_len = MHLEN;
    143 	if (n->m_pkthdr.len >= MINCLSIZE) {
    144 		MCLGET(n, M_DONTWAIT);
    145 		if (n->m_flags & M_EXT)
    146 			n->m_len = n->m_ext.ext_size;
    147 	}
    148 	len = sizeof(struct ieee80211_frame);
    149 	memcpy(mtod(n, caddr_t), mtod(m, caddr_t), len);
    150 	wh = mtod(n, struct ieee80211_frame *);
    151 	left -= len;
    152 	moff = len;
    153 	noff = len;
    154 	if (txflag) {
    155 		kid = ic->ic_wep_txkey;
    156 		wh->i_fc[1] |= IEEE80211_FC1_WEP;
    157                 iv = ic->ic_iv;
    158 		/*
    159 		 * Skip 'bad' IVs from Fluhrer/Mantin/Shamir:
    160 		 * (B, 255, N) with 3 <= B < 8
    161 		 */
    162 		if (iv >= 0x03ff00 &&
    163 		    (iv & 0xf8ff00) == 0x00ff00)
    164 			iv += 0x000100;
    165 		ic->ic_iv = iv + 1;
    166 		/* put iv in little endian to prepare 802.11i */
    167 		ivp = mtod(n, u_int8_t *) + noff;
    168 		for (i = 0; i < IEEE80211_WEP_IVLEN; i++) {
    169 			ivp[i] = iv & 0xff;
    170 			iv >>= 8;
    171 		}
    172 		ivp[IEEE80211_WEP_IVLEN] = kid << 6;	/* pad and keyid */
    173 		noff += IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN;
    174 	} else {
    175 		wh->i_fc[1] &= ~IEEE80211_FC1_WEP;
    176 		ivp = mtod(m, u_int8_t *) + moff;
    177 		kid = ivp[IEEE80211_WEP_IVLEN] >> 6;
    178 		moff += IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN;
    179 	}
    180 	memcpy(keybuf, ivp, IEEE80211_WEP_IVLEN);
    181 	memcpy(keybuf + IEEE80211_WEP_IVLEN, ic->ic_nw_keys[kid].wk_key,
    182 	    ic->ic_nw_keys[kid].wk_len);
    183 	arc4_setkey(ctx, keybuf,
    184 	    IEEE80211_WEP_IVLEN + ic->ic_nw_keys[kid].wk_len);
    185 
    186 	/* encrypt with calculating CRC */
    187 	crc = ~0;
    188 	while (left > 0) {
    189 		len = m->m_len - moff;
    190 		if (len == 0) {
    191 			m = m->m_next;
    192 			moff = 0;
    193 			continue;
    194 		}
    195 		if (len > n->m_len - noff) {
    196 			len = n->m_len - noff;
    197 			if (len == 0) {
    198 				MGET(n->m_next, M_DONTWAIT, n->m_type);
    199 				if (n->m_next == NULL)
    200 					goto fail;
    201 				n = n->m_next;
    202 				n->m_len = MLEN;
    203 				if (left >= MINCLSIZE) {
    204 					MCLGET(n, M_DONTWAIT);
    205 					if (n->m_flags & M_EXT)
    206 						n->m_len = n->m_ext.ext_size;
    207 				}
    208 				noff = 0;
    209 				continue;
    210 			}
    211 		}
    212 		if (len > left)
    213 			len = left;
    214 		arc4_encrypt(ctx, mtod(n, caddr_t) + noff,
    215 		    mtod(m, caddr_t) + moff, len);
    216 		if (txflag)
    217 			crc = ieee80211_crc_update(crc,
    218 			    mtod(m, u_int8_t *) + moff, len);
    219 		else
    220 			crc = ieee80211_crc_update(crc,
    221 			    mtod(n, u_int8_t *) + noff, len);
    222 		left -= len;
    223 		moff += len;
    224 		noff += len;
    225 	}
    226 	crc = ~crc;
    227 	if (txflag) {
    228 		*(u_int32_t *)crcbuf = htole32(crc);
    229 		if (n->m_len >= noff + sizeof(crcbuf))
    230 			n->m_len = noff + sizeof(crcbuf);
    231 		else {
    232 			n->m_len = noff;
    233 			MGET(n->m_next, M_DONTWAIT, n->m_type);
    234 			if (n->m_next == NULL)
    235 				goto fail;
    236 			n = n->m_next;
    237 			n->m_len = sizeof(crcbuf);
    238 			noff = 0;
    239 		}
    240 		arc4_encrypt(ctx, mtod(n, caddr_t) + noff, crcbuf,
    241 		    sizeof(crcbuf));
    242 	} else {
    243 		n->m_len = noff;
    244 		for (noff = 0; noff < sizeof(crcbuf); noff += len) {
    245 			len = sizeof(crcbuf) - noff;
    246 			if (len > m->m_len - moff)
    247 				len = m->m_len - moff;
    248 			if (len > 0)
    249 				arc4_encrypt(ctx, crcbuf + noff,
    250 				    mtod(m, caddr_t) + moff, len);
    251 			m = m->m_next;
    252 			moff = 0;
    253 		}
    254 		if (crc != le32toh(*(u_int32_t *)crcbuf)) {
    255 #ifdef IEEE80211_DEBUG
    256 			if (ieee80211_debug) {
    257 				if_printf(ifp, "decrypt CRC error\n");
    258 				if (ieee80211_debug > 1)
    259 					ieee80211_dump_pkt(n0->m_data,
    260 					    n0->m_len, -1, -1);
    261 			}
    262 #endif
    263 			goto fail;
    264 		}
    265 	}
    266 	m_freem(m0);
    267 	return n0;
    268 
    269   fail:
    270 	m_freem(m0);
    271 	m_freem(n0);
    272 	return NULL;
    273 }
    274 
    275 /*
    276  * CRC 32 -- routine from RFC 2083
    277  */
    278 
    279 /* Table of CRCs of all 8-bit messages */
    280 static u_int32_t ieee80211_crc_table[256];
    281 
    282 /* Make the table for a fast CRC. */
    283 static void
    284 ieee80211_crc_init(void)
    285 {
    286 	u_int32_t c;
    287 	int n, k;
    288 
    289 	for (n = 0; n < 256; n++) {
    290 		c = (u_int32_t)n;
    291 		for (k = 0; k < 8; k++) {
    292 			if (c & 1)
    293 				c = 0xedb88320UL ^ (c >> 1);
    294 			else
    295 				c = c >> 1;
    296 		}
    297 		ieee80211_crc_table[n] = c;
    298 	}
    299 }
    300 
    301 /*
    302  * Update a running CRC with the bytes buf[0..len-1]--the CRC
    303  * should be initialized to all 1's, and the transmitted value
    304  * is the 1's complement of the final running CRC
    305  */
    306 
    307 static u_int32_t
    308 ieee80211_crc_update(u_int32_t crc, u_int8_t *buf, int len)
    309 {
    310 	u_int8_t *endbuf;
    311 
    312 	for (endbuf = buf + len; buf < endbuf; buf++)
    313 		crc = ieee80211_crc_table[(crc ^ *buf) & 0xff] ^ (crc >> 8);
    314 	return crc;
    315 }
    316