ieee80211_crypto_tkip.c revision 182437
113675Sdyson/*-
213675Sdyson * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
313675Sdyson * All rights reserved.
413675Sdyson *
513675Sdyson * Redistribution and use in source and binary forms, with or without
613675Sdyson * modification, are permitted provided that the following conditions
713675Sdyson * are met:
813675Sdyson * 1. Redistributions of source code must retain the above copyright
913675Sdyson *    notice, this list of conditions and the following disclaimer.
1013675Sdyson * 2. Redistributions in binary form must reproduce the above copyright
1113675Sdyson *    notice, this list of conditions and the following disclaimer in the
1213675Sdyson *    documentation and/or other materials provided with the distribution.
1313675Sdyson *
1413675Sdyson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1513675Sdyson * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1614037Sdyson * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1713675Sdyson * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
1813675Sdyson * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
1950477Speter * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2013675Sdyson * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2113675Sdyson * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2213675Sdyson * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2313675Sdyson * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2413675Sdyson */
2513675Sdyson
2613675Sdyson#include <sys/cdefs.h>
2713675Sdyson__FBSDID("$FreeBSD: head/sys/net80211/ieee80211_crypto_tkip.c 182437 2008-08-29 08:44:51Z avatar $");
2813675Sdyson
2913907Sdyson/*
3013907Sdyson * IEEE 802.11i TKIP crypto support.
3113907Sdyson *
3213907Sdyson * Part of this module is derived from similar code in the Host
3313907Sdyson * AP driver. The code is used with the consent of the author and
3413907Sdyson * it's license is included below.
3513907Sdyson */
3613907Sdyson#include "opt_wlan.h"
3713907Sdyson
3813907Sdyson#include <sys/param.h>
3913913Sdyson#include <sys/systm.h>
4013907Sdyson#include <sys/mbuf.h>
4113907Sdyson#include <sys/malloc.h>
4213907Sdyson#include <sys/kernel.h>
4313907Sdyson#include <sys/module.h>
4413907Sdyson#include <sys/endian.h>
4513907Sdyson
4613907Sdyson#include <sys/socket.h>
4713907Sdyson
4813913Sdyson#include <net/if.h>
4913907Sdyson#include <net/if_media.h>
5013907Sdyson#include <net/ethernet.h>
5113907Sdyson
5213675Sdyson#include <net80211/ieee80211_var.h>
5313675Sdyson
5424131Sbdestatic	void *tkip_attach(struct ieee80211vap *, struct ieee80211_key *);
5513675Sdysonstatic	void tkip_detach(struct ieee80211_key *);
5613675Sdysonstatic	int tkip_setkey(struct ieee80211_key *);
5724206Sbdestatic	int tkip_encap(struct ieee80211_key *, struct mbuf *m, uint8_t keyid);
5891372Salfredstatic	int tkip_enmic(struct ieee80211_key *, struct mbuf *, int);
5976166Smarkmstatic	int tkip_decap(struct ieee80211_key *, struct mbuf *, int);
6076827Salfredstatic	int tkip_demic(struct ieee80211_key *, struct mbuf *, int);
6124206Sbde
6213675Sdysonstatic const struct ieee80211_cipher tkip  = {
6391968Salfred	.ic_name	= "TKIP",
6429356Speter	.ic_cipher	= IEEE80211_CIPHER_TKIP,
6570834Swollman	.ic_header	= IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN +
6613675Sdyson			  IEEE80211_WEP_EXTIVLEN,
6713675Sdyson	.ic_trailer	= IEEE80211_WEP_CRCLEN,
6813675Sdyson	.ic_miclen	= IEEE80211_WEP_MICLEN,
6976166Smarkm	.ic_attach	= tkip_attach,
7055112Sbde	.ic_detach	= tkip_detach,
7134924Sbde	.ic_setkey	= tkip_setkey,
7259288Sjlemon	.ic_encap	= tkip_encap,
7313675Sdyson	.ic_decap	= tkip_decap,
7413675Sdyson	.ic_enmic	= tkip_enmic,
7513675Sdyson	.ic_demic	= tkip_demic,
7613675Sdyson};
7713675Sdyson
7813675Sdysontypedef	uint8_t u8;
7913675Sdysontypedef	uint16_t u16;
8013675Sdysontypedef	uint32_t __u32;
8113907Sdysontypedef	uint32_t u32;
8227899Sdyson
8313675Sdysonstruct tkip_ctx {
8414037Sdyson	struct ieee80211vap *tc_vap;	/* for diagnostics+statistics */
8514037Sdyson
8614037Sdyson	u16	tx_ttak[5];
8714037Sdyson	int	tx_phase1_done;
8814037Sdyson	u8	tx_rc4key[16];		/* XXX for test module; make locals? */
8914037Sdyson
9014037Sdyson	u16	rx_ttak[5];
9114037Sdyson	int	rx_phase1_done;
9214037Sdyson	u8	rx_rc4key[16];		/* XXX for test module; make locals? */
9314037Sdyson	uint64_t rx_rsc;		/* held until MIC verified */
9491413Salfred};
9591413Salfred
9691413Salfredstatic	void michael_mic(struct tkip_ctx *, const u8 *key,
9791413Salfred		struct mbuf *m, u_int off, size_t data_len,
9891413Salfred		u8 mic[IEEE80211_WEP_MICLEN]);
9991413Salfredstatic	int tkip_encrypt(struct tkip_ctx *, struct ieee80211_key *,
10091413Salfred		struct mbuf *, int hdr_len);
10191413Salfredstatic	int tkip_decrypt(struct tkip_ctx *, struct ieee80211_key *,
10291413Salfred		struct mbuf *, int hdr_len);
10391413Salfred
10413675Sdyson/* number of references from net80211 layer */
10572521Sjlemonstatic	int nrefs = 0;
10672521Sjlemon
10772521Sjlemonstatic void *
10872521Sjlemontkip_attach(struct ieee80211vap *vap, struct ieee80211_key *k)
10913675Sdyson{
11059288Sjlemon	struct tkip_ctx *ctx;
11159288Sjlemon
11259288Sjlemon	MALLOC(ctx, struct tkip_ctx *, sizeof(struct tkip_ctx),
11359288Sjlemon		M_80211_CRYPTO, M_NOWAIT | M_ZERO);
11472521Sjlemon	if (ctx == NULL) {
11572521Sjlemon		vap->iv_stats.is_crypto_nomem++;
11672521Sjlemon		return NULL;
11772521Sjlemon	}
11859288Sjlemon
11992305Salfred	ctx->tc_vap = vap;
12091362Salfred	nrefs++;			/* NB: we assume caller locking */
12192305Salfred	return ctx;
12292305Salfred}
12392305Salfred
12492305Salfredstatic void
12591362Salfredtkip_detach(struct ieee80211_key *k)
12691362Salfred{
12772521Sjlemon	struct tkip_ctx *ctx = k->wk_private;
12891362Salfred
12991362Salfred	FREE(ctx, M_80211_CRYPTO);
13091362Salfred	KASSERT(nrefs > 0, ("imbalanced attach/detach"));
13192305Salfred	nrefs--;			/* NB: we assume caller locking */
13291362Salfred}
13391362Salfred
13413675Sdysonstatic int
13513675Sdysontkip_setkey(struct ieee80211_key *k)
13613675Sdyson{
13713675Sdyson	struct tkip_ctx *ctx = k->wk_private;
13813675Sdyson
13913675Sdyson	if (k->wk_keylen != (128/NBBY)) {
14013907Sdyson		(void) ctx;		/* XXX */
14113907Sdyson		IEEE80211_DPRINTF(ctx->tc_vap, IEEE80211_MSG_CRYPTO,
14213675Sdyson			"%s: Invalid key length %u, expecting %u\n",
14313907Sdyson			__func__, k->wk_keylen, 128/NBBY);
14413907Sdyson		return 0;
14513907Sdyson	}
14613907Sdyson	k->wk_keytsc = 1;		/* TSC starts at 1 */
14713907Sdyson	return 1;
14813907Sdyson}
14913907Sdyson
15013907Sdyson/*
15113907Sdyson * Add privacy headers and do any s/w encryption required.
15213907Sdyson */
15313907Sdysonstatic int
15417163Sdysontkip_encap(struct ieee80211_key *k, struct mbuf *m, uint8_t keyid)
15517163Sdyson{
15617163Sdyson	struct tkip_ctx *ctx = k->wk_private;
15717163Sdyson	struct ieee80211vap *vap = ctx->tc_vap;
15817163Sdyson	struct ieee80211com *ic = vap->iv_ic;
15933181Seivind	uint8_t *ivp;
16017163Sdyson	int hdrlen;
16117124Sbde
16213907Sdyson	/*
16391413Salfred	 * Handle TKIP counter measures requirement.
16491413Salfred	 */
16591413Salfred	if (vap->iv_flags & IEEE80211_F_COUNTERM) {
16691413Salfred#ifdef IEEE80211_DEBUG
16791413Salfred		struct ieee80211_frame *wh = mtod(m, struct ieee80211_frame *);
16891413Salfred#endif
16991413Salfred
17014037Sdyson		IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO, wh->i_addr2,
17191413Salfred		    "discard frame due to countermeasures (%s)", __func__);
17291413Salfred		vap->iv_stats.is_crypto_tkipcm++;
17391413Salfred		return 0;
17491413Salfred	}
17514037Sdyson	hdrlen = ieee80211_hdrspace(ic, mtod(m, void *));
17691413Salfred
17713675Sdyson	/*
17833181Seivind	 * Copy down 802.11 header and add the IV, KeyID, and ExtIV.
17927899Sdyson	 */
18091372Salfred	M_PREPEND(m, tkip.ic_header, M_NOWAIT);
18191372Salfred	if (m == NULL)
18291372Salfred		return 0;
18391372Salfred	ivp = mtod(m, uint8_t *);
18491372Salfred	memmove(ivp, ivp + tkip.ic_header, hdrlen);
18592654Sjeff	ivp += hdrlen;
18692654Sjeff
18791372Salfred	ivp[0] = k->wk_keytsc >> 8;		/* TSC1 */
18891372Salfred	ivp[1] = (ivp[0] | 0x20) & 0x7f;	/* WEP seed */
18913675Sdyson	ivp[2] = k->wk_keytsc >> 0;		/* TSC0 */
19013675Sdyson	ivp[3] = keyid | IEEE80211_WEP_EXTIV;	/* KeyID | ExtID */
19113675Sdyson	ivp[4] = k->wk_keytsc >> 16;		/* TSC2 */
19213675Sdyson	ivp[5] = k->wk_keytsc >> 24;		/* TSC3 */
19313675Sdyson	ivp[6] = k->wk_keytsc >> 32;		/* TSC4 */
19413675Sdyson	ivp[7] = k->wk_keytsc >> 40;		/* TSC5 */
19583366Sjulian
19683366Sjulian	/*
19713675Sdyson	 * Finally, do software encrypt if neeed.
19813675Sdyson	 */
19913675Sdyson	if (k->wk_flags & IEEE80211_KEY_SWENCRYPT) {
20013675Sdyson		if (!tkip_encrypt(ctx, k, m, hdrlen))
20183366Sjulian			return 0;
20213675Sdyson		/* NB: tkip_encrypt handles wk_keytsc */
20313675Sdyson	} else
20491968Salfred		k->wk_keytsc++;
20513675Sdyson
20691362Salfred	return 1;
20791372Salfred}
20827899Sdyson
20991968Salfred/*
21091968Salfred * Add MIC to the frame as needed.
21176756Salfred */
21276364Salfredstatic int
21376364Salfredtkip_enmic(struct ieee80211_key *k, struct mbuf *m, int force)
21476364Salfred{
21591968Salfred	struct tkip_ctx *ctx = k->wk_private;
21676364Salfred
21776364Salfred	if (force || (k->wk_flags & IEEE80211_KEY_SWENMIC)) {
21876364Salfred		struct ieee80211_frame *wh = mtod(m, struct ieee80211_frame *);
21913907Sdyson		struct ieee80211vap *vap = ctx->tc_vap;
22013907Sdyson		struct ieee80211com *ic = vap->iv_ic;
22113675Sdyson		int hdrlen;
22283366Sjulian		uint8_t mic[IEEE80211_WEP_MICLEN];
22370915Sdwmalone
22470915Sdwmalone		vap->iv_stats.is_crypto_tkipenmic++;
22570915Sdwmalone
22691968Salfred		hdrlen = ieee80211_hdrspace(ic, wh);
22770915Sdwmalone
22870915Sdwmalone		michael_mic(ctx, k->wk_txmic,
22970915Sdwmalone			m, hdrlen, m->m_pkthdr.len - hdrlen, mic);
23083366Sjulian		return m_append(m, tkip.ic_miclen, mic);
23170915Sdwmalone	}
23270803Sdwmalone	return 1;
23370803Sdwmalone}
23470803Sdwmalone
23570803Sdwmalonestatic __inline uint64_t
23670803SdwmaloneREAD_6(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5)
23770803Sdwmalone{
23889306Salfred	uint32_t iv32 = (b0 << 0) | (b1 << 8) | (b2 << 16) | (b3 << 24);
23913675Sdyson	uint16_t iv16 = (b4 << 0) | (b5 << 8);
24013675Sdyson	return (((uint64_t)iv16) << 32) | iv32;
24149413Sgreen}
24213675Sdyson
24389306Salfred/*
24483366Sjulian * Validate and strip privacy headers (and trailer) for a
24570915Sdwmalone * received frame.  If necessary, decrypt the frame using
24689306Salfred * the specified key.
24783366Sjulian */
24883366Sjulianstatic int
24989306Salfredtkip_decap(struct ieee80211_key *k, struct mbuf *m, int hdrlen)
25083366Sjulian{
25189306Salfred	struct tkip_ctx *ctx = k->wk_private;
25289306Salfred	struct ieee80211vap *vap = ctx->tc_vap;
25383366Sjulian	struct ieee80211_frame *wh;
25470915Sdwmalone	uint8_t *ivp, tid;
25570915Sdwmalone
25691968Salfred	/*
25770915Sdwmalone	 * Header should have extended IV and sequence number;
25870915Sdwmalone	 * verify the former and validate the latter.
25989306Salfred	 */
26013675Sdyson	wh = mtod(m, struct ieee80211_frame *);
26113675Sdyson	ivp = mtod(m, uint8_t *) + hdrlen;
26249413Sgreen	if ((ivp[IEEE80211_WEP_IVLEN] & IEEE80211_WEP_EXTIV) == 0) {
26313675Sdyson		/*
26489306Salfred		 * No extended IV; discard frame.
26583366Sjulian		 */
26613675Sdyson		IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO, wh->i_addr2,
26713675Sdyson		    "%s", "missing ExtIV for TKIP cipher");
26891968Salfred		vap->iv_stats.is_rx_tkipformat++;
26991968Salfred		return 0;
27083366Sjulian	}
27113675Sdyson	/*
27213675Sdyson	 * Handle TKIP counter measures requirement.
27313675Sdyson	 */
27413675Sdyson	if (vap->iv_flags & IEEE80211_F_COUNTERM) {
27513909Sdyson		IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO, wh->i_addr2,
27613909Sdyson		    "discard frame due to countermeasures (%s)", __func__);
27776364Salfred		vap->iv_stats.is_crypto_tkipcm++;
27876364Salfred		return 0;
27976364Salfred	}
28013909Sdyson
28176364Salfred	tid = ieee80211_gettid(wh);
28276364Salfred	ctx->rx_rsc = READ_6(ivp[2], ivp[0], ivp[4], ivp[5], ivp[6], ivp[7]);
28313675Sdyson	if (ctx->rx_rsc <= k->wk_keyrsc[tid]) {
28476364Salfred		/*
28513675Sdyson		 * Replay violation; notify upper layer.
28676364Salfred		 */
28776364Salfred		ieee80211_notify_replay_failure(vap, wh, k, ctx->rx_rsc);
28813688Sdyson		vap->iv_stats.is_rx_tkipreplay++;
28913675Sdyson		return 0;
29079224Sdillon	}
29191412Salfred	/*
29291412Salfred	 * NB: We can't update the rsc in the key until MIC is verified.
29379224Sdillon	 *
29476364Salfred	 * We assume we are not preempted between doing the check above
29513675Sdyson	 * and updating wk_keyrsc when stripping the MIC in tkip_demic.
29613675Sdyson	 * Otherwise we might process another packet and discard it as
29713675Sdyson	 * a replay.
29814037Sdyson	 */
29913675Sdyson
30076364Salfred	/*
30176364Salfred	 * Check if the device handled the decrypt in hardware.
30213675Sdyson	 * If so we just strip the header; otherwise we need to
30313675Sdyson	 * handle the decrypt in software.
30413675Sdyson	 */
30513675Sdyson	if ((k->wk_flags & IEEE80211_KEY_SWDECRYPT) &&
30614037Sdyson	    !tkip_decrypt(ctx, k, m, hdrlen))
30713675Sdyson		return 0;
30876364Salfred
30976364Salfred	/*
31013688Sdyson	 * Copy up 802.11 header and strip crypto bits.
31113675Sdyson	 */
31276364Salfred	memmove(mtod(m, uint8_t *) + tkip.ic_header, mtod(m, void *), hdrlen);
31376364Salfred	m_adj(m, tkip.ic_header);
31476364Salfred	m_adj(m, -tkip.ic_trailer);
31576364Salfred
31676364Salfred	return 1;
31776364Salfred}
31876364Salfred
31976364Salfred/*
32076364Salfred * Verify and strip MIC from the frame.
32176364Salfred */
32276364Salfredstatic int
32376364Salfredtkip_demic(struct ieee80211_key *k, struct mbuf *m, int force)
32476364Salfred{
32513907Sdyson	struct tkip_ctx *ctx = k->wk_private;
32676364Salfred	struct ieee80211_frame *wh;
32713907Sdyson	uint8_t tid;
32813688Sdyson
32913907Sdyson	wh = mtod(m, struct ieee80211_frame *);
33013907Sdyson	if ((k->wk_flags & IEEE80211_KEY_SWDEMIC) || force) {
33113907Sdyson		struct ieee80211vap *vap = ctx->tc_vap;
33276364Salfred		int hdrlen = ieee80211_hdrspace(vap->iv_ic, wh);
33376364Salfred		u8 mic[IEEE80211_WEP_MICLEN];
33476364Salfred		u8 mic0[IEEE80211_WEP_MICLEN];
33576364Salfred
33613907Sdyson		vap->iv_stats.is_crypto_tkipdemic++;
33776364Salfred
33813907Sdyson		michael_mic(ctx, k->wk_rxmic,
33976364Salfred			m, hdrlen, m->m_pkthdr.len - (hdrlen + tkip.ic_miclen),
34076364Salfred			mic);
34176364Salfred		m_copydata(m, m->m_pkthdr.len - tkip.ic_miclen,
34217163Sdyson			tkip.ic_miclen, mic0);
34376364Salfred		if (memcmp(mic, mic0, tkip.ic_miclen)) {
34476364Salfred			/* NB: 802.11 layer handles statistic and debug msg */
34576364Salfred			ieee80211_notify_michael_failure(vap, wh,
34676364Salfred				k->wk_rxkeyix != IEEE80211_KEYIX_NONE ?
34776364Salfred					k->wk_rxkeyix : k->wk_keyix);
34876364Salfred			return 0;
34976364Salfred		}
35076364Salfred	}
35176364Salfred	/*
35276364Salfred	 * Strip MIC from the tail.
35376364Salfred	 */
35476754Salfred	m_adj(m, -tkip.ic_miclen);
35513675Sdyson
35613675Sdyson	/*
35713675Sdyson	 * Ok to update rsc now that MIC has been verified.
35813907Sdyson	 */
35914037Sdyson	tid = ieee80211_gettid(wh);
36013907Sdyson	k->wk_keyrsc[tid] = ctx->rx_rsc;
36113907Sdyson
36213907Sdyson	return 1;
36313907Sdyson}
36413907Sdyson
36513907Sdyson/*
36613907Sdyson * Host AP crypt: host-based TKIP encryption implementation for Host AP driver
36717124Sbde *
36814037Sdyson * Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi>
36976364Salfred *
37091412Salfred * This program is free software; you can redistribute it and/or modify
37176364Salfred * it under the terms of the GNU General Public License version 2 as
37276760Salfred * published by the Free Software Foundation. See README and COPYING for
37376364Salfred * more details.
37476364Salfred *
37576364Salfred * Alternatively, this software may be distributed under the terms of BSD
37676364Salfred * license.
37776364Salfred */
37876364Salfred
37976364Salfredstatic const __u32 crc32_table[256] = {
38013675Sdyson	0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
38113675Sdyson	0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
38213675Sdyson	0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
38313675Sdyson	0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
38413675Sdyson	0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
38513675Sdyson	0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
38613675Sdyson	0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
38713907Sdyson	0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
38813675Sdyson	0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
38913907Sdyson	0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
39013675Sdyson	0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
39113776Sdyson	0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
39276364Salfred	0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
39391362Salfred	0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
39491362Salfred	0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
39513675Sdyson	0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
39691362Salfred	0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
39791362Salfred	0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
39876760Salfred	0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
39976760Salfred	0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
40076760Salfred	0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
40113675Sdyson	0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
40291362Salfred	0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
40376760Salfred	0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
40413675Sdyson	0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
40513675Sdyson	0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
40613675Sdyson	0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
40713675Sdyson	0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
40813675Sdyson	0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
40913675Sdyson	0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
41013675Sdyson	0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
41113675Sdyson	0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
41213675Sdyson	0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
41376364Salfred	0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
41491362Salfred	0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
41591362Salfred	0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
41613675Sdyson	0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
41713675Sdyson	0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
41814177Sdyson	0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
41913675Sdyson	0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
42013675Sdyson	0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
42113675Sdyson	0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
42214037Sdyson	0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
42314037Sdyson	0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
42414037Sdyson	0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
42514037Sdyson	0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
42676364Salfred	0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
42714037Sdyson	0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
42814037Sdyson	0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
42914037Sdyson	0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
43014037Sdyson	0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
43141086Struckman	0x2d02ef8dL
43241086Struckman};
43359288Sjlemon
43414037Sdysonstatic __inline u16 RotR1(u16 val)
43514037Sdyson{
43613675Sdyson	return (val >> 1) | (val << 15);
43713675Sdyson}
43883366Sjulian
43913675Sdysonstatic __inline u8 Lo8(u16 val)
44013675Sdyson{
44113675Sdyson	return val & 0xff;
44283366Sjulian}
44345311Sdt
44413675Sdysonstatic __inline u8 Hi8(u16 val)
44513675Sdyson{
44647748Salc	return val >> 8;
44713675Sdyson}
44818863Sdyson
44913675Sdysonstatic __inline u16 Lo16(u32 val)
45091362Salfred{
45113675Sdyson	return val & 0xffff;
45247748Salc}
45347748Salc
45447748Salcstatic __inline u16 Hi16(u32 val)
45547748Salc{
45613675Sdyson	return val >> 16;
45713907Sdyson}
45813907Sdyson
45913907Sdysonstatic __inline u16 Mk16(u8 hi, u8 lo)
46013675Sdyson{
46118863Sdyson	return lo | (((u16) hi) << 8);
46213675Sdyson}
46313675Sdyson
46418863Sdysonstatic __inline u16 Mk16_le(const u16 *v)
46518863Sdyson{
46647748Salc	return le16toh(*v);
46791362Salfred}
46847748Salc
46913675Sdysonstatic const u16 Sbox[256] = {
47091362Salfred	0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154,
47176760Salfred	0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A,
47213675Sdyson	0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B,
47376760Salfred	0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B,
47413675Sdyson	0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F,
47513675Sdyson	0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F,
47613675Sdyson	0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5,
47713675Sdyson	0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F,
47813675Sdyson	0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB,
47947748Salc	0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397,
48047748Salc	0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED,
48147748Salc	0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A,
48247748Salc	0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194,
48347748Salc	0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3,
48447748Salc	0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104,
48547748Salc	0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D,
48647748Salc	0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39,
48747748Salc	0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695,
48847748Salc	0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83,
48913675Sdyson	0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76,
49014037Sdyson	0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4,
49113907Sdyson	0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B,
49213907Sdyson	0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0,
49313907Sdyson	0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018,
49413907Sdyson	0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751,
49547748Salc	0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85,
49647748Salc	0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12,
49718863Sdyson	0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9,
49818863Sdyson	0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7,
49947748Salc	0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A,
50076760Salfred	0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8,
50176760Salfred	0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A,
50291362Salfred};
50347748Salc
50491362Salfredstatic __inline u16 _S_(u16 v)
50513907Sdyson{
50613907Sdyson	u16 t = Sbox[Hi8(v)];
50713907Sdyson	return Sbox[Lo8(v)] ^ ((t << 8) | (t >> 8));
50813907Sdyson}
50913907Sdyson
51013907Sdyson#define PHASE1_LOOP_COUNT 8
51113907Sdyson
51213907Sdysonstatic void tkip_mixing_phase1(u16 *TTAK, const u8 *TK, const u8 *TA, u32 IV32)
51313907Sdyson{
51414037Sdyson	int i, j;
51513675Sdyson
51613675Sdyson	/* Initialize the 80-bit TTAK from TSC (IV32) and TA[0..5] */
51713675Sdyson	TTAK[0] = Lo16(IV32);
51876760Salfred	TTAK[1] = Hi16(IV32);
51913675Sdyson	TTAK[2] = Mk16(TA[1], TA[0]);
52076760Salfred	TTAK[3] = Mk16(TA[3], TA[2]);
52113675Sdyson	TTAK[4] = Mk16(TA[5], TA[4]);
52243623Sdillon
52313675Sdyson	for (i = 0; i < PHASE1_LOOP_COUNT; i++) {
52413675Sdyson		j = 2 * (i & 1);
52513675Sdyson		TTAK[0] += _S_(TTAK[4] ^ Mk16(TK[1 + j], TK[0 + j]));
52613675Sdyson		TTAK[1] += _S_(TTAK[0] ^ Mk16(TK[5 + j], TK[4 + j]));
52713675Sdyson		TTAK[2] += _S_(TTAK[1] ^ Mk16(TK[9 + j], TK[8 + j]));
52813675Sdyson		TTAK[3] += _S_(TTAK[2] ^ Mk16(TK[13 + j], TK[12 + j]));
52913675Sdyson		TTAK[4] += _S_(TTAK[3] ^ Mk16(TK[1 + j], TK[0 + j])) + i;
53043623Sdillon	}
53143623Sdillon}
53247748Salc
53343623Sdillon#ifndef _BYTE_ORDER
53447748Salc#error "Don't know native byte order"
53513675Sdyson#endif
53616960Sdyson
53743623Sdillonstatic void tkip_mixing_phase2(u8 *WEPSeed, const u8 *TK, const u16 *TTAK,
53847748Salc			       u16 IV16)
53947748Salc{
54047748Salc	/* Make temporary area overlap WEP seed so that the final copy can be
54143623Sdillon	 * avoided on little endian hosts. */
54247748Salc	u16 *PPK = (u16 *) &WEPSeed[4];
54343623Sdillon
54413675Sdyson	/* Step 1 - make copy of TTAK and bring in TSC */
54547748Salc	PPK[0] = TTAK[0];
54647748Salc	PPK[1] = TTAK[1];
54713675Sdyson	PPK[2] = TTAK[2];
54876760Salfred	PPK[3] = TTAK[3];
54947748Salc	PPK[4] = TTAK[4];
55076760Salfred	PPK[5] = TTAK[4] + IV16;
55147748Salc
55291362Salfred	/* Step 2 - 96-bit bijective mixing using S-box */
55391362Salfred	PPK[0] += _S_(PPK[5] ^ Mk16_le((const u16 *) &TK[0]));
55477140Salfred	PPK[1] += _S_(PPK[0] ^ Mk16_le((const u16 *) &TK[2]));
55547748Salc	PPK[2] += _S_(PPK[1] ^ Mk16_le((const u16 *) &TK[4]));
55613675Sdyson	PPK[3] += _S_(PPK[2] ^ Mk16_le((const u16 *) &TK[6]));
55747748Salc	PPK[4] += _S_(PPK[3] ^ Mk16_le((const u16 *) &TK[8]));
55847748Salc	PPK[5] += _S_(PPK[4] ^ Mk16_le((const u16 *) &TK[10]));
55913675Sdyson
56013675Sdyson	PPK[0] += RotR1(PPK[5] ^ Mk16_le((const u16 *) &TK[12]));
56147748Salc	PPK[1] += RotR1(PPK[0] ^ Mk16_le((const u16 *) &TK[14]));
56213675Sdyson	PPK[2] += RotR1(PPK[1]);
56391362Salfred	PPK[3] += RotR1(PPK[2]);
56424101Sbde	PPK[4] += RotR1(PPK[3]);
56555112Sbde	PPK[5] += RotR1(PPK[4]);
56647748Salc
56747748Salc	/* Step 3 - bring in last of TK bits, assign 24-bit WEP IV value
56813913Sdyson	 * WEPSeed[0..2] is transmitted as WEP IV */
56947748Salc	WEPSeed[0] = Hi8(IV16);
57047748Salc	WEPSeed[1] = (Hi8(IV16) | 0x20) & 0x7F;
57147748Salc	WEPSeed[2] = Lo8(IV16);
57213675Sdyson	WEPSeed[3] = Lo8((PPK[5] ^ Mk16_le((const u16 *) &TK[0])) >> 1);
57313675Sdyson
57413675Sdyson#if _BYTE_ORDER == _BIG_ENDIAN
57513675Sdyson	{
57613675Sdyson		int i;
57747748Salc		for (i = 0; i < 6; i++)
57813675Sdyson			PPK[i] = (PPK[i] << 8) | (PPK[i] >> 8);
57913675Sdyson	}
58013675Sdyson#endif
58113675Sdyson}
58213675Sdyson
58313675Sdysonstatic void
58414037Sdysonwep_encrypt(u8 *key, struct mbuf *m0, u_int off, size_t data_len,
58514802Sdyson	uint8_t icv[IEEE80211_WEP_CRCLEN])
58614037Sdyson{
58714037Sdyson	u32 i, j, k, crc;
58891362Salfred	size_t buflen;
58976760Salfred	u8 S[256];
59013675Sdyson	u8 *pos;
59113675Sdyson	struct mbuf *m;
59214037Sdyson#define S_SWAP(a,b) do { u8 t = S[a]; S[a] = S[b]; S[b] = t; } while(0)
59313907Sdyson
59413907Sdyson	/* Setup RC4 state */
59513907Sdyson	for (i = 0; i < 256; i++)
59613907Sdyson		S[i] = i;
59713675Sdyson	j = 0;
59813907Sdyson	for (i = 0; i < 256; i++) {
59913907Sdyson		j = (j + S[i] + key[i & 0x0f]) & 0xff;
60013675Sdyson		S_SWAP(i, j);
60113675Sdyson	}
60218863Sdyson
60313907Sdyson	/* Compute CRC32 over unencrypted data and apply RC4 to data */
60413907Sdyson	crc = ~0;
60513907Sdyson	i = j = 0;
60679224Sdillon	m = m0;
60791412Salfred	pos = mtod(m, uint8_t *) + off;
60879224Sdillon	buflen = m->m_len - off;
60918863Sdyson	for (;;) {
61013907Sdyson		if (buflen > data_len)
61113907Sdyson			buflen = data_len;
61213907Sdyson		data_len -= buflen;
61340286Sdg		for (k = 0; k < buflen; k++) {
61476760Salfred			crc = crc32_table[(crc ^ *pos) & 0xff] ^ (crc >> 8);
61576760Salfred			i = (i + 1) & 0xff;
61613907Sdyson			j = (j + S[i]) & 0xff;
61713907Sdyson			S_SWAP(i, j);
61851474Sdillon			*pos++ ^= S[(S[i] + S[j]) & 0xff];
61951474Sdillon		}
62013907Sdyson		m = m->m_next;
62176760Salfred		if (m == NULL) {
62276760Salfred			KASSERT(data_len == 0,
62340700Sdg			    ("out of buffers with data_len %zu\n", data_len));
62476760Salfred			break;
62513907Sdyson		}
62613907Sdyson		pos = mtod(m, uint8_t *);
62713907Sdyson		buflen = m->m_len;
62813907Sdyson	}
62913907Sdyson	crc = ~crc;
63013907Sdyson
63113907Sdyson	/* Append little-endian CRC32 and encrypt it to produce ICV */
63213907Sdyson	icv[0] = crc;
63313907Sdyson	icv[1] = crc >> 8;
63413907Sdyson	icv[2] = crc >> 16;
63513907Sdyson	icv[3] = crc >> 24;
63676760Salfred	for (k = 0; k < IEEE80211_WEP_CRCLEN; k++) {
63776760Salfred		i = (i + 1) & 0xff;
63813907Sdyson		j = (j + S[i]) & 0xff;
63913907Sdyson		S_SWAP(i, j);
64013907Sdyson		icv[k] ^= S[(S[i] + S[j]) & 0xff];
64113907Sdyson	}
64213907Sdyson}
64313907Sdyson
64413912Sdysonstatic int
64513912Sdysonwep_decrypt(u8 *key, struct mbuf *m, u_int off, size_t data_len)
64613912Sdyson{
64713912Sdyson	u32 i, j, k, crc;
64813907Sdyson	u8 S[256];
64913912Sdyson	u8 *pos, icv[4];
65013912Sdyson	size_t buflen;
65113907Sdyson
65213907Sdyson	/* Setup RC4 state */
65313907Sdyson	for (i = 0; i < 256; i++)
65413907Sdyson		S[i] = i;
65513907Sdyson	j = 0;
65613907Sdyson	for (i = 0; i < 256; i++) {
65713907Sdyson		j = (j + S[i] + key[i & 0x0f]) & 0xff;
65813907Sdyson		S_SWAP(i, j);
65913907Sdyson	}
66013907Sdyson
66113907Sdyson	/* Apply RC4 to data and compute CRC32 over decrypted data */
66213907Sdyson	crc = ~0;
66313907Sdyson	i = j = 0;
66413907Sdyson	pos = mtod(m, uint8_t *) + off;
66576760Salfred	buflen = m->m_len - off;
66613907Sdyson	for (;;) {
66713907Sdyson		if (buflen > data_len)
66813907Sdyson			buflen = data_len;
66913907Sdyson		data_len -= buflen;
67013907Sdyson		for (k = 0; k < buflen; k++) {
67113907Sdyson			i = (i + 1) & 0xff;
67213907Sdyson			j = (j + S[i]) & 0xff;
67376760Salfred			S_SWAP(i, j);
67413907Sdyson			*pos ^= S[(S[i] + S[j]) & 0xff];
67513907Sdyson			crc = crc32_table[(crc ^ *pos) & 0xff] ^ (crc >> 8);
67676364Salfred			pos++;
67779224Sdillon		}
67891412Salfred		m = m->m_next;
67979224Sdillon		if (m == NULL) {
68017163Sdyson			KASSERT(data_len == 0,
68117163Sdyson			    ("out of buffers with data_len %zu\n", data_len));
68213907Sdyson			break;
68313907Sdyson		}
68413907Sdyson		pos = mtod(m, uint8_t *);
68513907Sdyson		buflen = m->m_len;
68613907Sdyson	}
68713912Sdyson	crc = ~crc;
68813912Sdyson
68913907Sdyson	/* Encrypt little-endian CRC32 and verify that it matches with the
69013907Sdyson	 * received ICV */
69176760Salfred	icv[0] = crc;
69240700Sdg	icv[1] = crc >> 8;
69391653Stanimura	icv[2] = crc >> 16;
69413907Sdyson	icv[3] = crc >> 24;
69513907Sdyson	for (k = 0; k < 4; k++) {
69613907Sdyson		i = (i + 1) & 0xff;
69713907Sdyson		j = (j + S[i]) & 0xff;
69813907Sdyson		S_SWAP(i, j);
69913907Sdyson		if ((icv[k] ^ S[(S[i] + S[j]) & 0xff]) != *pos++) {
70013907Sdyson			/* ICV mismatch - drop frame */
70113907Sdyson			return -1;
70213907Sdyson		}
70376364Salfred	}
70413907Sdyson
70513907Sdyson	return 0;
70613907Sdyson}
70713907Sdyson
70891362Salfred
70913907Sdysonstatic __inline u32 rotl(u32 val, int bits)
71013907Sdyson{
71176760Salfred	return (val << bits) | (val >> (32 - bits));
71276760Salfred}
71313907Sdyson
71413907Sdyson
71513907Sdysonstatic __inline u32 rotr(u32 val, int bits)
71613907Sdyson{
71713907Sdyson	return (val >> bits) | (val << (32 - bits));
71813907Sdyson}
71991412Salfred
72013907Sdyson
72191412Salfredstatic __inline u32 xswap(u32 val)
72213907Sdyson{
72313907Sdyson	return ((val & 0x00ff00ff) << 8) | ((val & 0xff00ff00) >> 8);
72413907Sdyson}
72513907Sdyson
72613907Sdyson
72713907Sdyson#define michael_block(l, r)	\
72813907Sdysondo {				\
72913907Sdyson	r ^= rotl(l, 17);	\
73013907Sdyson	l += r;			\
73113907Sdyson	r ^= xswap(l);		\
73213907Sdyson	l += r;			\
73313907Sdyson	r ^= rotl(l, 3);	\
73413907Sdyson	l += r;			\
73513907Sdyson	r ^= rotr(l, 2);	\
73613907Sdyson	l += r;			\
73776364Salfred} while (0)
73813951Sdyson
73991362Salfred
74013907Sdysonstatic __inline u32 get_le32_split(u8 b0, u8 b1, u8 b2, u8 b3)
74176760Salfred{
74213951Sdyson	return b0 | (b1 << 8) | (b2 << 16) | (b3 << 24);
74313951Sdyson}
74413951Sdyson
74513992Sdysonstatic __inline u32 get_le32(const u8 *p)
74691362Salfred{
74791362Salfred	return get_le32_split(p[0], p[1], p[2], p[3]);
74814802Sdyson}
74913907Sdyson
75014802Sdyson
75114802Sdysonstatic __inline void put_le32(u8 *p, u32 v)
75214802Sdyson{
75314802Sdyson	p[0] = v;
75413907Sdyson	p[1] = v >> 8;
75513907Sdyson	p[2] = v >> 16;
75613951Sdyson	p[3] = v >> 24;
75776760Salfred}
75813951Sdyson
75913951Sdyson/*
76013951Sdyson * Craft pseudo header used to calculate the MIC.
76113951Sdyson */
76213992Sdysonstatic void
76391362Salfredmichael_mic_hdr(const struct ieee80211_frame *wh0, uint8_t hdr[16])
76491362Salfred{
76514802Sdyson	const struct ieee80211_frame_addr4 *wh =
76613907Sdyson		(const struct ieee80211_frame_addr4 *) wh0;
76714802Sdyson
76814802Sdyson	switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) {
76914802Sdyson	case IEEE80211_FC1_DIR_NODS:
77013907Sdyson		IEEE80211_ADDR_COPY(hdr, wh->i_addr1); /* DA */
77113951Sdyson		IEEE80211_ADDR_COPY(hdr + IEEE80211_ADDR_LEN, wh->i_addr2);
77213907Sdyson		break;
77313907Sdyson	case IEEE80211_FC1_DIR_TODS:
77413951Sdyson		IEEE80211_ADDR_COPY(hdr, wh->i_addr3); /* DA */
77513951Sdyson		IEEE80211_ADDR_COPY(hdr + IEEE80211_ADDR_LEN, wh->i_addr2);
77692305Salfred		break;
77791362Salfred	case IEEE80211_FC1_DIR_FROMDS:
77813907Sdyson		IEEE80211_ADDR_COPY(hdr, wh->i_addr1); /* DA */
77991362Salfred		IEEE80211_ADDR_COPY(hdr + IEEE80211_ADDR_LEN, wh->i_addr3);
78092305Salfred		break;
78113907Sdyson	case IEEE80211_FC1_DIR_DSTODS:
78213907Sdyson		IEEE80211_ADDR_COPY(hdr, wh->i_addr3); /* DA */
78313907Sdyson		IEEE80211_ADDR_COPY(hdr + IEEE80211_ADDR_LEN, wh->i_addr4);
78413907Sdyson		break;
78513907Sdyson	}
78613907Sdyson
78713907Sdyson	if (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_QOS) {
78813907Sdyson		const struct ieee80211_qosframe *qwh =
78913907Sdyson			(const struct ieee80211_qosframe *) wh;
79091362Salfred		hdr[12] = qwh->i_qos[0] & IEEE80211_QOS_TID;
79113907Sdyson	} else
79291362Salfred		hdr[12] = 0;
79313907Sdyson	hdr[13] = hdr[14] = hdr[15] = 0; /* reserved */
79414037Sdyson}
79514802Sdyson
79614802Sdysonstatic void
79713907Sdysonmichael_mic(struct tkip_ctx *ctx, const u8 *key,
79813992Sdyson	struct mbuf *m, u_int off, size_t data_len,
79913992Sdyson	u8 mic[IEEE80211_WEP_MICLEN])
80013992Sdyson{
80113992Sdyson	uint8_t hdr[16];
80214037Sdyson	u32 l, r;
80391362Salfred	const uint8_t *data;
80491362Salfred	u_int space;
80513907Sdyson
80613907Sdyson	michael_mic_hdr(mtod(m, struct ieee80211_frame *), hdr);
80713907Sdyson
80813907Sdyson	l = get_le32(key);
80913907Sdyson	r = get_le32(key + 4);
81013907Sdyson
81113907Sdyson	/* Michael MIC pseudo header: DA, SA, 3 x 0, Priority */
81213907Sdyson	l ^= get_le32(hdr);
81313907Sdyson	michael_block(l, r);
81413907Sdyson	l ^= get_le32(&hdr[4]);
81591412Salfred	michael_block(l, r);
81613907Sdyson	l ^= get_le32(&hdr[8]);
81791412Salfred	michael_block(l, r);
81813907Sdyson	l ^= get_le32(&hdr[12]);
81913907Sdyson	michael_block(l, r);
82076760Salfred
82113907Sdyson	/* first buffer has special handling */
82213907Sdyson	data = mtod(m, const uint8_t *) + off;
82313907Sdyson	space = m->m_len - off;
82476760Salfred	for (;;) {
82513907Sdyson		if (space > data_len)
82614037Sdyson			space = data_len;
82713907Sdyson		/* collect 32-bit blocks from current buffer */
82816960Sdyson		while (space >= sizeof(uint32_t)) {
82983366Sjulian			l ^= get_le32(data);
83016960Sdyson			michael_block(l, r);
83113907Sdyson			data += sizeof(uint32_t), space -= sizeof(uint32_t);
83216960Sdyson			data_len -= sizeof(uint32_t);
83383366Sjulian		}
83445311Sdt		/*
83513907Sdyson		 * NB: when space is zero we make one more trip around
83613675Sdyson		 * the loop to advance to the next mbuf where there is
83713913Sdyson		 * data.  This handles the case where there are 4*n
83816960Sdyson		 * bytes in an mbuf followed by <4 bytes in a later mbuf.
83916960Sdyson		 * By making an extra trip we'll drop out of the loop
84016960Sdyson		 * with m pointing at the mbuf with 3 bytes and space
84116960Sdyson		 * set as required by the remainder handling below.
84216960Sdyson		 */
84391395Salfred		if (data_len == 0 ||
84413675Sdyson		    (data_len < sizeof(uint32_t) && space != 0))
84513675Sdyson			break;
84613675Sdyson		m = m->m_next;
84716960Sdyson		if (m == NULL) {
84891395Salfred			KASSERT(0, ("out of data, data_len %zu\n", data_len));
84976760Salfred			break;
85013675Sdyson		}
85177676Sdillon		if (space != 0) {
85213675Sdyson			const uint8_t *data_next;
85317163Sdyson			/*
85417163Sdyson			 * Block straddles buffers, split references.
85517163Sdyson			 */
85617163Sdyson			data_next = mtod(m, const uint8_t *);
85717163Sdyson			KASSERT(m->m_len >= sizeof(uint32_t) - space,
85817163Sdyson				("not enough data in following buffer, "
85917163Sdyson				"m_len %u need %zu\n", m->m_len,
86017163Sdyson				sizeof(uint32_t) - space));
86117163Sdyson			switch (space) {
86217163Sdyson			case 1:
86313907Sdyson				l ^= get_le32_split(data[0], data_next[0],
86492305Salfred					data_next[1], data_next[2]);
86576364Salfred				data = data_next + 3;
86676364Salfred				space = m->m_len - 3;
86792305Salfred				break;
86813907Sdyson			case 2:
86913907Sdyson				l ^= get_le32_split(data[0], data[1],
87013907Sdyson					data_next[0], data_next[1]);
87177676Sdillon				data = data_next + 2;
87277676Sdillon				space = m->m_len - 2;
87377676Sdillon				break;
87477676Sdillon			case 3:
87577676Sdillon				l ^= get_le32_split(data[0], data[1],
87677676Sdillon					data[2], data_next[0]);
87777676Sdillon				data = data_next + 1;
87877676Sdillon				space = m->m_len - 1;
87977676Sdillon				break;
88077676Sdillon			}
88177676Sdillon			michael_block(l, r);
88277676Sdillon			data_len -= sizeof(uint32_t);
88391395Salfred		} else {
88477676Sdillon			/*
88577676Sdillon			 * Setup for next buffer.
88676364Salfred			 */
88776364Salfred			data = mtod(m, const uint8_t *);
88813907Sdyson			space = m->m_len;
88913913Sdyson		}
89077676Sdillon	}
89113675Sdyson	/*
89213907Sdyson	 * Catch degenerate cases like mbuf[4*n+1 bytes] followed by
89376760Salfred	 * mbuf[2 bytes].  I don't believe these should happen; if they
89414037Sdyson	 * do then we'll need more involved logic.
89513907Sdyson	 */
89613907Sdyson	KASSERT(data_len <= space,
89713907Sdyson	    ("not enough data, data_len %zu space %u\n", data_len, space));
89816416Sdyson
89916416Sdyson	/* Last block and padding (0x5a, 4..7 x 0) */
90058505Sdillon	switch (data_len) {
90158505Sdillon	case 0:
90258505Sdillon		l ^= get_le32_split(0x5a, 0, 0, 0);
90313907Sdyson		break;
90417163Sdyson	case 1:
90517163Sdyson		l ^= get_le32_split(data[0], 0x5a, 0, 0);
90617163Sdyson		break;
90713907Sdyson	case 2:
90813907Sdyson		l ^= get_le32_split(data[0], data[1], 0x5a, 0);
90976760Salfred		break;
91013907Sdyson	case 3:
91113907Sdyson		l ^= get_le32_split(data[0], data[1], data[2], 0x5a);
91291362Salfred		break;
91314037Sdyson	}
91413907Sdyson	michael_block(l, r);
91513907Sdyson	/* l ^= 0; */
91613907Sdyson	michael_block(l, r);
91713907Sdyson
91813907Sdyson	put_le32(mic, l);
91958505Sdillon	put_le32(mic + 4, r);
92058505Sdillon}
92113907Sdyson
92213907Sdysonstatic int
92313907Sdysontkip_encrypt(struct tkip_ctx *ctx, struct ieee80211_key *key,
92413992Sdyson	struct mbuf *m, int hdrlen)
92513992Sdyson{
92613992Sdyson	struct ieee80211_frame *wh;
92713992Sdyson	uint8_t icv[IEEE80211_WEP_CRCLEN];
92891395Salfred
92991362Salfred	ctx->tc_vap->iv_stats.is_crypto_tkip++;
93058505Sdillon
93158505Sdillon	wh = mtod(m, struct ieee80211_frame *);
93213907Sdyson	if (!ctx->tx_phase1_done) {
93313907Sdyson		tkip_mixing_phase1(ctx->tx_ttak, key->wk_key, wh->i_addr2,
93413907Sdyson				   (u32)(key->wk_keytsc >> 16));
93558505Sdillon		ctx->tx_phase1_done = 1;
93658505Sdillon	}
93758505Sdillon	tkip_mixing_phase2(ctx->tx_rc4key, key->wk_key, ctx->tx_ttak,
93858505Sdillon		(u16) key->wk_keytsc);
93913907Sdyson
94013907Sdyson	wep_encrypt(ctx->tx_rc4key,
94114644Sdyson		m, hdrlen + tkip.ic_header,
94214644Sdyson		m->m_pkthdr.len - (hdrlen + tkip.ic_header),
94313913Sdyson		icv);
94413913Sdyson	(void) m_append(m, IEEE80211_WEP_CRCLEN, icv);	/* XXX check return */
94513907Sdyson
94617163Sdyson	key->wk_keytsc++;
94713907Sdyson	if ((u16)(key->wk_keytsc) == 0)
94854534Stegge		ctx->tx_phase1_done = 0;
94954534Stegge	return 1;
95076760Salfred}
95113907Sdyson
95213907Sdysonstatic int
95313907Sdysontkip_decrypt(struct tkip_ctx *ctx, struct ieee80211_key *key,
95413907Sdyson	struct mbuf *m, int hdrlen)
95513907Sdyson{
95613907Sdyson	struct ieee80211_frame *wh;
95713907Sdyson	struct ieee80211vap *vap = ctx->tc_vap;
95813907Sdyson	u32 iv32;
95954534Stegge	u16 iv16;
96054534Stegge	u8 tid;
96154534Stegge
96258505Sdillon	vap->iv_stats.is_crypto_tkip++;
96358505Sdillon
96458505Sdillon	wh = mtod(m, struct ieee80211_frame *);
96554534Stegge	/* NB: tkip_decap already verified header and left seq in rx_rsc */
96654534Stegge	iv16 = (u16) ctx->rx_rsc;
96754534Stegge	iv32 = (u32) (ctx->rx_rsc >> 16);
96854534Stegge
96954534Stegge	tid = ieee80211_gettid(wh);
97054534Stegge	if (iv32 != (u32)(key->wk_keyrsc[tid] >> 16) || !ctx->rx_phase1_done) {
97154534Stegge		tkip_mixing_phase1(ctx->rx_ttak, key->wk_key,
97254534Stegge			wh->i_addr2, iv32);
97354534Stegge		ctx->rx_phase1_done = 1;
97454534Stegge	}
97554534Stegge	tkip_mixing_phase2(ctx->rx_rc4key, key->wk_key, ctx->rx_ttak, iv16);
97654534Stegge
97754534Stegge	/* NB: m is unstripped; deduct headers + ICV to get payload */
97854534Stegge	if (wep_decrypt(ctx->rx_rc4key,
97954534Stegge		m, hdrlen + tkip.ic_header,
98054534Stegge	        m->m_pkthdr.len - (hdrlen + tkip.ic_header + tkip.ic_trailer))) {
98154534Stegge		if (iv32 != (u32)(key->wk_keyrsc[tid] >> 16)) {
98254534Stegge			/* Previously cached Phase1 result was already lost, so
98354534Stegge			 * it needs to be recalculated for the next packet. */
98454534Stegge			ctx->rx_phase1_done = 0;
98554534Stegge		}
98654534Stegge		IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO, wh->i_addr2,
98754534Stegge		    "%s", "TKIP ICV mismatch on decrypt");
98854534Stegge		vap->iv_stats.is_rx_tkipicv++;
98954534Stegge		return 0;
99054534Stegge	}
99154534Stegge	return 1;
99254534Stegge}
99354534Stegge
99491395Salfred/*
99554534Stegge * Module glue.
99654534Stegge */
99791395SalfredIEEE80211_CRYPTO_MODULE(tkip, 1);
99854534Stegge