1a399b765Szf /*
2b510adaeSfei feng - Sun Microsystems - Beijing China  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
3a399b765Szf  * Use is subject to license terms.
4a399b765Szf  */
5a399b765Szf 
6a399b765Szf /*
7a399b765Szf  * Copyright (c) 2001 Atsushi Onoe
8e2cf88acSQuaker Fang  * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
9a399b765Szf  * All rights reserved.
10a399b765Szf  *
11a399b765Szf  * Redistribution and use in source and binary forms, with or without
12a399b765Szf  * modification, are permitted provided that the following conditions
13a399b765Szf  * are met:
14a399b765Szf  * 1. Redistributions of source code must retain the above copyright
15a399b765Szf  *    notice, this list of conditions and the following disclaimer.
16a399b765Szf  * 2. Redistributions in binary form must reproduce the above copyright
17a399b765Szf  *    notice, this list of conditions and the following disclaimer in the
18a399b765Szf  *    documentation and/or other materials provided with the distribution.
19a399b765Szf  * 3. The name of the author may not be used to endorse or promote products
20a399b765Szf  *    derived from this software without specific prior written permission.
21a399b765Szf  *
22a399b765Szf  * Alternatively, this software may be distributed under the terms of the
23a399b765Szf  * GNU General Public License ("GPL") version 2 as published by the Free
24a399b765Szf  * Software Foundation.
25a399b765Szf  *
26a399b765Szf  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
27a399b765Szf  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
28a399b765Szf  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
29a399b765Szf  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
30a399b765Szf  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
31a399b765Szf  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32a399b765Szf  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33a399b765Szf  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34a399b765Szf  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
35a399b765Szf  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36a399b765Szf  */
37a399b765Szf 
38a399b765Szf /*
39a399b765Szf  * IEEE 802.11i TKIP crypto support.
403a1a8936Szf  *
413a1a8936Szf  * Part of this module is derived from similar code in the Host
423a1a8936Szf  * AP driver. The code is used with the consent of the author and
433a1a8936Szf  * it's license is included below.
44a399b765Szf  */
453a1a8936Szf 
46a399b765Szf #include <sys/byteorder.h>
47a399b765Szf #include <sys/crypto/common.h>
48a399b765Szf #include <sys/crypto/api.h>
49a399b765Szf #include <sys/crc32.h>
50a399b765Szf #include <sys/random.h>
51ff3124efSff #include <sys/strsun.h>
52a399b765Szf #include "net80211_impl.h"
53a399b765Szf 
54a399b765Szf static void *tkip_attach(struct ieee80211com *, struct ieee80211_key *);
55a399b765Szf static void tkip_detach(struct ieee80211_key *);
56a399b765Szf static int tkip_setkey(struct ieee80211_key *);
57a399b765Szf static int tkip_encap(struct ieee80211_key *, mblk_t *, uint8_t);
58a399b765Szf static int tkip_decap(struct ieee80211_key *, mblk_t *, int);
59a399b765Szf static int tkip_enmic(struct ieee80211_key *, mblk_t *, int);
60a399b765Szf static int tkip_demic(struct ieee80211_key *, mblk_t *, int);
61a399b765Szf 
62a399b765Szf const struct ieee80211_cipher tkip  = {
63a399b765Szf 	"TKIP",
64a399b765Szf 	IEEE80211_CIPHER_TKIP,
65a399b765Szf 	IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN +
66a399b765Szf 	    IEEE80211_WEP_EXTIVLEN,
67a399b765Szf 	IEEE80211_WEP_CRCLEN,
68a399b765Szf 	IEEE80211_WEP_MICLEN,
69a399b765Szf 	tkip_attach,
70a399b765Szf 	tkip_detach,
71a399b765Szf 	tkip_setkey,
72a399b765Szf 	tkip_encap,
73a399b765Szf 	tkip_decap,
74a399b765Szf 	tkip_enmic,
75a399b765Szf 	tkip_demic,
76a399b765Szf };
77a399b765Szf 
78a399b765Szf struct tkip_ctx {
79a399b765Szf 	struct ieee80211com	*tc_ic;		/* for diagnostics */
80a399b765Szf 	uint16_t		tx_ttak[5];
81a399b765Szf 	int			tx_phase1_done;
82a399b765Szf 	uint8_t			tx_rc4key[16];
83a399b765Szf 	uint16_t		rx_ttak[5];
84a399b765Szf 	int			rx_phase1_done;
85a399b765Szf 	uint8_t			rx_rc4key[16];
86a399b765Szf 	uint64_t		rx_rsc;		/* held until MIC verified */
87a399b765Szf };
88a399b765Szf 
893a1a8936Szf static void michael_mic(struct tkip_ctx *, const uint8_t *,
903a1a8936Szf     mblk_t *, uint_t, size_t, uint8_t[]);
913a1a8936Szf static int tkip_encrypt(struct tkip_ctx *, struct ieee80211_key *,
923a1a8936Szf     mblk_t *, int);
933a1a8936Szf static int tkip_decrypt(struct tkip_ctx *, struct ieee80211_key *,
943a1a8936Szf     mblk_t *, int);
953a1a8936Szf 
963a1a8936Szf extern int rc4_init(crypto_context_t *, const uint8_t *, int);
973a1a8936Szf extern int rc4_crypt(crypto_context_t, const uint8_t *, uint8_t *, int);
983a1a8936Szf extern int rc4_final(crypto_context_t, uint8_t *, int);
993a1a8936Szf 
100a399b765Szf /* ARGSUSED */
101a399b765Szf static void *
tkip_attach(struct ieee80211com * ic,struct ieee80211_key * k)102a399b765Szf tkip_attach(struct ieee80211com *ic, struct ieee80211_key *k)
103a399b765Szf {
104a399b765Szf 	struct tkip_ctx *ctx;
105a399b765Szf 
106a399b765Szf 	ctx = kmem_zalloc(sizeof (struct tkip_ctx), KM_SLEEP);
107a399b765Szf 	if (ctx == NULL)
108a399b765Szf 		return (NULL);
109a399b765Szf 
110a399b765Szf 	ctx->tc_ic = ic;
111a399b765Szf 	return (ctx);
112a399b765Szf }
113a399b765Szf 
114a399b765Szf static void
tkip_detach(struct ieee80211_key * k)115a399b765Szf tkip_detach(struct ieee80211_key *k)
116a399b765Szf {
117a399b765Szf 	struct tkip_ctx *ctx = k->wk_private;
118a399b765Szf 
119a399b765Szf 	if (ctx != NULL)
120a399b765Szf 		kmem_free(ctx, sizeof (struct tkip_ctx));
121a399b765Szf }
122a399b765Szf 
123a399b765Szf static int
tkip_setkey(struct ieee80211_key * k)124a399b765Szf tkip_setkey(struct ieee80211_key *k)
125a399b765Szf {
126a399b765Szf 	if (k->wk_keylen != (128/NBBY))
127a399b765Szf 		return (0);
128a399b765Szf 
129a399b765Szf 	k->wk_keytsc = 1;		/* TSC starts at 1 */
130a399b765Szf 	return (1);
131a399b765Szf }
132a399b765Szf 
133a399b765Szf /*
134a399b765Szf  * Add privacy headers appropriate for the specified key.
135a399b765Szf  */
136a399b765Szf static int
tkip_encap(struct ieee80211_key * k,mblk_t * mp,uint8_t keyid)137a399b765Szf tkip_encap(struct ieee80211_key *k, mblk_t *mp, uint8_t keyid)
138a399b765Szf {
139a399b765Szf 	struct tkip_ctx *ctx = k->wk_private;
140a399b765Szf 	struct ieee80211com *ic = ctx->tc_ic;
141a399b765Szf 	uint8_t *ivp;
142a399b765Szf 	int hdrlen;
143a399b765Szf 
144a399b765Szf 	/*
145a399b765Szf 	 * Handle TKIP counter measures requirement.
146a399b765Szf 	 */
147a399b765Szf 	if (ic->ic_flags & IEEE80211_F_COUNTERM)
148a399b765Szf 		return (0);
149a399b765Szf 
150e2cf88acSQuaker Fang 	hdrlen = ieee80211_hdrspace(ic, mp->b_rptr);
151a399b765Szf 	/*
152a399b765Szf 	 * Copy down 802.11 header and add the IV, KeyID, and ExtIV.
153a399b765Szf 	 */
154a399b765Szf 	ivp = mp->b_rptr;
155a399b765Szf 	ivp += hdrlen;
156a399b765Szf 
157a399b765Szf 	ivp[0] = k->wk_keytsc >> 8;		/* TSC1 */
158a399b765Szf 	ivp[1] = (ivp[0] | 0x20) & 0x7f;	/* WEP seed */
159a399b765Szf 	ivp[2] = k->wk_keytsc >> 0;		/* TSC0 */
160a399b765Szf 	ivp[3] = keyid | IEEE80211_WEP_EXTIV;	/* KeyID | ExtID */
161a399b765Szf 	ivp[4] = k->wk_keytsc >> 16;		/* TSC2 */
162a399b765Szf 	ivp[5] = k->wk_keytsc >> 24;		/* TSC3 */
163a399b765Szf 	ivp[6] = k->wk_keytsc >> 32;		/* TSC4 */
164a399b765Szf 	ivp[7] = k->wk_keytsc >> 40;		/* TSC5 */
165a399b765Szf 
166a399b765Szf 	/*
1673a1a8936Szf 	 * Finally, do software encrypt if neeed.
168a399b765Szf 	 */
1693a1a8936Szf 	if (k->wk_flags & IEEE80211_KEY_SWCRYPT) {
1703a1a8936Szf 		if (!tkip_encrypt(ctx, k, mp, hdrlen))
1713a1a8936Szf 			return (0);
1723a1a8936Szf 	} else
173a399b765Szf 		k->wk_keytsc++;		/* wrap at 48 bits */
174a399b765Szf 
175a399b765Szf 	return (1);
176a399b765Szf }
177a399b765Szf 
178a399b765Szf uint64_t
ieee80211_read_6(uint8_t b0,uint8_t b1,uint8_t b2,uint8_t b3,uint8_t b4,uint8_t b5)179a399b765Szf ieee80211_read_6(uint8_t b0, uint8_t b1, uint8_t b2,
180a399b765Szf     uint8_t b3, uint8_t b4, uint8_t b5)
181a399b765Szf {
182a399b765Szf 	uint32_t iv32 = (b0 << 0) | (b1 << 8) | (b2 << 16) | (b3 << 24);
183a399b765Szf 	uint16_t iv16 = (b4 << 0) | (b5 << 8);
184a399b765Szf 	return ((((uint64_t)iv16) << 32) | iv32);
185a399b765Szf }
186a399b765Szf 
187a399b765Szf /*
188a399b765Szf  * Validate and strip privacy headers (and trailer) for a
189a399b765Szf  * received frame.  If necessary, decrypt the frame using
190a399b765Szf  * the specified key.
191a399b765Szf  */
192a399b765Szf static int
tkip_decap(struct ieee80211_key * k,mblk_t * mp,int hdrlen)193a399b765Szf tkip_decap(struct ieee80211_key *k, mblk_t *mp, int hdrlen)
194a399b765Szf {
195a399b765Szf 	struct tkip_ctx *ctx = k->wk_private;
196a399b765Szf 	struct ieee80211com *ic = ctx->tc_ic;
197a399b765Szf 	uint8_t *ivp;
198a399b765Szf 	uint64_t pn;
199a399b765Szf 
200a399b765Szf 	/*
201a399b765Szf 	 * Header should have extended IV and sequence number;
202a399b765Szf 	 * verify the former and validate the latter.
203a399b765Szf 	 */
204a399b765Szf 	ivp = mp->b_rptr + hdrlen;
205a399b765Szf 	if ((ivp[IEEE80211_WEP_IVLEN] & IEEE80211_WEP_EXTIV) == 0) {
206a399b765Szf 		/*
207a399b765Szf 		 * No extended IV; discard frame.
208a399b765Szf 		 */
209a399b765Szf 		return (0);
210a399b765Szf 	}
211a399b765Szf 	/*
212a399b765Szf 	 * Handle TKIP counter measures requirement.
213a399b765Szf 	 */
214a399b765Szf 	if (ic->ic_flags & IEEE80211_F_COUNTERM)
215a399b765Szf 		return (0);
216a399b765Szf 
217a399b765Szf 	/* NB: assume IEEEE80211_WEP_MINLEN covers the extended IV */
218a399b765Szf 	pn = ieee80211_read_6(ivp[2], ivp[0], ivp[4], ivp[5], ivp[6], ivp[7]);
219a399b765Szf 	ctx->rx_rsc = pn;
220a399b765Szf 	if (ctx->rx_rsc <= k->wk_keyrsc)
221a399b765Szf 		return (0);
222a399b765Szf 	/*
223a399b765Szf 	 * NB: We can't update the rsc in the key until MIC is verified.
224a399b765Szf 	 *
225a399b765Szf 	 * We assume we are not preempted between doing the check above
226a399b765Szf 	 * and updating wk_keyrsc when stripping the MIC in tkip_demic.
227a399b765Szf 	 * Otherwise we might process another packet and discard it as
228a399b765Szf 	 * a replay.
229a399b765Szf 	 */
230a399b765Szf 
231a399b765Szf 	/*
2323a1a8936Szf 	 * Check if the device handled the decrypt in hardware.
2333a1a8936Szf 	 * If so we just strip the header; otherwise we need to
2343a1a8936Szf 	 * handle the decrypt in software.
235a399b765Szf 	 */
2363a1a8936Szf 	if (k->wk_flags & IEEE80211_KEY_SWCRYPT) {
2373a1a8936Szf 		if (!tkip_decrypt(ctx, k, mp, hdrlen))
2383a1a8936Szf 			return (0);
2393a1a8936Szf 	}
240a399b765Szf 
241a399b765Szf 	/*
242a399b765Szf 	 * Copy up 802.11 header and strip crypto bits.
243a399b765Szf 	 */
244e2cf88acSQuaker Fang 	(void) memmove(mp->b_rptr + tkip.ic_header, mp->b_rptr, hdrlen);
245a399b765Szf 	mp->b_rptr += tkip.ic_header;
246a399b765Szf 	mp->b_wptr -= tkip.ic_trailer;
247a399b765Szf 
248a399b765Szf 	return (1);
249a399b765Szf }
250a399b765Szf 
251a399b765Szf /*
252a399b765Szf  * Add MIC to the frame as needed.
253a399b765Szf  */
254a399b765Szf static int
tkip_enmic(struct ieee80211_key * k,mblk_t * mp,int force)255a399b765Szf tkip_enmic(struct ieee80211_key *k, mblk_t *mp, int force)
256a399b765Szf {
2573a1a8936Szf 	struct tkip_ctx *ctx = k->wk_private;
2583a1a8936Szf 
2593a1a8936Szf 	if (force || (k->wk_flags & IEEE80211_KEY_SWMIC)) {
2603a1a8936Szf 		int hdrlen;
2613a1a8936Szf 		uint8_t *mic;
2623a1a8936Szf 
263e2cf88acSQuaker Fang 		hdrlen = ieee80211_hdrspace(ctx->tc_ic, mp->b_rptr);
2643a1a8936Szf 		mic = mp->b_wptr;
2653a1a8936Szf 		mp->b_wptr += tkip.ic_miclen;
2663a1a8936Szf 
267ff3124efSff 		if ((int)(MBLKL(mp) -
268ff3124efSff 		    (hdrlen + tkip.ic_header + tkip.ic_miclen)) < 0)
2693a1a8936Szf 			return (0);	/* dead packet */
2703a1a8936Szf 
2713a1a8936Szf 		michael_mic(ctx, k->wk_txmic, mp, (hdrlen + tkip.ic_header),
272ff3124efSff 		    MBLKL(mp) -
273ff3124efSff 		    (hdrlen + tkip.ic_header + tkip.ic_miclen), mic);
2743a1a8936Szf 	}
275a399b765Szf 	return (1);
276a399b765Szf }
277a399b765Szf 
278a399b765Szf /*
279a399b765Szf  * Verify and strip MIC from the frame.
280a399b765Szf  */
281a399b765Szf /* ARGSUSED */
282a399b765Szf static int
tkip_demic(struct ieee80211_key * k,mblk_t * mp,int force)283a399b765Szf tkip_demic(struct ieee80211_key *k, mblk_t *mp, int force)
284a399b765Szf {
285a399b765Szf 	struct tkip_ctx *ctx = k->wk_private;
286a399b765Szf 
2873a1a8936Szf 	if (force || (k->wk_flags & IEEE80211_KEY_SWMIC)) {
288e2cf88acSQuaker Fang 		int hdrlen = ieee80211_hdrspace(ctx->tc_ic, mp->b_rptr);
2893a1a8936Szf 		uint8_t mic[IEEE80211_WEP_MICLEN];
2903a1a8936Szf 		uint8_t mic0[IEEE80211_WEP_MICLEN];
2913a1a8936Szf 
2923a1a8936Szf 		michael_mic(ctx, k->wk_rxmic,
2933a1a8936Szf 		    mp, hdrlen,
294ff3124efSff 		    MBLKL(mp) - (hdrlen + tkip.ic_miclen),
2953a1a8936Szf 		    mic);
2963a1a8936Szf 		bcopy(mp->b_wptr - tkip.ic_miclen, mic0, tkip.ic_miclen);
2973a1a8936Szf 		if (bcmp(mic, mic0, tkip.ic_miclen)) {
2983a1a8936Szf 			ieee80211_dbg(IEEE80211_MSG_CRYPTO,
2993a1a8936Szf 			    "tkip_demic() mic mismatch\n");
3003a1a8936Szf 			return (0);
3013a1a8936Szf 		}
3023a1a8936Szf 	}
303a399b765Szf 	/*
304a399b765Szf 	 * Strip MIC from the tail.
305a399b765Szf 	 */
306a399b765Szf 	mp->b_wptr -= tkip.ic_miclen;
307a399b765Szf 	/*
308a399b765Szf 	 * Ok to update rsc now that MIC has been verified.
309a399b765Szf 	 */
310a399b765Szf 	k->wk_keyrsc = ctx->rx_rsc;
3113a1a8936Szf 	return (1);
3123a1a8936Szf }
3133a1a8936Szf 
3143a1a8936Szf /*
3153a1a8936Szf  * For the avoidance of doubt, except that if any license choice other
3163a1a8936Szf  * than GPL or LGPL is available it will apply instead, Sun elects to
3173a1a8936Szf  * use only the General Public License version 2 (GPLv2) at this time
3183a1a8936Szf  * for any software where a choice of GPL license versions is made
3193a1a8936Szf  * available with the language indicating that GPLv2 or any later
3203a1a8936Szf  * version may be used, or where a choice of which version of the GPL
3213a1a8936Szf  * is applied is otherwise unspecified.
3223a1a8936Szf  */
3233a1a8936Szf 
3243a1a8936Szf /*
3253a1a8936Szf  * Host AP crypt: host-based TKIP encryption implementation for Host AP driver
3263a1a8936Szf  *
3273a1a8936Szf  * Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi>
3283a1a8936Szf  *
3293a1a8936Szf  * This program is free software; you can redistribute it and/or modify
3303a1a8936Szf  * it under the terms of the GNU General Public License version 2 as
3313a1a8936Szf  * published by the Free Software Foundation. See README and COPYING for
3323a1a8936Szf  * more details.
3333a1a8936Szf  *
3343a1a8936Szf  * Alternatively, this software may be distributed under the terms of BSD
3353a1a8936Szf  * license.
3363a1a8936Szf  */
3373a1a8936Szf 
3383a1a8936Szf /* Table of CRCs of all 8-bit messages */
3393a1a8936Szf static uint32_t crc_table[] = { CRC32_TABLE };
3403a1a8936Szf 
3413a1a8936Szf static uint16_t
RotR1(uint16_t val)3423a1a8936Szf RotR1(uint16_t val)
3433a1a8936Szf {
3443a1a8936Szf 	return ((val >> 1) | (val << 15));
3453a1a8936Szf }
3463a1a8936Szf 
3473a1a8936Szf static uint8_t
Lo8(uint16_t val)3483a1a8936Szf Lo8(uint16_t val)
3493a1a8936Szf {
3503a1a8936Szf 	return (val & 0xff);
3513a1a8936Szf }
3523a1a8936Szf 
3533a1a8936Szf static uint8_t
Hi8(uint16_t val)3543a1a8936Szf Hi8(uint16_t val)
3553a1a8936Szf {
3563a1a8936Szf 	return (val >> 8);
3573a1a8936Szf }
3583a1a8936Szf 
3593a1a8936Szf static uint16_t
Lo16(uint32_t val)3603a1a8936Szf Lo16(uint32_t val)
3613a1a8936Szf {
3623a1a8936Szf 	return (val & 0xffff);
3633a1a8936Szf }
3643a1a8936Szf 
3653a1a8936Szf static uint16_t
Hi16(uint32_t val)3663a1a8936Szf Hi16(uint32_t val)
3673a1a8936Szf {
3683a1a8936Szf 	return (val >> 16);
3693a1a8936Szf }
3703a1a8936Szf 
3713a1a8936Szf static uint16_t
Mk16(uint8_t hi,uint8_t lo)3723a1a8936Szf Mk16(uint8_t hi, uint8_t lo)
3733a1a8936Szf {
3743a1a8936Szf 	return (lo | (((uint16_t)hi) << 8));
3753a1a8936Szf }
3763a1a8936Szf 
3773a1a8936Szf static uint16_t
Mk16_le(const uint16_t * v)3783a1a8936Szf Mk16_le(const uint16_t *v)
3793a1a8936Szf {
3803a1a8936Szf 	return (LE_16(*v));
3813a1a8936Szf }
3823a1a8936Szf 
3833a1a8936Szf static const uint16_t Sbox[256] = {
3843a1a8936Szf 	0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154,
3853a1a8936Szf 	0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A,
3863a1a8936Szf 	0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B,
3873a1a8936Szf 	0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B,
3883a1a8936Szf 	0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F,
3893a1a8936Szf 	0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F,
3903a1a8936Szf 	0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5,
3913a1a8936Szf 	0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F,
3923a1a8936Szf 	0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB,
3933a1a8936Szf 	0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397,
3943a1a8936Szf 	0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED,
3953a1a8936Szf 	0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A,
3963a1a8936Szf 	0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194,
3973a1a8936Szf 	0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3,
3983a1a8936Szf 	0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104,
3993a1a8936Szf 	0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D,
4003a1a8936Szf 	0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39,
4013a1a8936Szf 	0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695,
4023a1a8936Szf 	0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83,
4033a1a8936Szf 	0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76,
4043a1a8936Szf 	0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4,
4053a1a8936Szf 	0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B,
4063a1a8936Szf 	0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0,
4073a1a8936Szf 	0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018,
4083a1a8936Szf 	0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751,
4093a1a8936Szf 	0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85,
4103a1a8936Szf 	0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12,
4113a1a8936Szf 	0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9,
4123a1a8936Szf 	0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7,
4133a1a8936Szf 	0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A,
4143a1a8936Szf 	0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8,
4153a1a8936Szf 	0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A,
4163a1a8936Szf };
4173a1a8936Szf 
4183a1a8936Szf static uint16_t
_S_(uint16_t v)4193a1a8936Szf _S_(uint16_t v)
4203a1a8936Szf {
4213a1a8936Szf 	uint16_t t = Sbox[Hi8(v)];
4223a1a8936Szf 	return (Sbox[Lo8(v)] ^ ((t << 8) | (t >> 8)));
4233a1a8936Szf }
4243a1a8936Szf 
4253a1a8936Szf #define	PHASE1_LOOP_COUNT	8
4263a1a8936Szf 
4273a1a8936Szf static void
tkip_mixing_phase1(uint16_t * TTAK,const uint8_t * TK,const uint8_t * TA,uint32_t IV32)4283a1a8936Szf tkip_mixing_phase1(uint16_t *TTAK, const uint8_t *TK,
4293a1a8936Szf     const uint8_t *TA, uint32_t IV32)
4303a1a8936Szf {
4313a1a8936Szf 	int i, j;
4323a1a8936Szf 
4333a1a8936Szf 	/* Initialize the 80-bit TTAK from TSC (IV32) and TA[0..5] */
4343a1a8936Szf 	TTAK[0] = Lo16(IV32);
4353a1a8936Szf 	TTAK[1] = Hi16(IV32);
4363a1a8936Szf 	TTAK[2] = Mk16(TA[1], TA[0]);
4373a1a8936Szf 	TTAK[3] = Mk16(TA[3], TA[2]);
4383a1a8936Szf 	TTAK[4] = Mk16(TA[5], TA[4]);
4393a1a8936Szf 
4403a1a8936Szf 	for (i = 0; i < PHASE1_LOOP_COUNT; i++) {
4413a1a8936Szf 		j = 2 * (i & 1);
4423a1a8936Szf 		TTAK[0] += _S_(TTAK[4] ^ Mk16(TK[1 + j], TK[0 + j]));
4433a1a8936Szf 		TTAK[1] += _S_(TTAK[0] ^ Mk16(TK[5 + j], TK[4 + j]));
4443a1a8936Szf 		TTAK[2] += _S_(TTAK[1] ^ Mk16(TK[9 + j], TK[8 + j]));
4453a1a8936Szf 		TTAK[3] += _S_(TTAK[2] ^ Mk16(TK[13 + j], TK[12 + j]));
4463a1a8936Szf 		TTAK[4] += _S_(TTAK[3] ^ Mk16(TK[1 + j], TK[0 + j])) + i;
4473a1a8936Szf 	}
4483a1a8936Szf }
4493a1a8936Szf 
4503a1a8936Szf static void
tkip_mixing_phase2(uint8_t * WEPSeed,const uint8_t * TK,const uint16_t * TTAK,uint16_t IV16)4513a1a8936Szf tkip_mixing_phase2(uint8_t *WEPSeed, const uint8_t *TK,
4523a1a8936Szf     const uint16_t *TTAK, uint16_t IV16)
4533a1a8936Szf {
4543a1a8936Szf 	/*
4553a1a8936Szf 	 * Make temporary area overlap WEP seed so that the final copy can be
4563a1a8936Szf 	 * avoided on little endian hosts.
4573a1a8936Szf 	 */
4583a1a8936Szf 	uint16_t *PPK = (uint16_t *)&WEPSeed[4];
4593a1a8936Szf 
4603a1a8936Szf 	/* Step 1 - make copy of TTAK and bring in TSC */
4613a1a8936Szf 	PPK[0] = TTAK[0];
4623a1a8936Szf 	PPK[1] = TTAK[1];
4633a1a8936Szf 	PPK[2] = TTAK[2];
4643a1a8936Szf 	PPK[3] = TTAK[3];
4653a1a8936Szf 	PPK[4] = TTAK[4];
4663a1a8936Szf 	PPK[5] = TTAK[4] + IV16;
4673a1a8936Szf 
4683a1a8936Szf 	/* Step 2 - 96-bit bijective mixing using S-box */
4693a1a8936Szf 	PPK[0] += _S_(PPK[5] ^ Mk16_le((const uint16_t *) &TK[0]));
4703a1a8936Szf 	PPK[1] += _S_(PPK[0] ^ Mk16_le((const uint16_t *) &TK[2]));
4713a1a8936Szf 	PPK[2] += _S_(PPK[1] ^ Mk16_le((const uint16_t *) &TK[4]));
4723a1a8936Szf 	PPK[3] += _S_(PPK[2] ^ Mk16_le((const uint16_t *) &TK[6]));
4733a1a8936Szf 	PPK[4] += _S_(PPK[3] ^ Mk16_le((const uint16_t *) &TK[8]));
4743a1a8936Szf 	PPK[5] += _S_(PPK[4] ^ Mk16_le((const uint16_t *) &TK[10]));
4753a1a8936Szf 
4763a1a8936Szf 	PPK[0] += RotR1(PPK[5] ^ Mk16_le((const uint16_t *) &TK[12]));
4773a1a8936Szf 	PPK[1] += RotR1(PPK[0] ^ Mk16_le((const uint16_t *) &TK[14]));
4783a1a8936Szf 	PPK[2] += RotR1(PPK[1]);
4793a1a8936Szf 	PPK[3] += RotR1(PPK[2]);
4803a1a8936Szf 	PPK[4] += RotR1(PPK[3]);
4813a1a8936Szf 	PPK[5] += RotR1(PPK[4]);
4823a1a8936Szf 
4833a1a8936Szf 	/*
4843a1a8936Szf 	 * Step 3 - bring in last of TK bits, assign 24-bit WEP IV value
4853a1a8936Szf 	 * WEPSeed[0..2] is transmitted as WEP IV
4863a1a8936Szf 	 */
4873a1a8936Szf 	WEPSeed[0] = Hi8(IV16);
4883a1a8936Szf 	WEPSeed[1] = (Hi8(IV16) | 0x20) & 0x7F;
4893a1a8936Szf 	WEPSeed[2] = Lo8(IV16);
4903a1a8936Szf 	WEPSeed[3] = Lo8((PPK[5] ^ Mk16_le((const uint16_t *) &TK[0])) >> 1);
491b510adaeSfei feng - Sun Microsystems - Beijing China 
492b510adaeSfei feng - Sun Microsystems - Beijing China #ifdef _BIG_ENDIAN
493b510adaeSfei feng - Sun Microsystems - Beijing China 	int i;
494b510adaeSfei feng - Sun Microsystems - Beijing China 	for (i = 0; i < 6; i++)
495b510adaeSfei feng - Sun Microsystems - Beijing China 		PPK[i] = (PPK[i] << 8) | (PPK[i] >> 8);
496b510adaeSfei feng - Sun Microsystems - Beijing China #endif
4973a1a8936Szf }
4983a1a8936Szf 
4993a1a8936Szf static int
wep_encrypt(uint8_t * key,mblk_t * mp,uint_t off,size_t data_len,uint8_t icv[IEEE80211_WEP_CRCLEN])5003a1a8936Szf wep_encrypt(uint8_t *key, mblk_t *mp, uint_t off, size_t data_len,
5013a1a8936Szf     uint8_t icv[IEEE80211_WEP_CRCLEN])
5023a1a8936Szf {
5033a1a8936Szf 	uint8_t crcbuf[IEEE80211_WEP_CRCLEN];
5043a1a8936Szf 	uint32_t crc;
5053a1a8936Szf 	crypto_context_t ctx;
5063a1a8936Szf 	int rv;
5073a1a8936Szf 
5083a1a8936Szf 	ctx = NULL;
5093a1a8936Szf 	rv = rc4_init(&ctx, (const uint8_t *)key, 16);
5103a1a8936Szf 	if (rv != CRYPTO_SUCCESS)
5113a1a8936Szf 		return (0);
5123a1a8936Szf 
5133a1a8936Szf 	/* calculate CRC over unencrypted data */
5143a1a8936Szf 	CRC32(crc, mp->b_rptr + off, data_len, -1U, crc_table);
5153a1a8936Szf 
5163a1a8936Szf 	/* encrypt data */
5173a1a8936Szf 	(void) rc4_crypt(ctx, mp->b_rptr + off, mp->b_rptr + off, data_len);
5183a1a8936Szf 
5193a1a8936Szf 	/* tack on ICV */
5203a1a8936Szf 	*(uint32_t *)crcbuf = LE_32(~crc);
5213a1a8936Szf 	(void) rc4_crypt(ctx, crcbuf, icv, IEEE80211_WEP_CRCLEN);
5223a1a8936Szf 
5233a1a8936Szf 	(void) rc4_final(ctx, icv, IEEE80211_WEP_CRCLEN);
5243a1a8936Szf 
5253a1a8936Szf 	return (1);
5263a1a8936Szf }
5273a1a8936Szf 
5283a1a8936Szf static int
wep_decrypt(uint8_t * key,mblk_t * mp,uint_t off,size_t data_len)5293a1a8936Szf wep_decrypt(uint8_t *key, mblk_t *mp, uint_t off, size_t data_len)
5303a1a8936Szf {
5313a1a8936Szf 	uint8_t crcbuf[IEEE80211_WEP_CRCLEN];
5323a1a8936Szf 	uint8_t *icv;
5333a1a8936Szf 	uint32_t crc;
5343a1a8936Szf 	crypto_context_t ctx;
5353a1a8936Szf 	int rv;
5363a1a8936Szf 
5373a1a8936Szf 	ctx = NULL;
5383a1a8936Szf 	rv = rc4_init(&ctx, (const uint8_t *)key, 16);
5393a1a8936Szf 	if (rv != CRYPTO_SUCCESS)
5403a1a8936Szf 		return (0);
5413a1a8936Szf 
5423a1a8936Szf 	/* decrypt data */
5433a1a8936Szf 	(void) rc4_crypt(ctx, mp->b_rptr + off, mp->b_rptr + off, data_len);
5443a1a8936Szf 
5453a1a8936Szf 	/* calculate CRC over unencrypted data */
5463a1a8936Szf 	CRC32(crc, mp->b_rptr + off, data_len, -1U, crc_table);
5473a1a8936Szf 
5483a1a8936Szf 	/* decrypt ICV and compare to CRC */
5493a1a8936Szf 	icv = mp->b_wptr - IEEE80211_WEP_CRCLEN;
5503a1a8936Szf 	(void) rc4_crypt(ctx, icv, crcbuf, IEEE80211_WEP_CRCLEN);
5513a1a8936Szf 	(void) rc4_final(ctx, crcbuf, IEEE80211_WEP_CRCLEN);
5523a1a8936Szf 
5533a1a8936Szf 	return (crc == ~LE_32(*(uint32_t *)crcbuf));
5543a1a8936Szf }
5553a1a8936Szf 
5563a1a8936Szf static uint32_t
rotl(uint32_t val,int bits)5573a1a8936Szf rotl(uint32_t val, int bits)
5583a1a8936Szf {
5593a1a8936Szf 	return ((val << bits) | (val >> (32 - bits)));
5603a1a8936Szf }
5613a1a8936Szf 
5623a1a8936Szf 
5633a1a8936Szf static uint32_t
rotr(uint32_t val,int bits)5643a1a8936Szf rotr(uint32_t val, int bits)
5653a1a8936Szf {
5663a1a8936Szf 	return ((val >> bits) | (val << (32 - bits)));
5673a1a8936Szf }
5683a1a8936Szf 
5693a1a8936Szf 
5703a1a8936Szf static uint32_t
xswap(uint32_t val)5713a1a8936Szf xswap(uint32_t val)
5723a1a8936Szf {
5733a1a8936Szf 	return (((val & 0x00ff00ff) << 8) | ((val & 0xff00ff00) >> 8));
5743a1a8936Szf }
5753a1a8936Szf 
5763a1a8936Szf 
5773a1a8936Szf #define	michael_block(l, r)	\
5783a1a8936Szf do {				\
5793a1a8936Szf 	r ^= rotl(l, 17);	\
5803a1a8936Szf 	l += r;			\
5813a1a8936Szf 	r ^= xswap(l);		\
5823a1a8936Szf 	l += r;			\
5833a1a8936Szf 	r ^= rotl(l, 3);	\
5843a1a8936Szf 	l += r;			\
5853a1a8936Szf 	r ^= rotr(l, 2);	\
5863a1a8936Szf 	l += r;			\
5873a1a8936Szf 	_NOTE(CONSTANTCONDITION)\
5883a1a8936Szf } while (0)
5893a1a8936Szf 
5903a1a8936Szf 
5913a1a8936Szf static uint32_t
get_le32_split(uint8_t b0,uint8_t b1,uint8_t b2,uint8_t b3)5923a1a8936Szf get_le32_split(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3)
5933a1a8936Szf {
5943a1a8936Szf 	return (b0 | (b1 << 8) | (b2 << 16) | (b3 << 24));
5953a1a8936Szf }
5963a1a8936Szf 
5973a1a8936Szf static uint32_t
get_le32(const uint8_t * p)5983a1a8936Szf get_le32(const uint8_t *p)
5993a1a8936Szf {
6003a1a8936Szf 	return (get_le32_split(p[0], p[1], p[2], p[3]));
6013a1a8936Szf }
6023a1a8936Szf 
6033a1a8936Szf 
6043a1a8936Szf static void
put_le32(uint8_t * p,uint32_t v)6053a1a8936Szf put_le32(uint8_t *p, uint32_t v)
6063a1a8936Szf {
6073a1a8936Szf 	p[0] = (uint8_t)v;
6083a1a8936Szf 	p[1] = v >> 8;
6093a1a8936Szf 	p[2] = v >> 16;
6103a1a8936Szf 	p[3] = v >> 24;
6113a1a8936Szf }
612a399b765Szf 
6133a1a8936Szf /*
6143a1a8936Szf  * Craft pseudo header used to calculate the MIC.
6153a1a8936Szf  */
6163a1a8936Szf static void
michael_mic_hdr(const struct ieee80211_frame * wh0,uint8_t hdr[16])6173a1a8936Szf michael_mic_hdr(const struct ieee80211_frame *wh0, uint8_t hdr[16])
6183a1a8936Szf {
6193a1a8936Szf 	const struct ieee80211_frame_addr4 *wh =
6203a1a8936Szf 	    (const struct ieee80211_frame_addr4 *)wh0;
6213a1a8936Szf 
6223a1a8936Szf 	switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) {
6233a1a8936Szf 	case IEEE80211_FC1_DIR_NODS:
6243a1a8936Szf 		IEEE80211_ADDR_COPY(hdr, wh->i_addr1); /* DA */
6253a1a8936Szf 		IEEE80211_ADDR_COPY(hdr + IEEE80211_ADDR_LEN, wh->i_addr2);
6263a1a8936Szf 		break;
6273a1a8936Szf 	case IEEE80211_FC1_DIR_TODS:
6283a1a8936Szf 		IEEE80211_ADDR_COPY(hdr, wh->i_addr3); /* DA */
6293a1a8936Szf 		IEEE80211_ADDR_COPY(hdr + IEEE80211_ADDR_LEN, wh->i_addr2);
6303a1a8936Szf 		break;
6313a1a8936Szf 	case IEEE80211_FC1_DIR_FROMDS:
6323a1a8936Szf 		IEEE80211_ADDR_COPY(hdr, wh->i_addr1); /* DA */
6333a1a8936Szf 		IEEE80211_ADDR_COPY(hdr + IEEE80211_ADDR_LEN, wh->i_addr3);
6343a1a8936Szf 		break;
6353a1a8936Szf 	case IEEE80211_FC1_DIR_DSTODS:
6363a1a8936Szf 		IEEE80211_ADDR_COPY(hdr, wh->i_addr3); /* DA */
6373a1a8936Szf 		IEEE80211_ADDR_COPY(hdr + IEEE80211_ADDR_LEN, wh->i_addr4);
6383a1a8936Szf 		break;
6393a1a8936Szf 	}
6403a1a8936Szf 
641e2cf88acSQuaker Fang 	if (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_QOS) {
642e2cf88acSQuaker Fang 		const struct ieee80211_qosframe *qwh =
643e2cf88acSQuaker Fang 		    (const struct ieee80211_qosframe *)wh;
644e2cf88acSQuaker Fang 		hdr[12] = qwh->i_qos[0] & IEEE80211_QOS_TID;
645e2cf88acSQuaker Fang 	} else
646e2cf88acSQuaker Fang 		hdr[12] = 0;
6473a1a8936Szf 	hdr[13] = hdr[14] = hdr[15] = 0; /* reserved */
6483a1a8936Szf }
6493a1a8936Szf 
6503a1a8936Szf /* ARGSUSED */
6513a1a8936Szf static void
michael_mic(struct tkip_ctx * ctx,const uint8_t * key,mblk_t * mp,uint_t off,size_t data_len,uint8_t mic[])6523a1a8936Szf michael_mic(struct tkip_ctx *ctx, const uint8_t *key,
6533a1a8936Szf     mblk_t *mp, uint_t off, size_t data_len,
654*f4203ebbSToomas Soome     uint8_t mic[])
6553a1a8936Szf {
6563a1a8936Szf 	uint8_t hdr[16];
6573a1a8936Szf 	uint32_t l, r;
6583a1a8936Szf 	const uint8_t *data;
6593a1a8936Szf 	int i, blocks, last;
6603a1a8936Szf 
6613a1a8936Szf 	michael_mic_hdr((struct ieee80211_frame *)mp->b_rptr, hdr);
6623a1a8936Szf 
6633a1a8936Szf 	l = get_le32(key);
6643a1a8936Szf 	r = get_le32(key + 4);
6653a1a8936Szf 
6663a1a8936Szf 	/* Michael MIC pseudo header: DA, SA, 3 x 0, Priority */
6673a1a8936Szf 	l ^= get_le32(hdr);
6683a1a8936Szf 	michael_block(l, r);
6693a1a8936Szf 	l ^= get_le32(&hdr[4]);
6703a1a8936Szf 	michael_block(l, r);
6713a1a8936Szf 	l ^= get_le32(&hdr[8]);
6723a1a8936Szf 	michael_block(l, r);
6733a1a8936Szf 	l ^= get_le32(&hdr[12]);
6743a1a8936Szf 	michael_block(l, r);
6753a1a8936Szf 
6763a1a8936Szf 	/* first buffer has special handling */
6773a1a8936Szf 	data = mp->b_rptr + off;
6783a1a8936Szf 
6793a1a8936Szf 	blocks = data_len / 4;
6803a1a8936Szf 	last = data_len % 4;
6813a1a8936Szf 
6823a1a8936Szf 	for (i = 0; i < blocks; i++) {
6833a1a8936Szf 		l ^= get_le32(&data[4 * i]);
6843a1a8936Szf 		michael_block(l, r);
6853a1a8936Szf 	}
6863a1a8936Szf 
6873a1a8936Szf 	/* Last block and padding (0x5a, 4..7 x 0) */
6883a1a8936Szf 	switch (last) {
6893a1a8936Szf 	case 0:
6903a1a8936Szf 		l ^= 0x5a;
6913a1a8936Szf 		break;
6923a1a8936Szf 	case 1:
6933a1a8936Szf 		l ^= data[4 * i] | 0x5a00;
6943a1a8936Szf 		break;
6953a1a8936Szf 	case 2:
6963a1a8936Szf 		l ^= data[4 * i] | (data[4 * i + 1] << 8) | 0x5a0000;
6973a1a8936Szf 		break;
6983a1a8936Szf 	case 3:
6993a1a8936Szf 		l ^= data[4 * i] | (data[4 * i + 1] << 8) |
7003a1a8936Szf 		    (data[4 * i + 2] << 16) | 0x5a000000;
7013a1a8936Szf 		break;
7023a1a8936Szf 	}
7033a1a8936Szf 	michael_block(l, r);
7043a1a8936Szf 	/* l ^= 0; */
7053a1a8936Szf 	michael_block(l, r);
7063a1a8936Szf 
7073a1a8936Szf 	put_le32(mic, l);
7083a1a8936Szf 	put_le32(mic + 4, r);
7093a1a8936Szf }
7103a1a8936Szf 
7113a1a8936Szf static int
tkip_encrypt(struct tkip_ctx * ctx,struct ieee80211_key * key,mblk_t * mp,int hdrlen)7123a1a8936Szf tkip_encrypt(struct tkip_ctx *ctx, struct ieee80211_key *key,
7133a1a8936Szf     mblk_t *mp, int hdrlen)
7143a1a8936Szf {
7153a1a8936Szf 	struct ieee80211_frame *wh;
7163a1a8936Szf 	uint8_t *icv;
7173a1a8936Szf 
7183a1a8936Szf 	wh = (struct ieee80211_frame *)mp->b_rptr;
7193a1a8936Szf 	if (!ctx->tx_phase1_done) {
7203a1a8936Szf 		tkip_mixing_phase1(ctx->tx_ttak, key->wk_key, wh->i_addr2,
7213a1a8936Szf 		    (uint32_t)(key->wk_keytsc >> 16));
7223a1a8936Szf 		ctx->tx_phase1_done = 1;
7233a1a8936Szf 	}
7243a1a8936Szf 	tkip_mixing_phase2(ctx->tx_rc4key, key->wk_key, ctx->tx_ttak,
7253a1a8936Szf 	    (uint16_t)key->wk_keytsc);
7263a1a8936Szf 
7273a1a8936Szf 	icv = mp->b_wptr;
7283a1a8936Szf 	mp->b_wptr += tkip.ic_trailer;
7293a1a8936Szf 
7303a1a8936Szf 	(void) wep_encrypt(ctx->tx_rc4key,
7313a1a8936Szf 	    mp, hdrlen + tkip.ic_header,
732ff3124efSff 	    MBLKL(mp) -
733ff3124efSff 	    (hdrlen + tkip.ic_header + tkip.ic_trailer),
7343a1a8936Szf 	    icv);
7353a1a8936Szf 
7363a1a8936Szf 	key->wk_keytsc++;
7373a1a8936Szf 	if ((uint16_t)(key->wk_keytsc) == 0)
7383a1a8936Szf 		ctx->tx_phase1_done = 0;
7393a1a8936Szf 	return (1);
7403a1a8936Szf }
7413a1a8936Szf 
7423a1a8936Szf static int
tkip_decrypt(struct tkip_ctx * ctx,struct ieee80211_key * key,mblk_t * mp,int hdrlen)7433a1a8936Szf tkip_decrypt(struct tkip_ctx *ctx, struct ieee80211_key *key,
7443a1a8936Szf     mblk_t *mp, int hdrlen)
7453a1a8936Szf {
7463a1a8936Szf 	struct ieee80211_frame *wh;
7473a1a8936Szf 	uint32_t iv32;
7483a1a8936Szf 	uint16_t iv16;
7493a1a8936Szf 
7503a1a8936Szf 	wh = (struct ieee80211_frame *)mp->b_rptr;
7513a1a8936Szf 	/* tkip_decap already verified header and left seq in rx_rsc */
7523a1a8936Szf 	iv16 = (uint16_t)ctx->rx_rsc;
7533a1a8936Szf 	iv32 = (uint32_t)(ctx->rx_rsc >> 16);
7543a1a8936Szf 
7553a1a8936Szf 	if (iv32 != (uint32_t)(key->wk_keyrsc >> 16) || !ctx->rx_phase1_done) {
7563a1a8936Szf 		tkip_mixing_phase1(ctx->rx_ttak, key->wk_key,
7573a1a8936Szf 		    wh->i_addr2, iv32);
7583a1a8936Szf 		ctx->rx_phase1_done = 0;	/* DHCP */
7593a1a8936Szf 	}
7603a1a8936Szf 	tkip_mixing_phase2(ctx->rx_rc4key, key->wk_key, ctx->rx_ttak, iv16);
7613a1a8936Szf 
7623a1a8936Szf 	/* m is unstripped; deduct headers + ICV to get payload */
7633a1a8936Szf 	if (!wep_decrypt(ctx->rx_rc4key,
7643a1a8936Szf 	    mp, hdrlen + tkip.ic_header,
765ff3124efSff 	    MBLKL(mp) -
766ff3124efSff 	    (hdrlen + tkip.ic_header + tkip.ic_trailer))) {
7673a1a8936Szf 		if (iv32 != (uint32_t)(key->wk_keyrsc >> 16)) {
7683a1a8936Szf 			/*
7693a1a8936Szf 			 * Previously cached Phase1 result was already lost, so
7703a1a8936Szf 			 * it needs to be recalculated for the next packet.
7713a1a8936Szf 			 */
7723a1a8936Szf 			ctx->rx_phase1_done = 0;
7733a1a8936Szf 		}
7743a1a8936Szf 		ieee80211_dbg(IEEE80211_MSG_CRYPTO, "tkip_decrypt() error\n");
7753a1a8936Szf 		return (0);
7763a1a8936Szf 	}
777a399b765Szf 	return (1);
778a399b765Szf }
779