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 $ */
6 * Copyright (c) 2000 The NetBSD Foundation, Inc.
9 * This code is derived from software contributed to The NetBSD Foundation
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
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>
58 #include <sys/malloc.h>
60 #include <sys/socket.h>
61 #include <sys/errno.h>
62 #include <sys/sockio.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>
84 return sizeof(struct rc4_state
);
88 arc4_setkey(void *ctx
, u_int8_t
*key
, int keylen
)
90 rc4_init(ctx
, key
, keylen
);
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
[] = {
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
)
126 u_int8_t keybuf
[AWI_MAX_KEYLEN
];
128 if (nwkey
->i_defkid
<= 0 ||
129 nwkey
->i_defkid
> IEEE80211_WEP_NKID
)
132 for (i
= 0; i
< IEEE80211_WEP_NKID
; i
++) {
133 if (nwkey
->i_key
[i
].i_keydat
== NULL
)
135 len
= nwkey
->i_key
[i
].i_keylen
;
136 if (len
> sizeof(keybuf
)) {
140 error
= copyin(nwkey
->i_key
[i
].i_keydat
, keybuf
, len
);
143 error
= awi_wep_setkey(sc
, i
, keybuf
, len
);
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
) {
152 error
= awi_init(sc
);
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 */
169 for (i
= 0; i
< IEEE80211_WEP_NKID
; i
++) {
170 if (nwkey
->i_key
[i
].i_keydat
== NULL
)
176 len
= sizeof(keybuf
);
177 error
= awi_wep_getkey(sc
, i
, keybuf
, &len
);
180 if (nwkey
->i_key
[i
].i_keylen
< len
) {
184 nwkey
->i_key
[i
].i_keylen
= len
;
185 error
= copyout(keybuf
, nwkey
->i_key
[i
].i_keydat
, len
);
193 awi_wep_getalgo(struct awi_softc
*sc
)
196 if (sc
->sc_wep_algo
== NULL
)
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
;
207 awi_crc_init(); /* XXX: not belongs here */
208 if (algo
< 0 || algo
> sizeof(awi_wep_algo
)/sizeof(awi_wep_algo
[0]))
210 awa
= &awi_wep_algo
[algo
];
211 if (awa
->awa_name
== NULL
)
213 if (awa
->awa_ctxlen
== NULL
) {
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
;
223 sc
->sc_wep_ctx
= kmalloc(ctxlen
, M_DEVBUF
, M_INTWAIT
);
224 if (sc
->sc_wep_ctx
== NULL
)
227 sc
->sc_wep_algo
= awa
;
232 awi_wep_setkey(struct awi_softc
*sc
, int kid
, unsigned char *key
, int keylen
)
235 if (kid
< 0 || kid
>= IEEE80211_WEP_NKID
)
237 if (keylen
< 0 || keylen
+ IEEE80211_WEP_IVLEN
> AWI_MAX_KEYLEN
)
239 sc
->sc_wep_keylen
[kid
] = keylen
;
241 memcpy(sc
->sc_wep_key
[kid
] + IEEE80211_WEP_IVLEN
, key
, keylen
);
246 awi_wep_getkey(struct awi_softc
*sc
, int kid
, unsigned char *key
, int *keylen
)
249 if (kid
< 0 || kid
>= IEEE80211_WEP_NKID
)
251 if (*keylen
< sc
->sc_wep_keylen
[kid
])
253 *keylen
= sc
->sc_wep_keylen
[kid
];
255 memcpy(key
, sc
->sc_wep_key
[kid
] + IEEE80211_WEP_IVLEN
, *keylen
);
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
;
269 u_int8_t crcbuf
[IEEE80211_WEP_CRCLEN
];
272 awa
= sc
->sc_wep_algo
;
275 ctx
= sc
->sc_wep_ctx
;
277 left
= m
->m_pkthdr
.len
;
279 len
= IEEE80211_WEP_IVLEN
+ IEEE80211_WEP_KIDLEN
+ IEEE80211_WEP_CRCLEN
;
281 plen
= m
->m_pkthdr
.len
+ len
;
283 plen
= m
->m_pkthdr
.len
- len
;
286 n0
= n
= m_getl(plen
, MB_DONTWAIT
, m
->m_type
, M_PKTHDR
, &msize
);
290 n
->m_pkthdr
.len
= plen
;
292 len
= sizeof(struct ieee80211_frame
);
294 memcpy(mtod(n
, caddr_t
), mtod(m
, caddr_t
), len
);
299 kid
= sc
->sc_wep_defkid
;
300 wh
= mtod(n
, struct ieee80211_frame
*);
301 wh
->i_fc
[1] |= IEEE80211_FC1_WEP
;
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;
311 ivp
[3] = kid
& 0x03; /* clear pad and keyid */
312 noff
+= IEEE80211_WEP_IVLEN
+ IEEE80211_WEP_KIDLEN
;
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 */
324 awa
->awa_setkey(ctx
, key
, IEEE80211_WEP_IVLEN
+ keylen
);
326 /* encrypt with calculating CRC */
329 len
= m
->m_len
- moff
;
335 if (len
> n
->m_len
- noff
) {
336 len
= n
->m_len
- noff
;
338 n
->m_next
= m_getl(left
, MB_DONTWAIT
,
339 n
->m_type
, 0, &msize
);
340 if (n
->m_next
== NULL
)
342 n
->m_next
->m_len
= msize
;
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
);
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
);
365 LE_WRITE_4(crcbuf
, crc
);
366 if (n
->m_len
>= noff
+ sizeof(crcbuf
))
367 n
->m_len
= noff
+ sizeof(crcbuf
);
370 MGET(n
->m_next
, MB_DONTWAIT
, n
->m_type
);
371 if (n
->m_next
== NULL
)
374 n
->m_len
= sizeof(crcbuf
);
377 awa
->awa_encrypt(ctx
, mtod(n
, caddr_t
) + noff
, crcbuf
,
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
;
386 awa
->awa_decrypt(ctx
, crcbuf
+ noff
,
387 mtod(m
, caddr_t
) + moff
, len
);
391 if (crc
!= LE_READ_4(crcbuf
))
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. */
418 if (awi_crc_table_computed
)
420 for (n
= 0; n
< 256; n
++) {
422 for (k
= 0; k
< 8; k
++) {
424 c
= 0xedb88320UL
^ (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
440 awi_crc_update(u_int32_t crc
, u_int8_t
*buf
, int len
)
444 for (endbuf
= buf
+ len
; buf
< endbuf
; buf
++)
445 crc
= awi_crc_table
[(crc
^ *buf
) & 0xff] ^ (crc
>> 8);
450 * Null -- do nothing but copy.
454 awi_null_ctxlen(void)
461 awi_null_setkey(void *ctx
, u_char
*key
, int keylen
)
466 awi_null_copy(void *ctx
, u_char
*dst
, u_char
*src
, int len
)
469 memcpy(dst
, src
, len
);