source: rtems-libbsd/freebsd/sys/net80211/ieee80211_crypto_wep.c @ f244de9

4.1155-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since f244de9 was f244de9, checked in by Sebastian Huber <sebastian.huber@…>, on 11/06/13 at 07:56:38

Rename rtems-bsd-config.h

Rename rtems-bsd-config.h in rtems-bsd-kernel-space.h.

  • Property mode set to 100644
File size: 14.3 KB
Line 
1#include <machine/rtems-bsd-kernel-space.h>
2
3/*-
4 * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#include <sys/cdefs.h>
29__FBSDID("$FreeBSD$");
30
31/*
32 * IEEE 802.11 WEP crypto support.
33 */
34#include <rtems/bsd/local/opt_wlan.h>
35
36#include <rtems/bsd/sys/param.h>
37#include <sys/systm.h>
38#include <sys/mbuf.h>   
39#include <sys/malloc.h>
40#include <sys/kernel.h>
41#include <sys/module.h>
42#include <sys/endian.h>
43
44#include <sys/socket.h>
45
46#include <net/if.h>
47#include <net/if_media.h>
48#include <net/ethernet.h>
49
50#include <net80211/ieee80211_var.h>
51
52static  void *wep_attach(struct ieee80211vap *, struct ieee80211_key *);
53static  void wep_detach(struct ieee80211_key *);
54static  int wep_setkey(struct ieee80211_key *);
55static  int wep_encap(struct ieee80211_key *, struct mbuf *, uint8_t keyid);
56static  int wep_decap(struct ieee80211_key *, struct mbuf *, int hdrlen);
57static  int wep_enmic(struct ieee80211_key *, struct mbuf *, int);
58static  int wep_demic(struct ieee80211_key *, struct mbuf *, int);
59
60static const struct ieee80211_cipher wep = {
61        .ic_name        = "WEP",
62        .ic_cipher      = IEEE80211_CIPHER_WEP,
63        .ic_header      = IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN,
64        .ic_trailer     = IEEE80211_WEP_CRCLEN,
65        .ic_miclen      = 0,
66        .ic_attach      = wep_attach,
67        .ic_detach      = wep_detach,
68        .ic_setkey      = wep_setkey,
69        .ic_encap       = wep_encap,
70        .ic_decap       = wep_decap,
71        .ic_enmic       = wep_enmic,
72        .ic_demic       = wep_demic,
73};
74
75static  int wep_encrypt(struct ieee80211_key *, struct mbuf *, int hdrlen);
76static  int wep_decrypt(struct ieee80211_key *, struct mbuf *, int hdrlen);
77
78struct wep_ctx {
79        struct ieee80211vap *wc_vap;    /* for diagnostics+statistics */
80        struct ieee80211com *wc_ic;
81        uint32_t        wc_iv;          /* initial vector for crypto */
82};
83
84/* number of references from net80211 layer */
85static  int nrefs = 0;
86
87static void *
88wep_attach(struct ieee80211vap *vap, struct ieee80211_key *k)
89{
90        struct wep_ctx *ctx;
91
92        ctx = (struct wep_ctx *) malloc(sizeof(struct wep_ctx),
93                M_80211_CRYPTO, M_NOWAIT | M_ZERO);
94        if (ctx == NULL) {
95                vap->iv_stats.is_crypto_nomem++;
96                return NULL;
97        }
98
99        ctx->wc_vap = vap;
100        ctx->wc_ic = vap->iv_ic;
101        get_random_bytes(&ctx->wc_iv, sizeof(ctx->wc_iv));
102        nrefs++;                        /* NB: we assume caller locking */
103        return ctx;
104}
105
106static void
107wep_detach(struct ieee80211_key *k)
108{
109        struct wep_ctx *ctx = k->wk_private;
110
111        free(ctx, M_80211_CRYPTO);
112        KASSERT(nrefs > 0, ("imbalanced attach/detach"));
113        nrefs--;                        /* NB: we assume caller locking */
114}
115
116static int
117wep_setkey(struct ieee80211_key *k)
118{
119        return k->wk_keylen >= 40/NBBY;
120}
121
122/*
123 * Add privacy headers appropriate for the specified key.
124 */
125static int
126wep_encap(struct ieee80211_key *k, struct mbuf *m, uint8_t keyid)
127{
128        struct wep_ctx *ctx = k->wk_private;
129        struct ieee80211com *ic = ctx->wc_ic;
130        uint32_t iv;
131        uint8_t *ivp;
132        int hdrlen;
133
134        hdrlen = ieee80211_hdrspace(ic, mtod(m, void *));
135
136        /*
137         * Copy down 802.11 header and add the IV + KeyID.
138         */
139        M_PREPEND(m, wep.ic_header, M_NOWAIT);
140        if (m == NULL)
141                return 0;
142        ivp = mtod(m, uint8_t *);
143        ovbcopy(ivp + wep.ic_header, ivp, hdrlen);
144        ivp += hdrlen;
145
146        /*
147         * XXX
148         * IV must not duplicate during the lifetime of the key.
149         * But no mechanism to renew keys is defined in IEEE 802.11
150         * for WEP.  And the IV may be duplicated at other stations
151         * because the session key itself is shared.  So we use a
152         * pseudo random IV for now, though it is not the right way.
153         *
154         * NB: Rather than use a strictly random IV we select a
155         * random one to start and then increment the value for
156         * each frame.  This is an explicit tradeoff between
157         * overhead and security.  Given the basic insecurity of
158         * WEP this seems worthwhile.
159         */
160
161        /*
162         * Skip 'bad' IVs from Fluhrer/Mantin/Shamir:
163         * (B, 255, N) with 3 <= B < 16 and 0 <= N <= 255
164         */
165        iv = ctx->wc_iv;
166        if ((iv & 0xff00) == 0xff00) {
167                int B = (iv & 0xff0000) >> 16;
168                if (3 <= B && B < 16)
169                        iv += 0x0100;
170        }
171        ctx->wc_iv = iv + 1;
172
173        /*
174         * NB: Preserve byte order of IV for packet
175         *     sniffers; it doesn't matter otherwise.
176         */
177#if _BYTE_ORDER == _BIG_ENDIAN
178        ivp[0] = iv >> 0;
179        ivp[1] = iv >> 8;
180        ivp[2] = iv >> 16;
181#else
182        ivp[2] = iv >> 0;
183        ivp[1] = iv >> 8;
184        ivp[0] = iv >> 16;
185#endif
186        ivp[3] = keyid;
187
188        /*
189         * Finally, do software encrypt if neeed.
190         */
191        if ((k->wk_flags & IEEE80211_KEY_SWENCRYPT) &&
192            !wep_encrypt(k, m, hdrlen))
193                return 0;
194
195        return 1;
196}
197
198/*
199 * Add MIC to the frame as needed.
200 */
201static int
202wep_enmic(struct ieee80211_key *k, struct mbuf *m, int force)
203{
204
205        return 1;
206}
207
208/*
209 * Validate and strip privacy headers (and trailer) for a
210 * received frame.  If necessary, decrypt the frame using
211 * the specified key.
212 */
213static int
214wep_decap(struct ieee80211_key *k, struct mbuf *m, int hdrlen)
215{
216        struct wep_ctx *ctx = k->wk_private;
217        struct ieee80211vap *vap = ctx->wc_vap;
218        struct ieee80211_frame *wh;
219
220        wh = mtod(m, struct ieee80211_frame *);
221
222        /*
223         * Check if the device handled the decrypt in hardware.
224         * If so we just strip the header; otherwise we need to
225         * handle the decrypt in software.
226         */
227        if ((k->wk_flags & IEEE80211_KEY_SWDECRYPT) &&
228            !wep_decrypt(k, m, hdrlen)) {
229                IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO, wh->i_addr2,
230                    "%s", "WEP ICV mismatch on decrypt");
231                vap->iv_stats.is_rx_wepfail++;
232                return 0;
233        }
234
235        /*
236         * Copy up 802.11 header and strip crypto bits.
237         */
238        ovbcopy(mtod(m, void *), mtod(m, uint8_t *) + wep.ic_header, hdrlen);
239        m_adj(m, wep.ic_header);
240        m_adj(m, -wep.ic_trailer);
241
242        return 1;
243}
244
245/*
246 * Verify and strip MIC from the frame.
247 */
248static int
249wep_demic(struct ieee80211_key *k, struct mbuf *skb, int force)
250{
251        return 1;
252}
253
254static const uint32_t crc32_table[256] = {
255        0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
256        0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
257        0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
258        0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
259        0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
260        0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
261        0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
262        0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
263        0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
264        0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
265        0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
266        0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
267        0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
268        0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
269        0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
270        0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
271        0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
272        0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
273        0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
274        0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
275        0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
276        0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
277        0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
278        0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
279        0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
280        0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
281        0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
282        0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
283        0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
284        0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
285        0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
286        0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
287        0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
288        0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
289        0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
290        0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
291        0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
292        0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
293        0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
294        0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
295        0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
296        0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
297        0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
298        0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
299        0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
300        0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
301        0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
302        0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
303        0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
304        0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
305        0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
306        0x2d02ef8dL
307};
308
309static int
310wep_encrypt(struct ieee80211_key *key, struct mbuf *m0, int hdrlen)
311{
312#define S_SWAP(a,b) do { uint8_t t = S[a]; S[a] = S[b]; S[b] = t; } while(0)
313        struct wep_ctx *ctx = key->wk_private;
314        struct ieee80211vap *vap = ctx->wc_vap;
315        struct mbuf *m = m0;
316        uint8_t rc4key[IEEE80211_WEP_IVLEN + IEEE80211_KEYBUF_SIZE];
317        uint8_t icv[IEEE80211_WEP_CRCLEN];
318        uint32_t i, j, k, crc;
319        size_t buflen, data_len;
320        uint8_t S[256];
321        uint8_t *pos;
322        u_int off, keylen;
323
324        vap->iv_stats.is_crypto_wep++;
325
326        /* NB: this assumes the header was pulled up */
327        memcpy(rc4key, mtod(m, uint8_t *) + hdrlen, IEEE80211_WEP_IVLEN);
328        memcpy(rc4key + IEEE80211_WEP_IVLEN, key->wk_key, key->wk_keylen);
329
330        /* Setup RC4 state */
331        for (i = 0; i < 256; i++)
332                S[i] = i;
333        j = 0;
334        keylen = key->wk_keylen + IEEE80211_WEP_IVLEN;
335        for (i = 0; i < 256; i++) {
336                j = (j + S[i] + rc4key[i % keylen]) & 0xff;
337                S_SWAP(i, j);
338        }
339
340        off = hdrlen + wep.ic_header;
341        data_len = m->m_pkthdr.len - off;
342
343        /* Compute CRC32 over unencrypted data and apply RC4 to data */
344        crc = ~0;
345        i = j = 0;
346        pos = mtod(m, uint8_t *) + off;
347        buflen = m->m_len - off;
348        for (;;) {
349                if (buflen > data_len)
350                        buflen = data_len;
351                data_len -= buflen;
352                for (k = 0; k < buflen; k++) {
353                        crc = crc32_table[(crc ^ *pos) & 0xff] ^ (crc >> 8);
354                        i = (i + 1) & 0xff;
355                        j = (j + S[i]) & 0xff;
356                        S_SWAP(i, j);
357                        *pos++ ^= S[(S[i] + S[j]) & 0xff];
358                }
359                if (m->m_next == NULL) {
360                        if (data_len != 0) {            /* out of data */
361                                IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO,
362                                    ether_sprintf(mtod(m0,
363                                        struct ieee80211_frame *)->i_addr2),
364                                    "out of data for WEP (data_len %zu)",
365                                    data_len);
366                                /* XXX stat */
367                                return 0;
368                        }
369                        break;
370                }
371                m = m->m_next;
372                pos = mtod(m, uint8_t *);
373                buflen = m->m_len;
374        }
375        crc = ~crc;
376
377        /* Append little-endian CRC32 and encrypt it to produce ICV */
378        icv[0] = crc;
379        icv[1] = crc >> 8;
380        icv[2] = crc >> 16;
381        icv[3] = crc >> 24;
382        for (k = 0; k < IEEE80211_WEP_CRCLEN; k++) {
383                i = (i + 1) & 0xff;
384                j = (j + S[i]) & 0xff;
385                S_SWAP(i, j);
386                icv[k] ^= S[(S[i] + S[j]) & 0xff];
387        }
388        return m_append(m0, IEEE80211_WEP_CRCLEN, icv);
389#undef S_SWAP
390}
391
392static int
393wep_decrypt(struct ieee80211_key *key, struct mbuf *m0, int hdrlen)
394{
395#define S_SWAP(a,b) do { uint8_t t = S[a]; S[a] = S[b]; S[b] = t; } while(0)
396        struct wep_ctx *ctx = key->wk_private;
397        struct ieee80211vap *vap = ctx->wc_vap;
398        struct mbuf *m = m0;
399        uint8_t rc4key[IEEE80211_WEP_IVLEN + IEEE80211_KEYBUF_SIZE];
400        uint8_t icv[IEEE80211_WEP_CRCLEN];
401        uint32_t i, j, k, crc;
402        size_t buflen, data_len;
403        uint8_t S[256];
404        uint8_t *pos;
405        u_int off, keylen;
406
407        vap->iv_stats.is_crypto_wep++;
408
409        /* NB: this assumes the header was pulled up */
410        memcpy(rc4key, mtod(m, uint8_t *) + hdrlen, IEEE80211_WEP_IVLEN);
411        memcpy(rc4key + IEEE80211_WEP_IVLEN, key->wk_key, key->wk_keylen);
412
413        /* Setup RC4 state */
414        for (i = 0; i < 256; i++)
415                S[i] = i;
416        j = 0;
417        keylen = key->wk_keylen + IEEE80211_WEP_IVLEN;
418        for (i = 0; i < 256; i++) {
419                j = (j + S[i] + rc4key[i % keylen]) & 0xff;
420                S_SWAP(i, j);
421        }
422
423        off = hdrlen + wep.ic_header;
424        data_len = m->m_pkthdr.len - (off + wep.ic_trailer),
425
426        /* Compute CRC32 over unencrypted data and apply RC4 to data */
427        crc = ~0;
428        i = j = 0;
429        pos = mtod(m, uint8_t *) + off;
430        buflen = m->m_len - off;
431        for (;;) {
432                if (buflen > data_len)
433                        buflen = data_len;
434                data_len -= buflen;
435                for (k = 0; k < buflen; k++) {
436                        i = (i + 1) & 0xff;
437                        j = (j + S[i]) & 0xff;
438                        S_SWAP(i, j);
439                        *pos ^= S[(S[i] + S[j]) & 0xff];
440                        crc = crc32_table[(crc ^ *pos) & 0xff] ^ (crc >> 8);
441                        pos++;
442                }
443                m = m->m_next;
444                if (m == NULL) {
445                        if (data_len != 0) {            /* out of data */
446                                IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO,
447                                    mtod(m0, struct ieee80211_frame *)->i_addr2,
448                                    "out of data for WEP (data_len %zu)",
449                                    data_len);
450                                return 0;
451                        }
452                        break;
453                }
454                pos = mtod(m, uint8_t *);
455                buflen = m->m_len;
456        }
457        crc = ~crc;
458
459        /* Encrypt little-endian CRC32 and verify that it matches with
460         * received ICV */
461        icv[0] = crc;
462        icv[1] = crc >> 8;
463        icv[2] = crc >> 16;
464        icv[3] = crc >> 24;
465        for (k = 0; k < IEEE80211_WEP_CRCLEN; k++) {
466                i = (i + 1) & 0xff;
467                j = (j + S[i]) & 0xff;
468                S_SWAP(i, j);
469                /* XXX assumes ICV is contiguous in mbuf */
470                if ((icv[k] ^ S[(S[i] + S[j]) & 0xff]) != *pos++) {
471                        /* ICV mismatch - drop frame */
472                        return 0;
473                }
474        }
475        return 1;
476#undef S_SWAP
477}
478
479/*
480 * Module glue.
481 */
482IEEE80211_CRYPTO_MODULE(wep, 1);
Note: See TracBrowser for help on using the repository browser.