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