xref: /illumos-gate/usr/src/uts/common/io/net80211/net80211_crypto_tkip.c (revision 56f33205c9ed776c3c909e07d52e94610a675740)
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-2008 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(ic, 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 	uint8_t *ivp;
198 	uint64_t pn;
199 
200 	/*
201 	 * Header should have extended IV and sequence number;
202 	 * verify the former and validate the latter.
203 	 */
204 	ivp = mp->b_rptr + hdrlen;
205 	if ((ivp[IEEE80211_WEP_IVLEN] & IEEE80211_WEP_EXTIV) == 0) {
206 		/*
207 		 * No extended IV; discard frame.
208 		 */
209 		return (0);
210 	}
211 	/*
212 	 * Handle TKIP counter measures requirement.
213 	 */
214 	if (ic->ic_flags & IEEE80211_F_COUNTERM)
215 		return (0);
216 
217 	/* NB: assume IEEEE80211_WEP_MINLEN covers the extended IV */
218 	pn = ieee80211_read_6(ivp[2], ivp[0], ivp[4], ivp[5], ivp[6], ivp[7]);
219 	ctx->rx_rsc = pn;
220 	if (ctx->rx_rsc <= k->wk_keyrsc)
221 		return (0);
222 	/*
223 	 * NB: We can't update the rsc in the key until MIC is verified.
224 	 *
225 	 * We assume we are not preempted between doing the check above
226 	 * and updating wk_keyrsc when stripping the MIC in tkip_demic.
227 	 * Otherwise we might process another packet and discard it as
228 	 * a replay.
229 	 */
230 
231 	/*
232 	 * Check if the device handled the decrypt in hardware.
233 	 * If so we just strip the header; otherwise we need to
234 	 * handle the decrypt in software.
235 	 */
236 	if (k->wk_flags & IEEE80211_KEY_SWCRYPT) {
237 		if (!tkip_decrypt(ctx, k, mp, hdrlen))
238 			return (0);
239 	}
240 
241 	/*
242 	 * Copy up 802.11 header and strip crypto bits.
243 	 */
244 	(void) memmove(mp->b_rptr + tkip.ic_header, mp->b_rptr, hdrlen);
245 	mp->b_rptr += tkip.ic_header;
246 	mp->b_wptr -= tkip.ic_trailer;
247 
248 	return (1);
249 }
250 
251 /*
252  * Add MIC to the frame as needed.
253  */
254 static int
255 tkip_enmic(struct ieee80211_key *k, mblk_t *mp, int force)
256 {
257 	struct tkip_ctx *ctx = k->wk_private;
258 
259 	if (force || (k->wk_flags & IEEE80211_KEY_SWMIC)) {
260 		int hdrlen;
261 		uint8_t *mic;
262 
263 		hdrlen = ieee80211_hdrspace(ctx->tc_ic, mp->b_rptr);
264 		mic = mp->b_wptr;
265 		mp->b_wptr += tkip.ic_miclen;
266 
267 		if ((int)(MBLKL(mp) -
268 		    (hdrlen + tkip.ic_header + tkip.ic_miclen)) < 0)
269 			return (0);	/* dead packet */
270 
271 		michael_mic(ctx, k->wk_txmic, mp, (hdrlen + tkip.ic_header),
272 		    MBLKL(mp) -
273 		    (hdrlen + tkip.ic_header + tkip.ic_miclen), mic);
274 	}
275 	return (1);
276 }
277 
278 /*
279  * Verify and strip MIC from the frame.
280  */
281 /* ARGSUSED */
282 static int
283 tkip_demic(struct ieee80211_key *k, mblk_t *mp, int force)
284 {
285 	struct tkip_ctx *ctx = k->wk_private;
286 
287 	if (force || (k->wk_flags & IEEE80211_KEY_SWMIC)) {
288 		int hdrlen = ieee80211_hdrspace(ctx->tc_ic, mp->b_rptr);
289 		uint8_t mic[IEEE80211_WEP_MICLEN];
290 		uint8_t mic0[IEEE80211_WEP_MICLEN];
291 
292 		michael_mic(ctx, k->wk_rxmic,
293 		    mp, hdrlen,
294 		    MBLKL(mp) - (hdrlen + tkip.ic_miclen),
295 		    mic);
296 		bcopy(mp->b_wptr - tkip.ic_miclen, mic0, tkip.ic_miclen);
297 		if (bcmp(mic, mic0, tkip.ic_miclen)) {
298 			ieee80211_dbg(IEEE80211_MSG_CRYPTO,
299 			    "tkip_demic() mic mismatch\n");
300 			return (0);
301 		}
302 	}
303 	/*
304 	 * Strip MIC from the tail.
305 	 */
306 	mp->b_wptr -= tkip.ic_miclen;
307 	/*
308 	 * Ok to update rsc now that MIC has been verified.
309 	 */
310 	k->wk_keyrsc = ctx->rx_rsc;
311 	return (1);
312 }
313 
314 /*
315  * For the avoidance of doubt, except that if any license choice other
316  * than GPL or LGPL is available it will apply instead, Sun elects to
317  * use only the General Public License version 2 (GPLv2) at this time
318  * for any software where a choice of GPL license versions is made
319  * available with the language indicating that GPLv2 or any later
320  * version may be used, or where a choice of which version of the GPL
321  * is applied is otherwise unspecified.
322  */
323 
324 /*
325  * Host AP crypt: host-based TKIP encryption implementation for Host AP driver
326  *
327  * Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi>
328  *
329  * This program is free software; you can redistribute it and/or modify
330  * it under the terms of the GNU General Public License version 2 as
331  * published by the Free Software Foundation. See README and COPYING for
332  * more details.
333  *
334  * Alternatively, this software may be distributed under the terms of BSD
335  * license.
336  */
337 
338 /* Table of CRCs of all 8-bit messages */
339 static uint32_t crc_table[] = { CRC32_TABLE };
340 
341 static uint16_t
342 RotR1(uint16_t val)
343 {
344 	return ((val >> 1) | (val << 15));
345 }
346 
347 static uint8_t
348 Lo8(uint16_t val)
349 {
350 	return (val & 0xff);
351 }
352 
353 static uint8_t
354 Hi8(uint16_t val)
355 {
356 	return (val >> 8);
357 }
358 
359 static uint16_t
360 Lo16(uint32_t val)
361 {
362 	return (val & 0xffff);
363 }
364 
365 static uint16_t
366 Hi16(uint32_t val)
367 {
368 	return (val >> 16);
369 }
370 
371 static uint16_t
372 Mk16(uint8_t hi, uint8_t lo)
373 {
374 	return (lo | (((uint16_t)hi) << 8));
375 }
376 
377 static uint16_t
378 Mk16_le(const uint16_t *v)
379 {
380 	return (LE_16(*v));
381 }
382 
383 static const uint16_t Sbox[256] = {
384 	0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154,
385 	0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A,
386 	0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B,
387 	0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B,
388 	0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F,
389 	0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F,
390 	0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5,
391 	0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F,
392 	0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB,
393 	0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397,
394 	0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED,
395 	0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A,
396 	0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194,
397 	0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3,
398 	0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104,
399 	0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D,
400 	0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39,
401 	0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695,
402 	0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83,
403 	0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76,
404 	0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4,
405 	0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B,
406 	0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0,
407 	0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018,
408 	0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751,
409 	0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85,
410 	0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12,
411 	0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9,
412 	0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7,
413 	0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A,
414 	0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8,
415 	0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A,
416 };
417 
418 static uint16_t
419 _S_(uint16_t v)
420 {
421 	uint16_t t = Sbox[Hi8(v)];
422 	return (Sbox[Lo8(v)] ^ ((t << 8) | (t >> 8)));
423 }
424 
425 #define	PHASE1_LOOP_COUNT	8
426 
427 static void
428 tkip_mixing_phase1(uint16_t *TTAK, const uint8_t *TK,
429     const uint8_t *TA, uint32_t IV32)
430 {
431 	int i, j;
432 
433 	/* Initialize the 80-bit TTAK from TSC (IV32) and TA[0..5] */
434 	TTAK[0] = Lo16(IV32);
435 	TTAK[1] = Hi16(IV32);
436 	TTAK[2] = Mk16(TA[1], TA[0]);
437 	TTAK[3] = Mk16(TA[3], TA[2]);
438 	TTAK[4] = Mk16(TA[5], TA[4]);
439 
440 	for (i = 0; i < PHASE1_LOOP_COUNT; i++) {
441 		j = 2 * (i & 1);
442 		TTAK[0] += _S_(TTAK[4] ^ Mk16(TK[1 + j], TK[0 + j]));
443 		TTAK[1] += _S_(TTAK[0] ^ Mk16(TK[5 + j], TK[4 + j]));
444 		TTAK[2] += _S_(TTAK[1] ^ Mk16(TK[9 + j], TK[8 + j]));
445 		TTAK[3] += _S_(TTAK[2] ^ Mk16(TK[13 + j], TK[12 + j]));
446 		TTAK[4] += _S_(TTAK[3] ^ Mk16(TK[1 + j], TK[0 + j])) + i;
447 	}
448 }
449 
450 static void
451 tkip_mixing_phase2(uint8_t *WEPSeed, const uint8_t *TK,
452     const uint16_t *TTAK, uint16_t IV16)
453 {
454 	/*
455 	 * Make temporary area overlap WEP seed so that the final copy can be
456 	 * avoided on little endian hosts.
457 	 */
458 	uint16_t *PPK = (uint16_t *)&WEPSeed[4];
459 
460 	/* Step 1 - make copy of TTAK and bring in TSC */
461 	PPK[0] = TTAK[0];
462 	PPK[1] = TTAK[1];
463 	PPK[2] = TTAK[2];
464 	PPK[3] = TTAK[3];
465 	PPK[4] = TTAK[4];
466 	PPK[5] = TTAK[4] + IV16;
467 
468 	/* Step 2 - 96-bit bijective mixing using S-box */
469 	PPK[0] += _S_(PPK[5] ^ Mk16_le((const uint16_t *) &TK[0]));
470 	PPK[1] += _S_(PPK[0] ^ Mk16_le((const uint16_t *) &TK[2]));
471 	PPK[2] += _S_(PPK[1] ^ Mk16_le((const uint16_t *) &TK[4]));
472 	PPK[3] += _S_(PPK[2] ^ Mk16_le((const uint16_t *) &TK[6]));
473 	PPK[4] += _S_(PPK[3] ^ Mk16_le((const uint16_t *) &TK[8]));
474 	PPK[5] += _S_(PPK[4] ^ Mk16_le((const uint16_t *) &TK[10]));
475 
476 	PPK[0] += RotR1(PPK[5] ^ Mk16_le((const uint16_t *) &TK[12]));
477 	PPK[1] += RotR1(PPK[0] ^ Mk16_le((const uint16_t *) &TK[14]));
478 	PPK[2] += RotR1(PPK[1]);
479 	PPK[3] += RotR1(PPK[2]);
480 	PPK[4] += RotR1(PPK[3]);
481 	PPK[5] += RotR1(PPK[4]);
482 
483 	/*
484 	 * Step 3 - bring in last of TK bits, assign 24-bit WEP IV value
485 	 * WEPSeed[0..2] is transmitted as WEP IV
486 	 */
487 	WEPSeed[0] = Hi8(IV16);
488 	WEPSeed[1] = (Hi8(IV16) | 0x20) & 0x7F;
489 	WEPSeed[2] = Lo8(IV16);
490 	WEPSeed[3] = Lo8((PPK[5] ^ Mk16_le((const uint16_t *) &TK[0])) >> 1);
491 
492 #ifdef _BIG_ENDIAN
493 	int i;
494 	for (i = 0; i < 6; i++)
495 		PPK[i] = (PPK[i] << 8) | (PPK[i] >> 8);
496 #endif
497 }
498 
499 static int
500 wep_encrypt(uint8_t *key, mblk_t *mp, uint_t off, size_t data_len,
501     uint8_t icv[IEEE80211_WEP_CRCLEN])
502 {
503 	uint8_t crcbuf[IEEE80211_WEP_CRCLEN];
504 	uint32_t crc;
505 	crypto_context_t ctx;
506 	int rv;
507 
508 	ctx = NULL;
509 	rv = rc4_init(&ctx, (const uint8_t *)key, 16);
510 	if (rv != CRYPTO_SUCCESS)
511 		return (0);
512 
513 	/* calculate CRC over unencrypted data */
514 	CRC32(crc, mp->b_rptr + off, data_len, -1U, crc_table);
515 
516 	/* encrypt data */
517 	(void) rc4_crypt(ctx, mp->b_rptr + off, mp->b_rptr + off, data_len);
518 
519 	/* tack on ICV */
520 	*(uint32_t *)crcbuf = LE_32(~crc);
521 	(void) rc4_crypt(ctx, crcbuf, icv, IEEE80211_WEP_CRCLEN);
522 
523 	(void) rc4_final(ctx, icv, IEEE80211_WEP_CRCLEN);
524 
525 	return (1);
526 }
527 
528 static int
529 wep_decrypt(uint8_t *key, mblk_t *mp, uint_t off, size_t data_len)
530 {
531 	uint8_t crcbuf[IEEE80211_WEP_CRCLEN];
532 	uint8_t *icv;
533 	uint32_t crc;
534 	crypto_context_t ctx;
535 	int rv;
536 
537 	ctx = NULL;
538 	rv = rc4_init(&ctx, (const uint8_t *)key, 16);
539 	if (rv != CRYPTO_SUCCESS)
540 		return (0);
541 
542 	/* decrypt data */
543 	(void) rc4_crypt(ctx, mp->b_rptr + off, mp->b_rptr + off, data_len);
544 
545 	/* calculate CRC over unencrypted data */
546 	CRC32(crc, mp->b_rptr + off, data_len, -1U, crc_table);
547 
548 	/* decrypt ICV and compare to CRC */
549 	icv = mp->b_wptr - IEEE80211_WEP_CRCLEN;
550 	(void) rc4_crypt(ctx, icv, crcbuf, IEEE80211_WEP_CRCLEN);
551 	(void) rc4_final(ctx, crcbuf, IEEE80211_WEP_CRCLEN);
552 
553 	return (crc == ~LE_32(*(uint32_t *)crcbuf));
554 }
555 
556 static uint32_t
557 rotl(uint32_t val, int bits)
558 {
559 	return ((val << bits) | (val >> (32 - bits)));
560 }
561 
562 
563 static uint32_t
564 rotr(uint32_t val, int bits)
565 {
566 	return ((val >> bits) | (val << (32 - bits)));
567 }
568 
569 
570 static uint32_t
571 xswap(uint32_t val)
572 {
573 	return (((val & 0x00ff00ff) << 8) | ((val & 0xff00ff00) >> 8));
574 }
575 
576 
577 #define	michael_block(l, r)	\
578 do {				\
579 	r ^= rotl(l, 17);	\
580 	l += r;			\
581 	r ^= xswap(l);		\
582 	l += r;			\
583 	r ^= rotl(l, 3);	\
584 	l += r;			\
585 	r ^= rotr(l, 2);	\
586 	l += r;			\
587 	_NOTE(CONSTANTCONDITION)\
588 } while (0)
589 
590 
591 static uint32_t
592 get_le32_split(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3)
593 {
594 	return (b0 | (b1 << 8) | (b2 << 16) | (b3 << 24));
595 }
596 
597 static uint32_t
598 get_le32(const uint8_t *p)
599 {
600 	return (get_le32_split(p[0], p[1], p[2], p[3]));
601 }
602 
603 
604 static void
605 put_le32(uint8_t *p, uint32_t v)
606 {
607 	p[0] = (uint8_t)v;
608 	p[1] = v >> 8;
609 	p[2] = v >> 16;
610 	p[3] = v >> 24;
611 }
612 
613 /*
614  * Craft pseudo header used to calculate the MIC.
615  */
616 static void
617 michael_mic_hdr(const struct ieee80211_frame *wh0, uint8_t hdr[16])
618 {
619 	const struct ieee80211_frame_addr4 *wh =
620 	    (const struct ieee80211_frame_addr4 *)wh0;
621 
622 	switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) {
623 	case IEEE80211_FC1_DIR_NODS:
624 		IEEE80211_ADDR_COPY(hdr, wh->i_addr1); /* DA */
625 		IEEE80211_ADDR_COPY(hdr + IEEE80211_ADDR_LEN, wh->i_addr2);
626 		break;
627 	case IEEE80211_FC1_DIR_TODS:
628 		IEEE80211_ADDR_COPY(hdr, wh->i_addr3); /* DA */
629 		IEEE80211_ADDR_COPY(hdr + IEEE80211_ADDR_LEN, wh->i_addr2);
630 		break;
631 	case IEEE80211_FC1_DIR_FROMDS:
632 		IEEE80211_ADDR_COPY(hdr, wh->i_addr1); /* DA */
633 		IEEE80211_ADDR_COPY(hdr + IEEE80211_ADDR_LEN, wh->i_addr3);
634 		break;
635 	case IEEE80211_FC1_DIR_DSTODS:
636 		IEEE80211_ADDR_COPY(hdr, wh->i_addr3); /* DA */
637 		IEEE80211_ADDR_COPY(hdr + IEEE80211_ADDR_LEN, wh->i_addr4);
638 		break;
639 	}
640 
641 	if (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_QOS) {
642 		const struct ieee80211_qosframe *qwh =
643 		    (const struct ieee80211_qosframe *)wh;
644 		hdr[12] = qwh->i_qos[0] & IEEE80211_QOS_TID;
645 	} else
646 		hdr[12] = 0;
647 	hdr[13] = hdr[14] = hdr[15] = 0; /* reserved */
648 }
649 
650 /* ARGSUSED */
651 static void
652 michael_mic(struct tkip_ctx *ctx, const uint8_t *key,
653     mblk_t *mp, uint_t off, size_t data_len,
654     uint8_t mic[IEEE80211_WEP_MICLEN])
655 {
656 	uint8_t hdr[16];
657 	uint32_t l, r;
658 	const uint8_t *data;
659 	int i, blocks, last;
660 
661 	michael_mic_hdr((struct ieee80211_frame *)mp->b_rptr, hdr);
662 
663 	l = get_le32(key);
664 	r = get_le32(key + 4);
665 
666 	/* Michael MIC pseudo header: DA, SA, 3 x 0, Priority */
667 	l ^= get_le32(hdr);
668 	michael_block(l, r);
669 	l ^= get_le32(&hdr[4]);
670 	michael_block(l, r);
671 	l ^= get_le32(&hdr[8]);
672 	michael_block(l, r);
673 	l ^= get_le32(&hdr[12]);
674 	michael_block(l, r);
675 
676 	/* first buffer has special handling */
677 	data = mp->b_rptr + off;
678 
679 	blocks = data_len / 4;
680 	last = data_len % 4;
681 
682 	for (i = 0; i < blocks; i++) {
683 		l ^= get_le32(&data[4 * i]);
684 		michael_block(l, r);
685 	}
686 
687 	/* Last block and padding (0x5a, 4..7 x 0) */
688 	switch (last) {
689 	case 0:
690 		l ^= 0x5a;
691 		break;
692 	case 1:
693 		l ^= data[4 * i] | 0x5a00;
694 		break;
695 	case 2:
696 		l ^= data[4 * i] | (data[4 * i + 1] << 8) | 0x5a0000;
697 		break;
698 	case 3:
699 		l ^= data[4 * i] | (data[4 * i + 1] << 8) |
700 		    (data[4 * i + 2] << 16) | 0x5a000000;
701 		break;
702 	}
703 	michael_block(l, r);
704 	/* l ^= 0; */
705 	michael_block(l, r);
706 
707 	put_le32(mic, l);
708 	put_le32(mic + 4, r);
709 }
710 
711 static int
712 tkip_encrypt(struct tkip_ctx *ctx, struct ieee80211_key *key,
713     mblk_t *mp, int hdrlen)
714 {
715 	struct ieee80211_frame *wh;
716 	uint8_t *icv;
717 
718 	wh = (struct ieee80211_frame *)mp->b_rptr;
719 	if (!ctx->tx_phase1_done) {
720 		tkip_mixing_phase1(ctx->tx_ttak, key->wk_key, wh->i_addr2,
721 		    (uint32_t)(key->wk_keytsc >> 16));
722 		ctx->tx_phase1_done = 1;
723 	}
724 	tkip_mixing_phase2(ctx->tx_rc4key, key->wk_key, ctx->tx_ttak,
725 	    (uint16_t)key->wk_keytsc);
726 
727 	icv = mp->b_wptr;
728 	mp->b_wptr += tkip.ic_trailer;
729 
730 	(void) wep_encrypt(ctx->tx_rc4key,
731 	    mp, hdrlen + tkip.ic_header,
732 	    MBLKL(mp) -
733 	    (hdrlen + tkip.ic_header + tkip.ic_trailer),
734 	    icv);
735 
736 	key->wk_keytsc++;
737 	if ((uint16_t)(key->wk_keytsc) == 0)
738 		ctx->tx_phase1_done = 0;
739 	return (1);
740 }
741 
742 static int
743 tkip_decrypt(struct tkip_ctx *ctx, struct ieee80211_key *key,
744     mblk_t *mp, int hdrlen)
745 {
746 	struct ieee80211_frame *wh;
747 	uint32_t iv32;
748 	uint16_t iv16;
749 
750 	wh = (struct ieee80211_frame *)mp->b_rptr;
751 	/* tkip_decap already verified header and left seq in rx_rsc */
752 	iv16 = (uint16_t)ctx->rx_rsc;
753 	iv32 = (uint32_t)(ctx->rx_rsc >> 16);
754 
755 	if (iv32 != (uint32_t)(key->wk_keyrsc >> 16) || !ctx->rx_phase1_done) {
756 		tkip_mixing_phase1(ctx->rx_ttak, key->wk_key,
757 		    wh->i_addr2, iv32);
758 		ctx->rx_phase1_done = 0;	/* DHCP */
759 	}
760 	tkip_mixing_phase2(ctx->rx_rc4key, key->wk_key, ctx->rx_ttak, iv16);
761 
762 	/* m is unstripped; deduct headers + ICV to get payload */
763 	if (!wep_decrypt(ctx->rx_rc4key,
764 	    mp, hdrlen + tkip.ic_header,
765 	    MBLKL(mp) -
766 	    (hdrlen + tkip.ic_header + tkip.ic_trailer))) {
767 		if (iv32 != (uint32_t)(key->wk_keyrsc >> 16)) {
768 			/*
769 			 * Previously cached Phase1 result was already lost, so
770 			 * it needs to be recalculated for the next packet.
771 			 */
772 			ctx->rx_phase1_done = 0;
773 		}
774 		ieee80211_dbg(IEEE80211_MSG_CRYPTO, "tkip_decrypt() error\n");
775 		return (0);
776 	}
777 	return (1);
778 }
779