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