Short manpage for ubt(4). Most of it is commented out for now because sco
[dragonfly.git] / sys / dev / netif / awi / awi_wep.c
bloba53b64741e3d025dff2dc88c3235964d61d162d9
1 /* $NetBSD: awi_wep.c,v 1.4 2000/08/14 11:28:03 onoe Exp $ */
2 /* $FreeBSD: src/sys/dev/awi/awi_wep.c,v 1.3.2.2 2003/01/23 21:06:42 sam Exp $ */
3 /* $DragonFly: src/sys/dev/netif/awi/Attic/awi_wep.c,v 1.17 2006/10/25 20:55:56 dillon Exp $ */
5 /*
6 * Copyright (c) 2000 The NetBSD Foundation, Inc.
7 * All rights reserved.
9 * This code is derived from software contributed to The NetBSD Foundation
10 * by Atsushi Onoe.
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. All advertising materials mentioning features or use of this software
21 * must display the following acknowledgement:
22 * This product includes software developed by the NetBSD
23 * Foundation, Inc. and its contributors.
24 * 4. Neither the name of The NetBSD Foundation nor the names of its
25 * contributors may be used to endorse or promote products derived
26 * from this software without specific prior written permission.
28 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
29 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
31 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
32 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
42 * WEP support framework for the awi driver.
44 * No actual encryption capability is provided here, but any can be added
45 * to awi_wep_algo table below.
47 * Note that IEEE802.11 specification states WEP uses RC4 with 40bit key,
48 * which is a proprietary encryption algorithm available under license
49 * from RSA Data Security Inc. Using another algorithm, includes null
50 * encryption provided here, the awi driver cannot be able to communicate
51 * with other stations.
54 #include <sys/param.h>
55 #include <sys/systm.h>
56 #include <sys/kernel.h>
57 #include <sys/mbuf.h>
58 #include <sys/malloc.h>
59 #include <sys/proc.h>
60 #include <sys/socket.h>
61 #include <sys/errno.h>
62 #include <sys/sockio.h>
63 #include <sys/bus.h>
65 #include <net/if.h>
66 #include <net/if_dl.h>
67 #include <net/ethernet.h>
68 #include <net/if_arp.h>
69 #include <net/if_media.h>
70 #include <netproto/802_11/ieee80211.h>
71 #include <netproto/802_11/ieee80211_ioctl.h>
73 #include <machine/cpu.h>
75 #include <dev/netif/awi/am79c930reg.h>
76 #include <dev/netif/awi/am79c930var.h>
77 #include <dev/netif/awi/awireg.h>
78 #include <dev/netif/awi/awivar.h>
80 #include <crypto/rc4/rc4.h>
81 static __inline int
82 arc4_ctxlen(void)
84 return sizeof(struct rc4_state);
87 static __inline void
88 arc4_setkey(void *ctx, u_int8_t *key, int keylen)
90 rc4_init(ctx, key, keylen);
93 static __inline void
94 arc4_encrypt(void *ctx, u_int8_t *dst, u_int8_t *src, int len)
96 rc4_crypt(ctx, src, dst, len);
99 static void awi_crc_init (void);
100 static u_int32_t awi_crc_update (u_int32_t crc, u_int8_t *buf, int len);
102 static int awi_null_ctxlen (void);
103 static void awi_null_setkey (void *ctx, u_int8_t *key, int keylen);
104 static void awi_null_copy (void *ctx, u_int8_t *dst, u_int8_t *src, int len);
106 /* XXX: the order should be known to wiconfig/user */
108 static struct awi_wep_algo awi_wep_algo[] = {
109 /* 0: no wep */
110 { "no" }, /* dummy for no wep */
112 /* 1: normal wep (arc4) */
113 { "arc4", arc4_ctxlen, arc4_setkey,
114 arc4_encrypt, arc4_encrypt },
116 /* 2: debug wep (null) */
117 { "null", awi_null_ctxlen, awi_null_setkey,
118 awi_null_copy, awi_null_copy },
119 /* dummy for wep without encryption */
123 awi_wep_setnwkey(struct awi_softc *sc, struct ieee80211_nwkey *nwkey)
125 int i, len, error;
126 u_int8_t keybuf[AWI_MAX_KEYLEN];
128 if (nwkey->i_defkid <= 0 ||
129 nwkey->i_defkid > IEEE80211_WEP_NKID)
130 return EINVAL;
131 error = 0;
132 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
133 if (nwkey->i_key[i].i_keydat == NULL)
134 continue;
135 len = nwkey->i_key[i].i_keylen;
136 if (len > sizeof(keybuf)) {
137 error = EINVAL;
138 break;
140 error = copyin(nwkey->i_key[i].i_keydat, keybuf, len);
141 if (error)
142 break;
143 error = awi_wep_setkey(sc, i, keybuf, len);
144 if (error)
145 break;
147 if (error == 0) {
148 sc->sc_wep_defkid = nwkey->i_defkid - 1;
149 error = awi_wep_setalgo(sc, nwkey->i_wepon);
150 if (error == 0 && sc->sc_enabled) {
151 awi_stop(sc);
152 error = awi_init(sc);
155 return error;
159 awi_wep_getnwkey(struct awi_softc *sc, struct ieee80211_nwkey *nwkey)
161 int i, len, error, suerr;
162 u_int8_t keybuf[AWI_MAX_KEYLEN];
164 nwkey->i_wepon = awi_wep_getalgo(sc);
165 nwkey->i_defkid = sc->sc_wep_defkid + 1;
166 /* do not show any keys to non-root user */
167 suerr = suser(curthread); /* note: EPERM if no proc */
168 error = 0;
169 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
170 if (nwkey->i_key[i].i_keydat == NULL)
171 continue;
172 if (suerr) {
173 error = suerr;
174 break;
176 len = sizeof(keybuf);
177 error = awi_wep_getkey(sc, i, keybuf, &len);
178 if (error)
179 break;
180 if (nwkey->i_key[i].i_keylen < len) {
181 error = ENOSPC;
182 break;
184 nwkey->i_key[i].i_keylen = len;
185 error = copyout(keybuf, nwkey->i_key[i].i_keydat, len);
186 if (error)
187 break;
189 return error;
193 awi_wep_getalgo(struct awi_softc *sc)
196 if (sc->sc_wep_algo == NULL)
197 return 0;
198 return sc->sc_wep_algo - awi_wep_algo;
202 awi_wep_setalgo(struct awi_softc *sc, int algo)
204 struct awi_wep_algo *awa;
205 int ctxlen;
207 awi_crc_init(); /* XXX: not belongs here */
208 if (algo < 0 || algo > sizeof(awi_wep_algo)/sizeof(awi_wep_algo[0]))
209 return EINVAL;
210 awa = &awi_wep_algo[algo];
211 if (awa->awa_name == NULL)
212 return EINVAL;
213 if (awa->awa_ctxlen == NULL) {
214 awa = NULL;
215 ctxlen = 0;
216 } else
217 ctxlen = awa->awa_ctxlen();
218 if (sc->sc_wep_ctx != NULL) {
219 kfree(sc->sc_wep_ctx, M_DEVBUF);
220 sc->sc_wep_ctx = NULL;
222 if (ctxlen) {
223 sc->sc_wep_ctx = kmalloc(ctxlen, M_DEVBUF, M_INTWAIT);
224 if (sc->sc_wep_ctx == NULL)
225 return ENOMEM;
227 sc->sc_wep_algo = awa;
228 return 0;
232 awi_wep_setkey(struct awi_softc *sc, int kid, unsigned char *key, int keylen)
235 if (kid < 0 || kid >= IEEE80211_WEP_NKID)
236 return EINVAL;
237 if (keylen < 0 || keylen + IEEE80211_WEP_IVLEN > AWI_MAX_KEYLEN)
238 return EINVAL;
239 sc->sc_wep_keylen[kid] = keylen;
240 if (keylen > 0)
241 memcpy(sc->sc_wep_key[kid] + IEEE80211_WEP_IVLEN, key, keylen);
242 return 0;
246 awi_wep_getkey(struct awi_softc *sc, int kid, unsigned char *key, int *keylen)
249 if (kid < 0 || kid >= IEEE80211_WEP_NKID)
250 return EINVAL;
251 if (*keylen < sc->sc_wep_keylen[kid])
252 return ENOSPC;
253 *keylen = sc->sc_wep_keylen[kid];
254 if (*keylen > 0)
255 memcpy(key, sc->sc_wep_key[kid] + IEEE80211_WEP_IVLEN, *keylen);
256 return 0;
259 struct mbuf *
260 awi_wep_encrypt(struct awi_softc *sc, struct mbuf *m0, int txflag)
262 struct mbuf *m, *n, *n0;
263 struct ieee80211_frame *wh;
264 struct awi_wep_algo *awa;
265 int left, len, plen, msize, moff, noff, keylen, kid;
266 u_int32_t iv, crc;
267 u_int8_t *key, *ivp;
268 void *ctx;
269 u_int8_t crcbuf[IEEE80211_WEP_CRCLEN];
271 n0 = NULL;
272 awa = sc->sc_wep_algo;
273 if (awa == NULL)
274 goto fail;
275 ctx = sc->sc_wep_ctx;
276 m = m0;
277 left = m->m_pkthdr.len;
279 len = IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN + IEEE80211_WEP_CRCLEN;
280 if (txflag) {
281 plen = m->m_pkthdr.len + len;
282 } else {
283 plen = m->m_pkthdr.len - len;
284 left -= len;
286 n0 = n = m_getl(plen, MB_DONTWAIT, m->m_type, M_PKTHDR, &msize);
287 if (n == NULL)
288 goto fail;
289 n->m_len = msize;
290 n->m_pkthdr.len = plen;
291 M_MOVE_PKTHDR(n, m);
292 len = sizeof(struct ieee80211_frame);
294 memcpy(mtod(n, caddr_t), mtod(m, caddr_t), len);
295 left -= len;
296 moff = len;
297 noff = len;
298 if (txflag) {
299 kid = sc->sc_wep_defkid;
300 wh = mtod(n, struct ieee80211_frame *);
301 wh->i_fc[1] |= IEEE80211_FC1_WEP;
302 iv = krandom();
304 * store IV, byte order is not the matter since it's random.
305 * assuming IEEE80211_WEP_IVLEN is 3
307 ivp = mtod(n, u_int8_t *) + noff;
308 ivp[0] = (iv >> 16) & 0xff;
309 ivp[1] = (iv >> 8) & 0xff;
310 ivp[2] = iv & 0xff;
311 ivp[3] = kid & 0x03; /* clear pad and keyid */
312 noff += IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN;
313 } else {
314 ivp = mtod(m, u_int8_t *) + moff;
315 moff += IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN;
316 kid = ivp[IEEE80211_WEP_IVLEN] & 0x03;
318 key = sc->sc_wep_key[kid];
319 keylen = sc->sc_wep_keylen[kid];
320 /* assuming IEEE80211_WEP_IVLEN is 3 */
321 key[0] = ivp[0];
322 key[1] = ivp[1];
323 key[2] = ivp[2];
324 awa->awa_setkey(ctx, key, IEEE80211_WEP_IVLEN + keylen);
326 /* encrypt with calculating CRC */
327 crc = ~0;
328 while (left > 0) {
329 len = m->m_len - moff;
330 if (len == 0) {
331 m = m->m_next;
332 moff = 0;
333 continue;
335 if (len > n->m_len - noff) {
336 len = n->m_len - noff;
337 if (len == 0) {
338 n->m_next = m_getl(left, MB_DONTWAIT,
339 n->m_type, 0, &msize);
340 if (n->m_next == NULL)
341 goto fail;
342 n->m_next->m_len = msize;
343 n = n->m_next;
344 noff = 0;
345 continue;
348 if (len > left)
349 len = left;
350 if (txflag) {
351 awa->awa_encrypt(ctx, mtod(n, caddr_t) + noff,
352 mtod(m, caddr_t) + moff, len);
353 crc = awi_crc_update(crc, mtod(m, caddr_t) + moff, len);
354 } else {
355 awa->awa_decrypt(ctx, mtod(n, caddr_t) + noff,
356 mtod(m, caddr_t) + moff, len);
357 crc = awi_crc_update(crc, mtod(n, caddr_t) + noff, len);
359 left -= len;
360 moff += len;
361 noff += len;
363 crc = ~crc;
364 if (txflag) {
365 LE_WRITE_4(crcbuf, crc);
366 if (n->m_len >= noff + sizeof(crcbuf))
367 n->m_len = noff + sizeof(crcbuf);
368 else {
369 n->m_len = noff;
370 MGET(n->m_next, MB_DONTWAIT, n->m_type);
371 if (n->m_next == NULL)
372 goto fail;
373 n = n->m_next;
374 n->m_len = sizeof(crcbuf);
375 noff = 0;
377 awa->awa_encrypt(ctx, mtod(n, caddr_t) + noff, crcbuf,
378 sizeof(crcbuf));
379 } else {
380 n->m_len = noff;
381 for (noff = 0; noff < sizeof(crcbuf); noff += len) {
382 len = sizeof(crcbuf) - noff;
383 if (len > m->m_len - moff)
384 len = m->m_len - moff;
385 if (len > 0)
386 awa->awa_decrypt(ctx, crcbuf + noff,
387 mtod(m, caddr_t) + moff, len);
388 m = m->m_next;
389 moff = 0;
391 if (crc != LE_READ_4(crcbuf))
392 goto fail;
394 m_freem(m0);
395 return n0;
397 fail:
398 m_freem(m0);
399 m_freem(n0);
400 return NULL;
404 * CRC 32 -- routine from RFC 2083
407 /* Table of CRCs of all 8-bit messages */
408 static u_int32_t awi_crc_table[256];
409 static int awi_crc_table_computed = 0;
411 /* Make the table for a fast CRC. */
412 static void
413 awi_crc_init(void)
415 u_int32_t c;
416 int n, k;
418 if (awi_crc_table_computed)
419 return;
420 for (n = 0; n < 256; n++) {
421 c = (u_int32_t)n;
422 for (k = 0; k < 8; k++) {
423 if (c & 1)
424 c = 0xedb88320UL ^ (c >> 1);
425 else
426 c = c >> 1;
428 awi_crc_table[n] = c;
430 awi_crc_table_computed = 1;
434 * Update a running CRC with the bytes buf[0..len-1]--the CRC
435 * should be initialized to all 1's, and the transmitted value
436 * is the 1's complement of the final running CRC
439 static u_int32_t
440 awi_crc_update(u_int32_t crc, u_int8_t *buf, int len)
442 u_int8_t *endbuf;
444 for (endbuf = buf + len; buf < endbuf; buf++)
445 crc = awi_crc_table[(crc ^ *buf) & 0xff] ^ (crc >> 8);
446 return crc;
450 * Null -- do nothing but copy.
453 static int
454 awi_null_ctxlen(void)
457 return 0;
460 static void
461 awi_null_setkey(void *ctx, u_char *key, int keylen)
465 static void
466 awi_null_copy(void *ctx, u_char *dst, u_char *src, int len)
469 memcpy(dst, src, len);