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