xref: /illumos-gate/usr/src/uts/common/io/net80211/net80211_crypto_tkip.c (revision c7402f0767d7a0360fabd0bd449c6baf9b282074)
1 /*
2  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
3  * Use is subject to license terms.
4  */
5 
6 /*
7  * Copyright (c) 2001 Atsushi Onoe
8  * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
9  * All rights reserved.
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. The name of the author may not be used to endorse or promote products
20  *    derived from this software without specific prior written permission.
21  *
22  * Alternatively, this software may be distributed under the terms of the
23  * GNU General Public License ("GPL") version 2 as published by the Free
24  * Software Foundation.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
27  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
28  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
29  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
30  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
31  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
35  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36  */
37 
38 /*
39  * IEEE 802.11i TKIP crypto support.
40  *
41  * Part of this module is derived from similar code in the Host
42  * AP driver. The code is used with the consent of the author and
43  * it's license is included below.
44  */
45 
46 #include <sys/byteorder.h>
47 #include <sys/crypto/common.h>
48 #include <sys/crypto/api.h>
49 #include <sys/crc32.h>
50 #include <sys/random.h>
51 #include <sys/strsun.h>
52 #include "net80211_impl.h"
53 
54 static void *tkip_attach(struct ieee80211com *, struct ieee80211_key *);
55 static void tkip_detach(struct ieee80211_key *);
56 static int tkip_setkey(struct ieee80211_key *);
57 static int tkip_encap(struct ieee80211_key *, mblk_t *, uint8_t);
58 static int tkip_decap(struct ieee80211_key *, mblk_t *, int);
59 static int tkip_enmic(struct ieee80211_key *, mblk_t *, int);
60 static int tkip_demic(struct ieee80211_key *, mblk_t *, int);
61 
62 const struct ieee80211_cipher tkip  = {
63 	"TKIP",
64 	IEEE80211_CIPHER_TKIP,
65 	IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN +
66 	    IEEE80211_WEP_EXTIVLEN,
67 	IEEE80211_WEP_CRCLEN,
68 	IEEE80211_WEP_MICLEN,
69 	tkip_attach,
70 	tkip_detach,
71 	tkip_setkey,
72 	tkip_encap,
73 	tkip_decap,
74 	tkip_enmic,
75 	tkip_demic,
76 };
77 
78 struct tkip_ctx {
79 	struct ieee80211com	*tc_ic;		/* for diagnostics */
80 	uint16_t		tx_ttak[5];
81 	int			tx_phase1_done;
82 	uint8_t			tx_rc4key[16];
83 	uint16_t		rx_ttak[5];
84 	int			rx_phase1_done;
85 	uint8_t			rx_rc4key[16];
86 	uint64_t		rx_rsc;		/* held until MIC verified */
87 };
88 
89 static void michael_mic(struct tkip_ctx *, const uint8_t *,
90     mblk_t *, uint_t, size_t, uint8_t[]);
91 static int tkip_encrypt(struct tkip_ctx *, struct ieee80211_key *,
92     mblk_t *, int);
93 static int tkip_decrypt(struct tkip_ctx *, struct ieee80211_key *,
94     mblk_t *, int);
95 
96 extern int rc4_init(crypto_context_t *, const uint8_t *, int);
97 extern int rc4_crypt(crypto_context_t, const uint8_t *, uint8_t *, int);
98 extern int rc4_final(crypto_context_t, uint8_t *, int);
99 
100 /* ARGSUSED */
101 static void *
102 tkip_attach(struct ieee80211com *ic, struct ieee80211_key *k)
103 {
104 	struct tkip_ctx *ctx;
105 
106 	ctx = kmem_zalloc(sizeof (struct tkip_ctx), KM_SLEEP);
107 	if (ctx == NULL)
108 		return (NULL);
109 
110 	ctx->tc_ic = ic;
111 	return (ctx);
112 }
113 
114 static void
115 tkip_detach(struct ieee80211_key *k)
116 {
117 	struct tkip_ctx *ctx = k->wk_private;
118 
119 	if (ctx != NULL)
120 		kmem_free(ctx, sizeof (struct tkip_ctx));
121 }
122 
123 static int
124 tkip_setkey(struct ieee80211_key *k)
125 {
126 	if (k->wk_keylen != (128/NBBY))
127 		return (0);
128 
129 	k->wk_keytsc = 1;		/* TSC starts at 1 */
130 	return (1);
131 }
132 
133 /*
134  * Add privacy headers appropriate for the specified key.
135  */
136 static int
137 tkip_encap(struct ieee80211_key *k, mblk_t *mp, uint8_t keyid)
138 {
139 	struct tkip_ctx *ctx = k->wk_private;
140 	struct ieee80211com *ic = ctx->tc_ic;
141 	uint8_t *ivp;
142 	int hdrlen;
143 
144 	/*
145 	 * Handle TKIP counter measures requirement.
146 	 */
147 	if (ic->ic_flags & IEEE80211_F_COUNTERM)
148 		return (0);
149 
150 	hdrlen = ieee80211_hdrspace(mp->b_rptr);
151 	/*
152 	 * Copy down 802.11 header and add the IV, KeyID, and ExtIV.
153 	 */
154 	ivp = mp->b_rptr;
155 	ivp += hdrlen;
156 
157 	ivp[0] = k->wk_keytsc >> 8;		/* TSC1 */
158 	ivp[1] = (ivp[0] | 0x20) & 0x7f;	/* WEP seed */
159 	ivp[2] = k->wk_keytsc >> 0;		/* TSC0 */
160 	ivp[3] = keyid | IEEE80211_WEP_EXTIV;	/* KeyID | ExtID */
161 	ivp[4] = k->wk_keytsc >> 16;		/* TSC2 */
162 	ivp[5] = k->wk_keytsc >> 24;		/* TSC3 */
163 	ivp[6] = k->wk_keytsc >> 32;		/* TSC4 */
164 	ivp[7] = k->wk_keytsc >> 40;		/* TSC5 */
165 
166 	/*
167 	 * Finally, do software encrypt if neeed.
168 	 */
169 	if (k->wk_flags & IEEE80211_KEY_SWCRYPT) {
170 		if (!tkip_encrypt(ctx, k, mp, hdrlen))
171 			return (0);
172 	} else
173 		k->wk_keytsc++;		/* wrap at 48 bits */
174 
175 	return (1);
176 }
177 
178 uint64_t
179 ieee80211_read_6(uint8_t b0, uint8_t b1, uint8_t b2,
180     uint8_t b3, uint8_t b4, uint8_t b5)
181 {
182 	uint32_t iv32 = (b0 << 0) | (b1 << 8) | (b2 << 16) | (b3 << 24);
183 	uint16_t iv16 = (b4 << 0) | (b5 << 8);
184 	return ((((uint64_t)iv16) << 32) | iv32);
185 }
186 
187 /*
188  * Validate and strip privacy headers (and trailer) for a
189  * received frame.  If necessary, decrypt the frame using
190  * the specified key.
191  */
192 static int
193 tkip_decap(struct ieee80211_key *k, mblk_t *mp, int hdrlen)
194 {
195 	struct tkip_ctx *ctx = k->wk_private;
196 	struct ieee80211com *ic = ctx->tc_ic;
197 	struct ieee80211_frame tmp;
198 	uint8_t *ivp;
199 	uint64_t pn;
200 
201 	/*
202 	 * Header should have extended IV and sequence number;
203 	 * verify the former and validate the latter.
204 	 */
205 	ivp = mp->b_rptr + hdrlen;
206 	if ((ivp[IEEE80211_WEP_IVLEN] & IEEE80211_WEP_EXTIV) == 0) {
207 		/*
208 		 * No extended IV; discard frame.
209 		 */
210 		return (0);
211 	}
212 	/*
213 	 * Handle TKIP counter measures requirement.
214 	 */
215 	if (ic->ic_flags & IEEE80211_F_COUNTERM)
216 		return (0);
217 
218 	/* NB: assume IEEEE80211_WEP_MINLEN covers the extended IV */
219 	pn = ieee80211_read_6(ivp[2], ivp[0], ivp[4], ivp[5], ivp[6], ivp[7]);
220 	ctx->rx_rsc = pn;
221 	if (ctx->rx_rsc <= k->wk_keyrsc)
222 		return (0);
223 	/*
224 	 * NB: We can't update the rsc in the key until MIC is verified.
225 	 *
226 	 * We assume we are not preempted between doing the check above
227 	 * and updating wk_keyrsc when stripping the MIC in tkip_demic.
228 	 * Otherwise we might process another packet and discard it as
229 	 * a replay.
230 	 */
231 
232 	/*
233 	 * Check if the device handled the decrypt in hardware.
234 	 * If so we just strip the header; otherwise we need to
235 	 * handle the decrypt in software.
236 	 */
237 	if (k->wk_flags & IEEE80211_KEY_SWCRYPT) {
238 		if (!tkip_decrypt(ctx, k, mp, hdrlen))
239 			return (0);
240 	}
241 
242 	/*
243 	 * Copy up 802.11 header and strip crypto bits.
244 	 */
245 	bcopy(mp->b_rptr, &tmp, hdrlen);
246 	bcopy(&tmp, mp->b_rptr + tkip.ic_header, hdrlen);
247 	mp->b_rptr += tkip.ic_header;
248 	mp->b_wptr -= tkip.ic_trailer;
249 
250 	return (1);
251 }
252 
253 /*
254  * Add MIC to the frame as needed.
255  */
256 static int
257 tkip_enmic(struct ieee80211_key *k, mblk_t *mp, int force)
258 {
259 	struct tkip_ctx *ctx = k->wk_private;
260 
261 	if (force || (k->wk_flags & IEEE80211_KEY_SWMIC)) {
262 		int hdrlen;
263 		uint8_t *mic;
264 
265 		hdrlen = ieee80211_hdrspace(mp->b_rptr);
266 		mic = mp->b_wptr;
267 		mp->b_wptr += tkip.ic_miclen;
268 
269 		if ((int)(MBLKL(mp) -
270 		    (hdrlen + tkip.ic_header + tkip.ic_miclen)) < 0)
271 			return (0);	/* dead packet */
272 
273 		michael_mic(ctx, k->wk_txmic, mp, (hdrlen + tkip.ic_header),
274 		    MBLKL(mp) -
275 		    (hdrlen + tkip.ic_header + tkip.ic_miclen), mic);
276 	}
277 	return (1);
278 }
279 
280 /*
281  * Verify and strip MIC from the frame.
282  */
283 /* ARGSUSED */
284 static int
285 tkip_demic(struct ieee80211_key *k, mblk_t *mp, int force)
286 {
287 	struct tkip_ctx *ctx = k->wk_private;
288 
289 	if (force || (k->wk_flags & IEEE80211_KEY_SWMIC)) {
290 		int hdrlen = ieee80211_hdrspace(mp->b_rptr);
291 		uint8_t mic[IEEE80211_WEP_MICLEN];
292 		uint8_t mic0[IEEE80211_WEP_MICLEN];
293 
294 		michael_mic(ctx, k->wk_rxmic,
295 		    mp, hdrlen,
296 		    MBLKL(mp) - (hdrlen + tkip.ic_miclen),
297 		    mic);
298 		bcopy(mp->b_wptr - tkip.ic_miclen, mic0, tkip.ic_miclen);
299 		if (bcmp(mic, mic0, tkip.ic_miclen)) {
300 			ieee80211_dbg(IEEE80211_MSG_CRYPTO,
301 			    "tkip_demic() mic mismatch\n");
302 			return (0);
303 		}
304 	}
305 	/*
306 	 * Strip MIC from the tail.
307 	 */
308 	mp->b_wptr -= tkip.ic_miclen;
309 	/*
310 	 * Ok to update rsc now that MIC has been verified.
311 	 */
312 	k->wk_keyrsc = ctx->rx_rsc;
313 	return (1);
314 }
315 
316 /*
317  * For the avoidance of doubt, except that if any license choice other
318  * than GPL or LGPL is available it will apply instead, Sun elects to
319  * use only the General Public License version 2 (GPLv2) at this time
320  * for any software where a choice of GPL license versions is made
321  * available with the language indicating that GPLv2 or any later
322  * version may be used, or where a choice of which version of the GPL
323  * is applied is otherwise unspecified.
324  */
325 
326 /*
327  * Host AP crypt: host-based TKIP encryption implementation for Host AP driver
328  *
329  * Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi>
330  *
331  * This program is free software; you can redistribute it and/or modify
332  * it under the terms of the GNU General Public License version 2 as
333  * published by the Free Software Foundation. See README and COPYING for
334  * more details.
335  *
336  * Alternatively, this software may be distributed under the terms of BSD
337  * license.
338  */
339 
340 /* Table of CRCs of all 8-bit messages */
341 static uint32_t crc_table[] = { CRC32_TABLE };
342 
343 static uint16_t
344 RotR1(uint16_t val)
345 {
346 	return ((val >> 1) | (val << 15));
347 }
348 
349 static uint8_t
350 Lo8(uint16_t val)
351 {
352 	return (val & 0xff);
353 }
354 
355 static uint8_t
356 Hi8(uint16_t val)
357 {
358 	return (val >> 8);
359 }
360 
361 static uint16_t
362 Lo16(uint32_t val)
363 {
364 	return (val & 0xffff);
365 }
366 
367 static uint16_t
368 Hi16(uint32_t val)
369 {
370 	return (val >> 16);
371 }
372 
373 static uint16_t
374 Mk16(uint8_t hi, uint8_t lo)
375 {
376 	return (lo | (((uint16_t)hi) << 8));
377 }
378 
379 static uint16_t
380 Mk16_le(const uint16_t *v)
381 {
382 	return (LE_16(*v));
383 }
384 
385 static const uint16_t Sbox[256] = {
386 	0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154,
387 	0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A,
388 	0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B,
389 	0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B,
390 	0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F,
391 	0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F,
392 	0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5,
393 	0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F,
394 	0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB,
395 	0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397,
396 	0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED,
397 	0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A,
398 	0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194,
399 	0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3,
400 	0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104,
401 	0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D,
402 	0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39,
403 	0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695,
404 	0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83,
405 	0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76,
406 	0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4,
407 	0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B,
408 	0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0,
409 	0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018,
410 	0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751,
411 	0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85,
412 	0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12,
413 	0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9,
414 	0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7,
415 	0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A,
416 	0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8,
417 	0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A,
418 };
419 
420 static uint16_t
421 _S_(uint16_t v)
422 {
423 	uint16_t t = Sbox[Hi8(v)];
424 	return (Sbox[Lo8(v)] ^ ((t << 8) | (t >> 8)));
425 }
426 
427 #define	PHASE1_LOOP_COUNT	8
428 
429 static void
430 tkip_mixing_phase1(uint16_t *TTAK, const uint8_t *TK,
431     const uint8_t *TA, uint32_t IV32)
432 {
433 	int i, j;
434 
435 	/* Initialize the 80-bit TTAK from TSC (IV32) and TA[0..5] */
436 	TTAK[0] = Lo16(IV32);
437 	TTAK[1] = Hi16(IV32);
438 	TTAK[2] = Mk16(TA[1], TA[0]);
439 	TTAK[3] = Mk16(TA[3], TA[2]);
440 	TTAK[4] = Mk16(TA[5], TA[4]);
441 
442 	for (i = 0; i < PHASE1_LOOP_COUNT; i++) {
443 		j = 2 * (i & 1);
444 		TTAK[0] += _S_(TTAK[4] ^ Mk16(TK[1 + j], TK[0 + j]));
445 		TTAK[1] += _S_(TTAK[0] ^ Mk16(TK[5 + j], TK[4 + j]));
446 		TTAK[2] += _S_(TTAK[1] ^ Mk16(TK[9 + j], TK[8 + j]));
447 		TTAK[3] += _S_(TTAK[2] ^ Mk16(TK[13 + j], TK[12 + j]));
448 		TTAK[4] += _S_(TTAK[3] ^ Mk16(TK[1 + j], TK[0 + j])) + i;
449 	}
450 }
451 
452 static void
453 tkip_mixing_phase2(uint8_t *WEPSeed, const uint8_t *TK,
454     const uint16_t *TTAK, uint16_t IV16)
455 {
456 	/*
457 	 * Make temporary area overlap WEP seed so that the final copy can be
458 	 * avoided on little endian hosts.
459 	 */
460 	uint16_t *PPK = (uint16_t *)&WEPSeed[4];
461 
462 	/* Step 1 - make copy of TTAK and bring in TSC */
463 	PPK[0] = TTAK[0];
464 	PPK[1] = TTAK[1];
465 	PPK[2] = TTAK[2];
466 	PPK[3] = TTAK[3];
467 	PPK[4] = TTAK[4];
468 	PPK[5] = TTAK[4] + IV16;
469 
470 	/* Step 2 - 96-bit bijective mixing using S-box */
471 	PPK[0] += _S_(PPK[5] ^ Mk16_le((const uint16_t *) &TK[0]));
472 	PPK[1] += _S_(PPK[0] ^ Mk16_le((const uint16_t *) &TK[2]));
473 	PPK[2] += _S_(PPK[1] ^ Mk16_le((const uint16_t *) &TK[4]));
474 	PPK[3] += _S_(PPK[2] ^ Mk16_le((const uint16_t *) &TK[6]));
475 	PPK[4] += _S_(PPK[3] ^ Mk16_le((const uint16_t *) &TK[8]));
476 	PPK[5] += _S_(PPK[4] ^ Mk16_le((const uint16_t *) &TK[10]));
477 
478 	PPK[0] += RotR1(PPK[5] ^ Mk16_le((const uint16_t *) &TK[12]));
479 	PPK[1] += RotR1(PPK[0] ^ Mk16_le((const uint16_t *) &TK[14]));
480 	PPK[2] += RotR1(PPK[1]);
481 	PPK[3] += RotR1(PPK[2]);
482 	PPK[4] += RotR1(PPK[3]);
483 	PPK[5] += RotR1(PPK[4]);
484 
485 	/*
486 	 * Step 3 - bring in last of TK bits, assign 24-bit WEP IV value
487 	 * WEPSeed[0..2] is transmitted as WEP IV
488 	 */
489 	WEPSeed[0] = Hi8(IV16);
490 	WEPSeed[1] = (Hi8(IV16) | 0x20) & 0x7F;
491 	WEPSeed[2] = Lo8(IV16);
492 	WEPSeed[3] = Lo8((PPK[5] ^ Mk16_le((const uint16_t *) &TK[0])) >> 1);
493 
494 #ifdef _BIG_ENDIAN
495 	int i;
496 	for (i = 0; i < 6; i++)
497 		PPK[i] = (PPK[i] << 8) | (PPK[i] >> 8);
498 #endif
499 }
500 
501 static int
502 wep_encrypt(uint8_t *key, mblk_t *mp, uint_t off, size_t data_len,
503     uint8_t icv[IEEE80211_WEP_CRCLEN])
504 {
505 	uint8_t crcbuf[IEEE80211_WEP_CRCLEN];
506 	uint32_t crc;
507 	crypto_context_t ctx;
508 	int rv;
509 
510 	ctx = NULL;
511 	rv = rc4_init(&ctx, (const uint8_t *)key, 16);
512 	if (rv != CRYPTO_SUCCESS)
513 		return (0);
514 
515 	/* calculate CRC over unencrypted data */
516 	CRC32(crc, mp->b_rptr + off, data_len, -1U, crc_table);
517 
518 	/* encrypt data */
519 	(void) rc4_crypt(ctx, mp->b_rptr + off, mp->b_rptr + off, data_len);
520 
521 	/* tack on ICV */
522 	*(uint32_t *)crcbuf = LE_32(~crc);
523 	(void) rc4_crypt(ctx, crcbuf, icv, IEEE80211_WEP_CRCLEN);
524 
525 	(void) rc4_final(ctx, icv, IEEE80211_WEP_CRCLEN);
526 
527 	return (1);
528 }
529 
530 static int
531 wep_decrypt(uint8_t *key, mblk_t *mp, uint_t off, size_t data_len)
532 {
533 	uint8_t crcbuf[IEEE80211_WEP_CRCLEN];
534 	uint8_t *icv;
535 	uint32_t crc;
536 	crypto_context_t ctx;
537 	int rv;
538 
539 	ctx = NULL;
540 	rv = rc4_init(&ctx, (const uint8_t *)key, 16);
541 	if (rv != CRYPTO_SUCCESS)
542 		return (0);
543 
544 	/* decrypt data */
545 	(void) rc4_crypt(ctx, mp->b_rptr + off, mp->b_rptr + off, data_len);
546 
547 	/* calculate CRC over unencrypted data */
548 	CRC32(crc, mp->b_rptr + off, data_len, -1U, crc_table);
549 
550 	/* decrypt ICV and compare to CRC */
551 	icv = mp->b_wptr - IEEE80211_WEP_CRCLEN;
552 	(void) rc4_crypt(ctx, icv, crcbuf, IEEE80211_WEP_CRCLEN);
553 	(void) rc4_final(ctx, crcbuf, IEEE80211_WEP_CRCLEN);
554 
555 	return (crc == ~LE_32(*(uint32_t *)crcbuf));
556 }
557 
558 static uint32_t
559 rotl(uint32_t val, int bits)
560 {
561 	return ((val << bits) | (val >> (32 - bits)));
562 }
563 
564 
565 static uint32_t
566 rotr(uint32_t val, int bits)
567 {
568 	return ((val >> bits) | (val << (32 - bits)));
569 }
570 
571 
572 static uint32_t
573 xswap(uint32_t val)
574 {
575 	return (((val & 0x00ff00ff) << 8) | ((val & 0xff00ff00) >> 8));
576 }
577 
578 
579 #define	michael_block(l, r)	\
580 do {				\
581 	r ^= rotl(l, 17);	\
582 	l += r;			\
583 	r ^= xswap(l);		\
584 	l += r;			\
585 	r ^= rotl(l, 3);	\
586 	l += r;			\
587 	r ^= rotr(l, 2);	\
588 	l += r;			\
589 	_NOTE(CONSTANTCONDITION)\
590 } while (0)
591 
592 
593 static uint32_t
594 get_le32_split(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3)
595 {
596 	return (b0 | (b1 << 8) | (b2 << 16) | (b3 << 24));
597 }
598 
599 static uint32_t
600 get_le32(const uint8_t *p)
601 {
602 	return (get_le32_split(p[0], p[1], p[2], p[3]));
603 }
604 
605 
606 static void
607 put_le32(uint8_t *p, uint32_t v)
608 {
609 	p[0] = (uint8_t)v;
610 	p[1] = v >> 8;
611 	p[2] = v >> 16;
612 	p[3] = v >> 24;
613 }
614 
615 /*
616  * Craft pseudo header used to calculate the MIC.
617  */
618 static void
619 michael_mic_hdr(const struct ieee80211_frame *wh0, uint8_t hdr[16])
620 {
621 	const struct ieee80211_frame_addr4 *wh =
622 	    (const struct ieee80211_frame_addr4 *)wh0;
623 
624 	switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) {
625 	case IEEE80211_FC1_DIR_NODS:
626 		IEEE80211_ADDR_COPY(hdr, wh->i_addr1); /* DA */
627 		IEEE80211_ADDR_COPY(hdr + IEEE80211_ADDR_LEN, wh->i_addr2);
628 		break;
629 	case IEEE80211_FC1_DIR_TODS:
630 		IEEE80211_ADDR_COPY(hdr, wh->i_addr3); /* DA */
631 		IEEE80211_ADDR_COPY(hdr + IEEE80211_ADDR_LEN, wh->i_addr2);
632 		break;
633 	case IEEE80211_FC1_DIR_FROMDS:
634 		IEEE80211_ADDR_COPY(hdr, wh->i_addr1); /* DA */
635 		IEEE80211_ADDR_COPY(hdr + IEEE80211_ADDR_LEN, wh->i_addr3);
636 		break;
637 	case IEEE80211_FC1_DIR_DSTODS:
638 		IEEE80211_ADDR_COPY(hdr, wh->i_addr3); /* DA */
639 		IEEE80211_ADDR_COPY(hdr + IEEE80211_ADDR_LEN, wh->i_addr4);
640 		break;
641 	}
642 
643 	hdr[12] = 0; /* QoS not supported */
644 	hdr[13] = hdr[14] = hdr[15] = 0; /* reserved */
645 }
646 
647 /* ARGSUSED */
648 static void
649 michael_mic(struct tkip_ctx *ctx, const uint8_t *key,
650     mblk_t *mp, uint_t off, size_t data_len,
651     uint8_t mic[IEEE80211_WEP_MICLEN])
652 {
653 	uint8_t hdr[16];
654 	uint32_t l, r;
655 	const uint8_t *data;
656 	int i, blocks, last;
657 
658 	michael_mic_hdr((struct ieee80211_frame *)mp->b_rptr, hdr);
659 
660 	l = get_le32(key);
661 	r = get_le32(key + 4);
662 
663 	/* Michael MIC pseudo header: DA, SA, 3 x 0, Priority */
664 	l ^= get_le32(hdr);
665 	michael_block(l, r);
666 	l ^= get_le32(&hdr[4]);
667 	michael_block(l, r);
668 	l ^= get_le32(&hdr[8]);
669 	michael_block(l, r);
670 	l ^= get_le32(&hdr[12]);
671 	michael_block(l, r);
672 
673 	/* first buffer has special handling */
674 	data = mp->b_rptr + off;
675 
676 	blocks = data_len / 4;
677 	last = data_len % 4;
678 
679 	for (i = 0; i < blocks; i++) {
680 		l ^= get_le32(&data[4 * i]);
681 		michael_block(l, r);
682 	}
683 
684 	/* Last block and padding (0x5a, 4..7 x 0) */
685 	switch (last) {
686 	case 0:
687 		l ^= 0x5a;
688 		break;
689 	case 1:
690 		l ^= data[4 * i] | 0x5a00;
691 		break;
692 	case 2:
693 		l ^= data[4 * i] | (data[4 * i + 1] << 8) | 0x5a0000;
694 		break;
695 	case 3:
696 		l ^= data[4 * i] | (data[4 * i + 1] << 8) |
697 		    (data[4 * i + 2] << 16) | 0x5a000000;
698 		break;
699 	}
700 	michael_block(l, r);
701 	/* l ^= 0; */
702 	michael_block(l, r);
703 
704 	put_le32(mic, l);
705 	put_le32(mic + 4, r);
706 }
707 
708 static int
709 tkip_encrypt(struct tkip_ctx *ctx, struct ieee80211_key *key,
710     mblk_t *mp, int hdrlen)
711 {
712 	struct ieee80211_frame *wh;
713 	uint8_t *icv;
714 
715 	wh = (struct ieee80211_frame *)mp->b_rptr;
716 	if (!ctx->tx_phase1_done) {
717 		tkip_mixing_phase1(ctx->tx_ttak, key->wk_key, wh->i_addr2,
718 		    (uint32_t)(key->wk_keytsc >> 16));
719 		ctx->tx_phase1_done = 1;
720 	}
721 	tkip_mixing_phase2(ctx->tx_rc4key, key->wk_key, ctx->tx_ttak,
722 	    (uint16_t)key->wk_keytsc);
723 
724 	icv = mp->b_wptr;
725 	mp->b_wptr += tkip.ic_trailer;
726 
727 	(void) wep_encrypt(ctx->tx_rc4key,
728 	    mp, hdrlen + tkip.ic_header,
729 	    MBLKL(mp) -
730 	    (hdrlen + tkip.ic_header + tkip.ic_trailer),
731 	    icv);
732 
733 	key->wk_keytsc++;
734 	if ((uint16_t)(key->wk_keytsc) == 0)
735 		ctx->tx_phase1_done = 0;
736 	return (1);
737 }
738 
739 static int
740 tkip_decrypt(struct tkip_ctx *ctx, struct ieee80211_key *key,
741     mblk_t *mp, int hdrlen)
742 {
743 	struct ieee80211_frame *wh;
744 	uint32_t iv32;
745 	uint16_t iv16;
746 
747 	wh = (struct ieee80211_frame *)mp->b_rptr;
748 	/* tkip_decap already verified header and left seq in rx_rsc */
749 	iv16 = (uint16_t)ctx->rx_rsc;
750 	iv32 = (uint32_t)(ctx->rx_rsc >> 16);
751 
752 	if (iv32 != (uint32_t)(key->wk_keyrsc >> 16) || !ctx->rx_phase1_done) {
753 		tkip_mixing_phase1(ctx->rx_ttak, key->wk_key,
754 		    wh->i_addr2, iv32);
755 		ctx->rx_phase1_done = 0;	/* DHCP */
756 	}
757 	tkip_mixing_phase2(ctx->rx_rc4key, key->wk_key, ctx->rx_ttak, iv16);
758 
759 	/* m is unstripped; deduct headers + ICV to get payload */
760 	if (!wep_decrypt(ctx->rx_rc4key,
761 	    mp, hdrlen + tkip.ic_header,
762 	    MBLKL(mp) -
763 	    (hdrlen + tkip.ic_header + tkip.ic_trailer))) {
764 		if (iv32 != (uint32_t)(key->wk_keyrsc >> 16)) {
765 			/*
766 			 * Previously cached Phase1 result was already lost, so
767 			 * it needs to be recalculated for the next packet.
768 			 */
769 			ctx->rx_phase1_done = 0;
770 		}
771 		ieee80211_dbg(IEEE80211_MSG_CRYPTO, "tkip_decrypt() error\n");
772 		return (0);
773 	}
774 	return (1);
775 }
776