net80211_crypto_tkip.c revision 4126:31652d91f33e
1/*
2 * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
3 * Use is subject to license terms.
4 */
5
6/*
7 * Copyright (c) 2001 Atsushi Onoe
8 * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 *    notice, this list of conditions and the following disclaimer in the
18 *    documentation and/or other materials provided with the distribution.
19 * 3. The name of the author may not be used to endorse or promote products
20 *    derived from this software without specific prior written permission.
21 *
22 * Alternatively, this software may be distributed under the terms of the
23 * GNU General Public License ("GPL") version 2 as published by the Free
24 * Software Foundation.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
27 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
28 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
29 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
30 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
31 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
35 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 */
37
38#pragma ident	"%Z%%M%	%I%	%E% SMI"
39
40/*
41 * IEEE 802.11i TKIP crypto support.
42 */
43#include <sys/byteorder.h>
44#include <sys/crypto/common.h>
45#include <sys/crypto/api.h>
46#include <sys/crc32.h>
47#include <sys/random.h>
48#include "net80211_impl.h"
49
50static void *tkip_attach(struct ieee80211com *, struct ieee80211_key *);
51static void tkip_detach(struct ieee80211_key *);
52static int tkip_setkey(struct ieee80211_key *);
53static int tkip_encap(struct ieee80211_key *, mblk_t *, uint8_t);
54static int tkip_decap(struct ieee80211_key *, mblk_t *, int);
55static int tkip_enmic(struct ieee80211_key *, mblk_t *, int);
56static int tkip_demic(struct ieee80211_key *, mblk_t *, int);
57
58const struct ieee80211_cipher tkip  = {
59	"TKIP",
60	IEEE80211_CIPHER_TKIP,
61	IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN +
62	    IEEE80211_WEP_EXTIVLEN,
63	IEEE80211_WEP_CRCLEN,
64	IEEE80211_WEP_MICLEN,
65	tkip_attach,
66	tkip_detach,
67	tkip_setkey,
68	tkip_encap,
69	tkip_decap,
70	tkip_enmic,
71	tkip_demic,
72};
73
74struct tkip_ctx {
75	struct ieee80211com	*tc_ic;		/* for diagnostics */
76	uint16_t		tx_ttak[5];
77	int			tx_phase1_done;
78	uint8_t			tx_rc4key[16];
79	uint16_t		rx_ttak[5];
80	int			rx_phase1_done;
81	uint8_t			rx_rc4key[16];
82	uint64_t		rx_rsc;		/* held until MIC verified */
83};
84
85/* ARGSUSED */
86static void *
87tkip_attach(struct ieee80211com *ic, struct ieee80211_key *k)
88{
89	struct tkip_ctx *ctx;
90
91	ctx = kmem_zalloc(sizeof (struct tkip_ctx), KM_SLEEP);
92	if (ctx == NULL)
93		return (NULL);
94
95	ctx->tc_ic = ic;
96	return (ctx);
97}
98
99static void
100tkip_detach(struct ieee80211_key *k)
101{
102	struct tkip_ctx *ctx = k->wk_private;
103
104	if (ctx != NULL)
105		kmem_free(ctx, sizeof (struct tkip_ctx));
106}
107
108static int
109tkip_setkey(struct ieee80211_key *k)
110{
111	if (k->wk_keylen != (128/NBBY))
112		return (0);
113
114	k->wk_keytsc = 1;		/* TSC starts at 1 */
115	return (1);
116}
117
118/*
119 * Add privacy headers appropriate for the specified key.
120 */
121static int
122tkip_encap(struct ieee80211_key *k, mblk_t *mp, uint8_t keyid)
123{
124	struct tkip_ctx *ctx = k->wk_private;
125	struct ieee80211com *ic = ctx->tc_ic;
126	uint8_t *ivp;
127	int hdrlen;
128
129	/*
130	 * Handle TKIP counter measures requirement.
131	 */
132	if (ic->ic_flags & IEEE80211_F_COUNTERM)
133		return (0);
134
135	hdrlen = ieee80211_hdrspace(mp->b_rptr);
136	/*
137	 * Copy down 802.11 header and add the IV, KeyID, and ExtIV.
138	 */
139	ivp = mp->b_rptr;
140	ivp += hdrlen;
141
142	ivp[0] = k->wk_keytsc >> 8;		/* TSC1 */
143	ivp[1] = (ivp[0] | 0x20) & 0x7f;	/* WEP seed */
144	ivp[2] = k->wk_keytsc >> 0;		/* TSC0 */
145	ivp[3] = keyid | IEEE80211_WEP_EXTIV;	/* KeyID | ExtID */
146	ivp[4] = k->wk_keytsc >> 16;		/* TSC2 */
147	ivp[5] = k->wk_keytsc >> 24;		/* TSC3 */
148	ivp[6] = k->wk_keytsc >> 32;		/* TSC4 */
149	ivp[7] = k->wk_keytsc >> 40;		/* TSC5 */
150
151	/*
152	 * NB: software TKIP is not supported.
153	 */
154	if (k->wk_flags & IEEE80211_KEY_SWCRYPT)
155		return (0);
156	else
157		k->wk_keytsc++;		/* wrap at 48 bits */
158
159	return (1);
160}
161
162uint64_t
163ieee80211_read_6(uint8_t b0, uint8_t b1, uint8_t b2,
164    uint8_t b3, uint8_t b4, uint8_t b5)
165{
166	uint32_t iv32 = (b0 << 0) | (b1 << 8) | (b2 << 16) | (b3 << 24);
167	uint16_t iv16 = (b4 << 0) | (b5 << 8);
168	return ((((uint64_t)iv16) << 32) | iv32);
169}
170
171/*
172 * Validate and strip privacy headers (and trailer) for a
173 * received frame.  If necessary, decrypt the frame using
174 * the specified key.
175 */
176static int
177tkip_decap(struct ieee80211_key *k, mblk_t *mp, int hdrlen)
178{
179	struct tkip_ctx *ctx = k->wk_private;
180	struct ieee80211com *ic = ctx->tc_ic;
181	struct ieee80211_frame tmp;
182	uint8_t *ivp;
183	uint64_t pn;
184
185	/*
186	 * Header should have extended IV and sequence number;
187	 * verify the former and validate the latter.
188	 */
189	ivp = mp->b_rptr + hdrlen;
190	if ((ivp[IEEE80211_WEP_IVLEN] & IEEE80211_WEP_EXTIV) == 0) {
191		/*
192		 * No extended IV; discard frame.
193		 */
194		return (0);
195	}
196	/*
197	 * Handle TKIP counter measures requirement.
198	 */
199	if (ic->ic_flags & IEEE80211_F_COUNTERM)
200		return (0);
201
202	/* NB: assume IEEEE80211_WEP_MINLEN covers the extended IV */
203	pn = ieee80211_read_6(ivp[2], ivp[0], ivp[4], ivp[5], ivp[6], ivp[7]);
204	ctx->rx_rsc = pn;
205	if (ctx->rx_rsc <= k->wk_keyrsc)
206		return (0);
207	/*
208	 * NB: We can't update the rsc in the key until MIC is verified.
209	 *
210	 * We assume we are not preempted between doing the check above
211	 * and updating wk_keyrsc when stripping the MIC in tkip_demic.
212	 * Otherwise we might process another packet and discard it as
213	 * a replay.
214	 */
215
216	/*
217	 * NB: software TKIP is not supported.
218	 */
219	if (k->wk_flags & IEEE80211_KEY_SWCRYPT)
220		return (0);
221
222	/*
223	 * Copy up 802.11 header and strip crypto bits.
224	 */
225	bcopy(mp->b_rptr, &tmp, hdrlen);
226	bcopy(&tmp, mp->b_rptr + tkip.ic_header, hdrlen);
227	mp->b_rptr += tkip.ic_header;
228	mp->b_wptr -= tkip.ic_trailer;
229
230	return (1);
231}
232
233/*
234 * Add MIC to the frame as needed.
235 */
236/* ARGSUSED */
237static int
238tkip_enmic(struct ieee80211_key *k, mblk_t *mp, int force)
239{
240	return (1);
241}
242
243/*
244 * Verify and strip MIC from the frame.
245 */
246/* ARGSUSED */
247static int
248tkip_demic(struct ieee80211_key *k, mblk_t *mp, int force)
249{
250	struct tkip_ctx *ctx = k->wk_private;
251
252	/*
253	 * NB: software TKIP is not supported.
254	 */
255	if (k->wk_flags & IEEE80211_KEY_SWMIC)
256		return (0);
257	/*
258	 * Strip MIC from the tail.
259	 */
260	mp->b_wptr -= tkip.ic_miclen;
261	/*
262	 * Ok to update rsc now that MIC has been verified.
263	 */
264	k->wk_keyrsc = ctx->rx_rsc;
265
266	return (1);
267}
268