1/*
2 * Copyright 2009 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-2008 Sam Leffler, Errno Consulting
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 *    notice, this list of conditions and the following disclaimer in the
18 *    documentation and/or other materials provided with the distribution.
19 * 3. The name of the author may not be used to endorse or promote products
20 *    derived from this software without specific prior written permission.
21 *
22 * Alternatively, this software may be distributed under the terms of the
23 * GNU General Public License ("GPL") version 2 as published by the Free
24 * Software Foundation.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
27 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
28 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
29 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
30 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
31 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
35 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 */
37
38/*
39 * IEEE 802.11 WEP crypto support.
40 */
41#include <sys/byteorder.h>
42#include <sys/crypto/common.h>
43#include <sys/crypto/api.h>
44#include <sys/crc32.h>
45#include <sys/random.h>
46#include <sys/strsun.h>
47#include "net80211_impl.h"
48
49static  void *wep_attach(struct ieee80211com *, struct ieee80211_key *);
50static  void wep_detach(struct ieee80211_key *);
51static  int wep_setkey(struct ieee80211_key *);
52static  int wep_encap(struct ieee80211_key *, mblk_t *, uint8_t keyid);
53static  int wep_decap(struct ieee80211_key *, mblk_t *, int);
54static  int wep_enmic(struct ieee80211_key *, mblk_t *, int);
55static  int wep_demic(struct ieee80211_key *, mblk_t *, int);
56
57const struct ieee80211_cipher wep = {
58	"WEP",
59	IEEE80211_CIPHER_WEP,
60	IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN,
61	IEEE80211_WEP_CRCLEN,
62	0,
63	wep_attach,
64	wep_detach,
65	wep_setkey,
66	wep_encap,
67	wep_decap,
68	wep_enmic,
69	wep_demic,
70};
71
72int rc4_init(crypto_context_t *, const uint8_t *, int);
73int rc4_crypt(crypto_context_t, const uint8_t *, uint8_t *, int);
74int rc4_final(crypto_context_t, uint8_t *, int);
75
76static	int wep_encrypt(struct ieee80211_key *, mblk_t *, int);
77static	int wep_decrypt(struct ieee80211_key *, mblk_t *, int);
78
79struct wep_ctx {
80	ieee80211com_t *wc_ic;		/* for diagnostics */
81	uint32_t	wc_iv;		/* initial vector for crypto */
82};
83
84/* Table of CRCs of all 8-bit messages */
85static uint32_t crc_table[] = { CRC32_TABLE };
86
87/* ARGSUSED */
88static void *
89wep_attach(struct ieee80211com *ic, struct ieee80211_key *k)
90{
91	struct wep_ctx *ctx;
92
93	ctx = kmem_zalloc(sizeof (struct wep_ctx), KM_NOSLEEP);
94	if (ctx == NULL)
95		return (NULL);
96
97	ctx->wc_ic = ic;
98	(void) random_get_pseudo_bytes((unsigned char *)&ctx->wc_iv,
99	    sizeof (uint32_t));
100	return (ctx);
101}
102
103static void
104wep_detach(struct ieee80211_key *k)
105{
106	struct wep_ctx *ctx = k->wk_private;
107
108	if (ctx != NULL)
109		kmem_free(ctx, sizeof (struct wep_ctx));
110}
111
112static int
113wep_setkey(struct ieee80211_key *k)
114{
115	/*
116	 * WEP key length is standardized to 40-bit. Many
117	 * implementations support 104-bit WEP kwys.
118	 */
119	return (k->wk_keylen == 40/NBBY || k->wk_keylen == 104/NBBY);
120}
121
122/*
123 * Add privacy headers appropriate for the specified key.
124 */
125static int
126wep_encap(struct ieee80211_key *k, mblk_t *mp, uint8_t keyid)
127{
128	struct wep_ctx *ctx = k->wk_private;
129	struct ieee80211_frame *wh = (struct ieee80211_frame *)mp->b_rptr;
130	uint32_t iv;
131	uint8_t *ivp;
132	int hdrlen;
133
134	if (mp == NULL)
135		return (0);
136	hdrlen = ieee80211_hdrspace(ctx->wc_ic, wh);
137
138	ivp = (uint8_t *)wh;
139	ivp += hdrlen;
140
141	/*
142	 * IV must not duplicate during the lifetime of the key.
143	 * But no mechanism to renew keys is defined in IEEE 802.11
144	 * WEP.  And IV may be duplicated between other stations
145	 * because of the session key itself is shared.
146	 * So we use pseudo random IV for now, though it is not the
147	 * right way.
148	 */
149	iv = ctx->wc_iv;
150	/*
151	 * Skip 'bad' IVs from Fluhrer/Mantin/Shamir:
152	 * (B, 255, N) with 3 <= B < 8
153	 */
154	if ((iv & 0xff00) == 0xff00) {
155		int B = (iv & 0xff0000) >> 16;
156		if (3 <= B && B < 16)
157			iv = (B+1) << 16;
158	}
159	ctx->wc_iv = iv + 1;
160
161	ivp[2] = (uint8_t)(iv >> 0);
162	ivp[1] = (uint8_t)(iv >> 8);
163	ivp[0] = (uint8_t)(iv >> 16);
164
165	/* Key ID and pad */
166	ivp[IEEE80211_WEP_IVLEN] = keyid;
167
168	if ((k->wk_flags & IEEE80211_KEY_SWCRYPT) &&
169	    (wep_encrypt(k, mp, hdrlen) == 0))
170		return (0);
171
172	return (1);
173}
174
175/*
176 * Validate and strip privacy headers (and trailer) for a
177 * received frame.  If necessary, decrypt the frame using
178 * the specified key.
179 */
180static int
181wep_decap(struct ieee80211_key *k, mblk_t *mp, int hdrlen)
182{
183	/*
184	 * Check if the device handled the decrypt in hardware.
185	 * If so we just strip the header; otherwise we need to
186	 * handle the decrypt in software.
187	 */
188	if ((k->wk_flags & IEEE80211_KEY_SWCRYPT) &&
189	    (wep_decrypt(k, mp, hdrlen) == 0)) {
190		ieee80211_err("WEP ICV mismatch on decrypt\n");
191		return (0);
192	}
193
194	/*
195	 * Copy up 802.11 header and strip crypto bits.
196	 */
197	(void) memmove(mp->b_rptr + wep.ic_header, mp->b_rptr, hdrlen);
198	mp->b_rptr += wep.ic_header;
199	mp->b_wptr -= wep.ic_trailer;
200
201	return (1);
202}
203
204/*
205 * Add MIC to the frame as needed.
206 */
207/* ARGSUSED */
208static int
209wep_enmic(struct ieee80211_key *k, mblk_t *mp, int force)
210{
211	return (1);
212}
213
214/*
215 * Verify and strip MIC from the frame.
216 */
217/* ARGSUSED */
218static int
219wep_demic(struct ieee80211_key *k, mblk_t *mp, int force)
220{
221	return (1);
222}
223
224static int
225wep_encrypt(struct ieee80211_key *key, mblk_t *mp, int hdrlen)
226{
227	uint8_t rc4key[IEEE80211_WEP_IVLEN + IEEE80211_KEYBUF_SIZE];
228	uint8_t crcbuf[IEEE80211_WEP_CRCLEN];
229	uint8_t *icv;
230	uint32_t crc;
231	crypto_context_t ctx;
232	int rv;
233
234	ASSERT(key->wk_flags & IEEE80211_KEY_SWCRYPT);
235
236	/* ctx->wc_ic->isc_stats.is_crypto_wep++; */
237
238	(void) memcpy(rc4key, mp->b_rptr + hdrlen, IEEE80211_WEP_IVLEN);
239	(void) memcpy(rc4key + IEEE80211_WEP_IVLEN, key->wk_key,
240	    key->wk_keylen);
241
242	ctx = NULL;
243	rv = rc4_init(&ctx, (const uint8_t *)rc4key,
244	    IEEE80211_WEP_IVLEN + key->wk_keylen);
245
246	if (rv != CRYPTO_SUCCESS)
247		return (0);
248
249	/* calculate CRC over unencrypted data */
250	CRC32(crc, mp->b_rptr + hdrlen + wep.ic_header,
251	    MBLKL(mp) - (hdrlen + wep.ic_header),
252	    -1U, crc_table);
253
254	/* encrypt data */
255	(void) rc4_crypt(ctx,
256	    mp->b_rptr + hdrlen + wep.ic_header,
257	    mp->b_rptr + hdrlen + wep.ic_header,
258	    MBLKL(mp) - (hdrlen + wep.ic_header));
259
260	/* tack on ICV */
261	*(uint32_t *)crcbuf = LE_32(~crc);
262	icv = mp->b_wptr;
263	mp->b_wptr += IEEE80211_WEP_CRCLEN;
264	(void) rc4_crypt(ctx, crcbuf, icv, IEEE80211_WEP_CRCLEN);
265
266	(void) rc4_final(ctx, icv, IEEE80211_WEP_CRCLEN);
267
268	return (1);
269}
270
271static int
272wep_decrypt(struct ieee80211_key *key, mblk_t *mp, int hdrlen)
273{
274	uint8_t rc4key[IEEE80211_WEP_IVLEN + IEEE80211_KEYBUF_SIZE];
275	uint8_t crcbuf[IEEE80211_WEP_CRCLEN];
276	uint8_t *icv;
277	uint32_t crc;
278	crypto_context_t ctx;
279	int rv;
280
281	ASSERT(key->wk_flags & IEEE80211_KEY_SWCRYPT);
282
283	/* ctx->wc_ic->isc_stats.is_crypto_wep++; */
284
285	(void) memcpy(rc4key, mp->b_rptr + hdrlen, IEEE80211_WEP_IVLEN);
286	(void) memcpy(rc4key + IEEE80211_WEP_IVLEN, key->wk_key,
287	    key->wk_keylen);
288
289	ctx = NULL;
290	rv = rc4_init(&ctx, (const uint8_t *)rc4key,
291	    IEEE80211_WEP_IVLEN + key->wk_keylen);
292
293	if (rv != CRYPTO_SUCCESS)
294		return (0);
295
296	/* decrypt data */
297	(void) rc4_crypt(ctx,
298	    mp->b_rptr + hdrlen + wep.ic_header,
299	    mp->b_rptr + hdrlen + wep.ic_header,
300	    MBLKL(mp) -
301	    (hdrlen + wep.ic_header + wep.ic_trailer));
302
303	/* calculate CRC over unencrypted data */
304	CRC32(crc, mp->b_rptr + hdrlen + wep.ic_header,
305	    MBLKL(mp) -
306	    (hdrlen + wep.ic_header + wep.ic_trailer),
307	    -1U, crc_table);
308
309	/* decrypt ICV and compare to CRC */
310	icv = mp->b_wptr - IEEE80211_WEP_CRCLEN;
311	(void) rc4_crypt(ctx, icv, crcbuf, IEEE80211_WEP_CRCLEN);
312
313	(void) rc4_final(ctx, crcbuf, IEEE80211_WEP_CRCLEN);
314
315	return (crc == ~LE_32(*(uint32_t *)crcbuf));
316}
317
318/*
319 * rc_init() -  To init the key, for multiply encryption/decryption
320 * Using the Kernel encryption framework
321 */
322int
323rc4_init(crypto_context_t *ctx, const uint8_t *key, int keylen)
324{
325	crypto_mechanism_t mech;
326	crypto_key_t crkey;
327	int rv;
328
329	bzero(&crkey, sizeof (crkey));
330
331	crkey.ck_format = CRYPTO_KEY_RAW;
332	crkey.ck_data   = (char *)key;
333	/* keys are measured in bits, not bytes, so multiply by 8 */
334	crkey.ck_length = keylen * 8;
335
336	mech.cm_type	  = crypto_mech2id(SUN_CKM_RC4);
337	mech.cm_param	  = NULL;
338	mech.cm_param_len = 0;
339
340	rv = crypto_encrypt_init(&mech, &crkey, NULL, ctx, NULL);
341	if (rv != CRYPTO_SUCCESS)
342		cmn_err(CE_WARN, "rc4_init failed (%x)", rv);
343
344	return (rv);
345}
346
347/*
348 * rc4_crypt
349 *
350 * Use the Kernel encryption framework to provide the
351 * crypto operations for the indicated data.
352 */
353int
354rc4_crypt(crypto_context_t ctx, const uint8_t *inbuf,
355	uint8_t *outbuf, int buflen)
356{
357	int rv = CRYPTO_FAILED;
358
359	crypto_data_t d1, d2;
360
361	ASSERT(inbuf  != NULL);
362	ASSERT(outbuf != NULL);
363
364	bzero(&d1, sizeof (d1));
365	bzero(&d2, sizeof (d2));
366
367	d1.cd_format = CRYPTO_DATA_RAW;
368	d1.cd_offset = 0;
369	d1.cd_length = buflen;
370	d1.cd_raw.iov_base = (char *)inbuf;
371	d1.cd_raw.iov_len  = buflen;
372
373	d2.cd_format = CRYPTO_DATA_RAW;
374	d2.cd_offset = 0;
375	d2.cd_length = buflen;
376	d2.cd_raw.iov_base = (char *)outbuf;
377	d2.cd_raw.iov_len  = buflen;
378
379	rv = crypto_encrypt_update(ctx, &d1, &d2, NULL);
380
381	if (rv != CRYPTO_SUCCESS)
382		cmn_err(CE_WARN, "rc4_crypt failed (%x)", rv);
383	return (rv);
384}
385
386/*
387 * rc4_final
388 *
389 * Use the Kernel encryption framework to provide the
390 * crypto operations for the indicated data.
391 */
392int
393rc4_final(crypto_context_t ctx, uint8_t *outbuf, int buflen)
394{
395	int rv = CRYPTO_FAILED;
396
397	crypto_data_t d2;
398
399	ASSERT(outbuf != NULL);
400
401	bzero(&d2, sizeof (d2));
402
403	d2.cd_format = CRYPTO_DATA_RAW;
404	d2.cd_offset = 0;
405	d2.cd_length = buflen;
406	d2.cd_raw.iov_base = (char *)outbuf;
407	d2.cd_raw.iov_len = buflen;
408
409	rv = crypto_encrypt_final(ctx, &d2, NULL);
410
411	if (rv != CRYPTO_SUCCESS)
412		cmn_err(CE_WARN, "rc4_final failed (%x)", rv);
413	return (rv);
414}
415