1 /* $NetBSD: awi_wep.c,v 1.4 2000/08/14 11:28:03 onoe Exp $ */
5 * Copyright (c) 2000 The NetBSD Foundation, Inc.
8 * This code is derived from software contributed to The NetBSD Foundation
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
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. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by the NetBSD
22 * Foundation, Inc. and its contributors.
23 * 4. Neither the name of The NetBSD Foundation nor the names of its
24 * contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGE.
41 * WEP support framework for the awi driver.
43 * No actual encryption capability is provided here, but any can be added
44 * to awi_wep_algo table below.
46 * Note that IEEE802.11 specification states WEP uses RC4 with 40bit key,
47 * which is a proprietary encryption algorithm available under license
48 * from RSA Data Security Inc. Using another algorithm, includes null
49 * encryption provided here, the awi driver cannot be able to communicate
50 * with other stations.
53 #include <sys/param.h>
54 #include <sys/systm.h>
55 #include <sys/kernel.h>
58 #include <sys/malloc.h>
59 #include <sys/socket.h>
60 #include <sys/errno.h>
61 #include <sys/sockio.h>
62 #if defined(__FreeBSD__) && __FreeBSD_version >= 400000
65 #include <sys/device.h>
69 #include <net/if_dl.h>
71 #include <net/ethernet.h>
72 #include <net/if_arp.h>
74 #include <net/if_ether.h>
76 #include <net/if_media.h>
77 #include <net/if_ieee80211.h>
79 #include <machine/cpu.h>
80 #include <machine/bus.h>
85 #include <dev/ic/am79c930reg.h>
86 #include <dev/ic/am79c930var.h>
87 #include <dev/ic/awireg.h>
88 #include <dev/ic/awivar.h>
90 #include <crypto/arc4/arc4.h>
94 #include <dev/awi/am79c930reg.h>
95 #include <dev/awi/am79c930var.h>
96 #include <dev/awi/awireg.h>
97 #include <dev/awi/awivar.h>
99 #include <crypto/rc4/rc4.h>
103 return sizeof(struct rc4_state);
107 arc4_setkey(void *ctx, u_int8_t *key, int keylen)
109 rc4_init(ctx, key, keylen);
113 arc4_encrypt(void *ctx, u_int8_t *dst, u_int8_t *src, int len)
115 rc4_crypt(ctx, src, dst, len);
119 static void awi_crc_init(void);
120 static u_int32_t awi_crc_update(u_int32_t crc, u_int8_t *buf, int len);
122 static int awi_null_ctxlen(void);
123 static void awi_null_setkey(void *ctx, u_int8_t *key, int keylen);
124 static void awi_null_copy(void *ctx, u_int8_t *dst, u_int8_t *src, int len);
126 /* XXX: the order should be known to wiconfig/user */
128 static struct awi_wep_algo awi_wep_algo[] = {
130 { "no" }, /* dummy for no wep */
132 /* 1: normal wep (arc4) */
133 { "arc4", arc4_ctxlen, arc4_setkey,
134 arc4_encrypt, arc4_encrypt },
136 /* 2: debug wep (null) */
137 { "null", awi_null_ctxlen, awi_null_setkey,
138 awi_null_copy, awi_null_copy },
139 /* dummy for wep without encryption */
143 awi_wep_setnwkey(sc, nwkey)
144 struct awi_softc *sc;
145 struct ieee80211_nwkey *nwkey;
148 u_int8_t keybuf[AWI_MAX_KEYLEN];
150 if (nwkey->i_defkid <= 0 ||
151 nwkey->i_defkid > IEEE80211_WEP_NKID)
154 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
155 if (nwkey->i_key[i].i_keydat == NULL)
157 len = nwkey->i_key[i].i_keylen;
158 if (len > sizeof(keybuf)) {
162 error = copyin(nwkey->i_key[i].i_keydat, keybuf, len);
165 error = awi_wep_setkey(sc, i, keybuf, len);
170 sc->sc_wep_defkid = nwkey->i_defkid - 1;
171 error = awi_wep_setalgo(sc, nwkey->i_wepon);
172 if (error == 0 && sc->sc_enabled) {
174 error = awi_init(sc);
181 awi_wep_getnwkey(sc, nwkey)
182 struct awi_softc *sc;
183 struct ieee80211_nwkey *nwkey;
185 int i, len, error, suerr;
186 u_int8_t keybuf[AWI_MAX_KEYLEN];
188 nwkey->i_wepon = awi_wep_getalgo(sc);
189 nwkey->i_defkid = sc->sc_wep_defkid + 1;
190 /* do not show any keys to non-root user */
192 #if __FreeBSD_version < 500028
193 suerr = suser(curproc);
195 suerr = suser(curthread);
198 suerr = suser(curproc->p_ucred, &curproc->p_acflag);
201 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
202 if (nwkey->i_key[i].i_keydat == NULL)
208 len = sizeof(keybuf);
209 error = awi_wep_getkey(sc, i, keybuf, &len);
212 if (nwkey->i_key[i].i_keylen < len) {
216 nwkey->i_key[i].i_keylen = len;
217 error = copyout(keybuf, nwkey->i_key[i].i_keydat, len);
226 struct awi_softc *sc;
229 if (sc->sc_wep_algo == NULL)
231 return sc->sc_wep_algo - awi_wep_algo;
235 awi_wep_setalgo(sc, algo)
236 struct awi_softc *sc;
239 struct awi_wep_algo *awa;
242 awi_crc_init(); /* XXX: not belongs here */
243 if (algo < 0 || algo > sizeof(awi_wep_algo)/sizeof(awi_wep_algo[0]))
245 awa = &awi_wep_algo[algo];
246 if (awa->awa_name == NULL)
248 if (awa->awa_ctxlen == NULL) {
252 ctxlen = awa->awa_ctxlen();
253 if (sc->sc_wep_ctx != NULL) {
254 free(sc->sc_wep_ctx, M_DEVBUF);
255 sc->sc_wep_ctx = NULL;
258 sc->sc_wep_ctx = malloc(ctxlen, M_DEVBUF, M_NOWAIT);
259 if (sc->sc_wep_ctx == NULL)
262 sc->sc_wep_algo = awa;
267 awi_wep_setkey(sc, kid, key, keylen)
268 struct awi_softc *sc;
274 if (kid < 0 || kid >= IEEE80211_WEP_NKID)
276 if (keylen < 0 || keylen + IEEE80211_WEP_IVLEN > AWI_MAX_KEYLEN)
278 sc->sc_wep_keylen[kid] = keylen;
280 memcpy(sc->sc_wep_key[kid] + IEEE80211_WEP_IVLEN, key, keylen);
285 awi_wep_getkey(sc, kid, key, keylen)
286 struct awi_softc *sc;
292 if (kid < 0 || kid >= IEEE80211_WEP_NKID)
294 if (*keylen < sc->sc_wep_keylen[kid])
296 *keylen = sc->sc_wep_keylen[kid];
298 memcpy(key, sc->sc_wep_key[kid] + IEEE80211_WEP_IVLEN, *keylen);
303 awi_wep_encrypt(sc, m0, txflag)
304 struct awi_softc *sc;
308 struct mbuf *m, *n, *n0;
309 struct ieee80211_frame *wh;
310 struct awi_wep_algo *awa;
311 int left, len, moff, noff, keylen, kid;
315 u_int8_t crcbuf[IEEE80211_WEP_CRCLEN];
318 awa = sc->sc_wep_algo;
321 ctx = sc->sc_wep_ctx;
323 left = m->m_pkthdr.len;
324 MGET(n, M_DONTWAIT, m->m_type);
329 len = IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN + IEEE80211_WEP_CRCLEN;
331 n->m_pkthdr.len += len;
333 n->m_pkthdr.len -= len;
337 if (n->m_pkthdr.len >= MINCLSIZE) {
338 MCLGET(n, M_DONTWAIT);
339 if (n->m_flags & M_EXT)
340 n->m_len = n->m_ext.ext_size;
342 len = sizeof(struct ieee80211_frame);
343 memcpy(mtod(n, caddr_t), mtod(m, caddr_t), len);
348 kid = sc->sc_wep_defkid;
349 wh = mtod(n, struct ieee80211_frame *);
350 wh->i_fc[1] |= IEEE80211_FC1_WEP;
353 * store IV, byte order is not the matter since it's random.
354 * assuming IEEE80211_WEP_IVLEN is 3
356 ivp = mtod(n, u_int8_t *) + noff;
357 ivp[0] = (iv >> 16) & 0xff;
358 ivp[1] = (iv >> 8) & 0xff;
360 ivp[IEEE80211_WEP_IVLEN] = kid << 6; /* pad and keyid */
361 noff += IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN;
363 ivp = mtod(m, u_int8_t *) + moff;
364 kid = ivp[IEEE80211_WEP_IVLEN] >> 6;
365 moff += IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN;
367 key = sc->sc_wep_key[kid];
368 keylen = sc->sc_wep_keylen[kid];
369 /* assuming IEEE80211_WEP_IVLEN is 3 */
373 awa->awa_setkey(ctx, key, IEEE80211_WEP_IVLEN + keylen);
375 /* encrypt with calculating CRC */
378 len = m->m_len - moff;
384 if (len > n->m_len - noff) {
385 len = n->m_len - noff;
387 MGET(n->m_next, M_DONTWAIT, n->m_type);
388 if (n->m_next == NULL)
392 if (left >= MINCLSIZE) {
393 MCLGET(n, M_DONTWAIT);
394 if (n->m_flags & M_EXT)
395 n->m_len = n->m_ext.ext_size;
404 awa->awa_encrypt(ctx, mtod(n, caddr_t) + noff,
405 mtod(m, caddr_t) + moff, len);
406 crc = awi_crc_update(crc, mtod(m, caddr_t) + moff, len);
408 awa->awa_decrypt(ctx, mtod(n, caddr_t) + noff,
409 mtod(m, caddr_t) + moff, len);
410 crc = awi_crc_update(crc, mtod(n, caddr_t) + noff, len);
418 LE_WRITE_4(crcbuf, crc);
419 if (n->m_len >= noff + sizeof(crcbuf))
420 n->m_len = noff + sizeof(crcbuf);
423 MGET(n->m_next, M_DONTWAIT, n->m_type);
424 if (n->m_next == NULL)
427 n->m_len = sizeof(crcbuf);
430 awa->awa_encrypt(ctx, mtod(n, caddr_t) + noff, crcbuf,
434 for (noff = 0; noff < sizeof(crcbuf); noff += len) {
435 len = sizeof(crcbuf) - noff;
436 if (len > m->m_len - moff)
437 len = m->m_len - moff;
439 awa->awa_decrypt(ctx, crcbuf + noff,
440 mtod(m, caddr_t) + moff, len);
444 if (crc != LE_READ_4(crcbuf))
457 * CRC 32 -- routine from RFC 2083
460 /* Table of CRCs of all 8-bit messages */
461 static u_int32_t awi_crc_table[256];
462 static int awi_crc_table_computed = 0;
464 /* Make the table for a fast CRC. */
471 if (awi_crc_table_computed)
473 for (n = 0; n < 256; n++) {
475 for (k = 0; k < 8; k++) {
477 c = 0xedb88320UL ^ (c >> 1);
481 awi_crc_table[n] = c;
483 awi_crc_table_computed = 1;
487 * Update a running CRC with the bytes buf[0..len-1]--the CRC
488 * should be initialized to all 1's, and the transmitted value
489 * is the 1's complement of the final running CRC
493 awi_crc_update(crc, buf, len)
500 for (endbuf = buf + len; buf < endbuf; buf++)
501 crc = awi_crc_table[(crc ^ *buf) & 0xff] ^ (crc >> 8);
506 * Null -- do nothing but copy.
517 awi_null_setkey(ctx, key, keylen)
525 awi_null_copy(ctx, dst, src, len)
532 memcpy(dst, src, len);