2 * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 #include <sys/cdefs.h>
27 __FBSDID("$FreeBSD$");
30 * IEEE 802.11i TKIP crypto support.
32 * Part of this module is derived from similar code in the Host
33 * AP driver. The code is used with the consent of the author and
34 * it's license is included below.
38 #include <sys/param.h>
39 #include <sys/systm.h>
41 #include <sys/malloc.h>
42 #include <sys/kernel.h>
43 #include <sys/module.h>
44 #include <sys/endian.h>
46 #include <sys/socket.h>
49 #include <net/if_media.h>
50 #include <net/ethernet.h>
52 #include <net80211/ieee80211_var.h>
54 static void *tkip_attach(struct ieee80211vap *, struct ieee80211_key *);
55 static void tkip_detach(struct ieee80211_key *);
56 static int tkip_setkey(struct ieee80211_key *);
57 static void tkip_setiv(struct ieee80211_key *, uint8_t *);
58 static int tkip_encap(struct ieee80211_key *, struct mbuf *);
59 static int tkip_enmic(struct ieee80211_key *, struct mbuf *, int);
60 static int tkip_decap(struct ieee80211_key *, struct mbuf *, int);
61 static int tkip_demic(struct ieee80211_key *, struct mbuf *, int);
63 static const struct ieee80211_cipher tkip = {
65 .ic_cipher = IEEE80211_CIPHER_TKIP,
66 .ic_header = IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN +
67 IEEE80211_WEP_EXTIVLEN,
68 .ic_trailer = IEEE80211_WEP_CRCLEN,
69 .ic_miclen = IEEE80211_WEP_MICLEN,
70 .ic_attach = tkip_attach,
71 .ic_detach = tkip_detach,
72 .ic_setkey = tkip_setkey,
73 .ic_setiv = tkip_setiv,
74 .ic_encap = tkip_encap,
75 .ic_decap = tkip_decap,
76 .ic_enmic = tkip_enmic,
77 .ic_demic = tkip_demic,
82 typedef uint32_t __u32;
86 struct ieee80211vap *tc_vap; /* for diagnostics+statistics */
89 u8 tx_rc4key[16]; /* XXX for test module; make locals? */
93 u8 rx_rc4key[16]; /* XXX for test module; make locals? */
94 uint64_t rx_rsc; /* held until MIC verified */
97 static void michael_mic(struct tkip_ctx *, const u8 *key,
98 struct mbuf *m, u_int off, size_t data_len,
99 u8 mic[IEEE80211_WEP_MICLEN]);
100 static int tkip_encrypt(struct tkip_ctx *, struct ieee80211_key *,
101 struct mbuf *, int hdr_len);
102 static int tkip_decrypt(struct tkip_ctx *, struct ieee80211_key *,
103 struct mbuf *, int hdr_len);
105 /* number of references from net80211 layer */
106 static int nrefs = 0;
109 tkip_attach(struct ieee80211vap *vap, struct ieee80211_key *k)
111 struct tkip_ctx *ctx;
113 ctx = (struct tkip_ctx *) IEEE80211_MALLOC(sizeof(struct tkip_ctx),
114 M_80211_CRYPTO, IEEE80211_M_NOWAIT | IEEE80211_M_ZERO);
116 vap->iv_stats.is_crypto_nomem++;
121 nrefs++; /* NB: we assume caller locking */
126 tkip_detach(struct ieee80211_key *k)
128 struct tkip_ctx *ctx = k->wk_private;
130 IEEE80211_FREE(ctx, M_80211_CRYPTO);
131 KASSERT(nrefs > 0, ("imbalanced attach/detach"));
132 nrefs--; /* NB: we assume caller locking */
136 tkip_setkey(struct ieee80211_key *k)
138 struct tkip_ctx *ctx = k->wk_private;
140 if (k->wk_keylen != (128/NBBY)) {
141 (void) ctx; /* XXX */
142 IEEE80211_DPRINTF(ctx->tc_vap, IEEE80211_MSG_CRYPTO,
143 "%s: Invalid key length %u, expecting %u\n",
144 __func__, k->wk_keylen, 128/NBBY);
147 ctx->rx_phase1_done = 0;
152 tkip_setiv(struct ieee80211_key *k, uint8_t *ivp)
154 struct tkip_ctx *ctx = k->wk_private;
155 struct ieee80211vap *vap = ctx->tc_vap;
158 keyid = ieee80211_crypto_get_keyid(vap, k) << 6;
161 ivp[0] = k->wk_keytsc >> 8; /* TSC1 */
162 ivp[1] = (ivp[0] | 0x20) & 0x7f; /* WEP seed */
163 ivp[2] = k->wk_keytsc >> 0; /* TSC0 */
164 ivp[3] = keyid | IEEE80211_WEP_EXTIV; /* KeyID | ExtID */
165 ivp[4] = k->wk_keytsc >> 16; /* TSC2 */
166 ivp[5] = k->wk_keytsc >> 24; /* TSC3 */
167 ivp[6] = k->wk_keytsc >> 32; /* TSC4 */
168 ivp[7] = k->wk_keytsc >> 40; /* TSC5 */
172 * Add privacy headers and do any s/w encryption required.
175 tkip_encap(struct ieee80211_key *k, struct mbuf *m)
177 struct tkip_ctx *ctx = k->wk_private;
178 struct ieee80211vap *vap = ctx->tc_vap;
179 struct ieee80211com *ic = vap->iv_ic;
184 * Handle TKIP counter measures requirement.
186 if (vap->iv_flags & IEEE80211_F_COUNTERM) {
187 #ifdef IEEE80211_DEBUG
188 struct ieee80211_frame *wh = mtod(m, struct ieee80211_frame *);
191 IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO, wh->i_addr2,
192 "discard frame due to countermeasures (%s)", __func__);
193 vap->iv_stats.is_crypto_tkipcm++;
196 hdrlen = ieee80211_hdrspace(ic, mtod(m, void *));
199 * Copy down 802.11 header and add the IV, KeyID, and ExtIV.
201 M_PREPEND(m, tkip.ic_header, M_NOWAIT);
204 ivp = mtod(m, uint8_t *);
205 memmove(ivp, ivp + tkip.ic_header, hdrlen);
211 * Finally, do software encrypt if needed.
213 if ((k->wk_flags & IEEE80211_KEY_SWENCRYPT) &&
214 !tkip_encrypt(ctx, k, m, hdrlen))
221 * Add MIC to the frame as needed.
224 tkip_enmic(struct ieee80211_key *k, struct mbuf *m, int force)
226 struct tkip_ctx *ctx = k->wk_private;
228 if (force || (k->wk_flags & IEEE80211_KEY_SWENMIC)) {
229 struct ieee80211_frame *wh = mtod(m, struct ieee80211_frame *);
230 struct ieee80211vap *vap = ctx->tc_vap;
231 struct ieee80211com *ic = vap->iv_ic;
233 uint8_t mic[IEEE80211_WEP_MICLEN];
235 vap->iv_stats.is_crypto_tkipenmic++;
237 hdrlen = ieee80211_hdrspace(ic, wh);
239 michael_mic(ctx, k->wk_txmic,
240 m, hdrlen, m->m_pkthdr.len - hdrlen, mic);
241 return m_append(m, tkip.ic_miclen, mic);
246 static __inline uint64_t
247 READ_6(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5)
249 uint32_t iv32 = (b0 << 0) | (b1 << 8) | (b2 << 16) | (b3 << 24);
250 uint16_t iv16 = (b4 << 0) | (b5 << 8);
251 return (((uint64_t)iv16) << 32) | iv32;
255 * Validate and strip privacy headers (and trailer) for a
256 * received frame. If necessary, decrypt the frame using
260 tkip_decap(struct ieee80211_key *k, struct mbuf *m, int hdrlen)
262 struct tkip_ctx *ctx = k->wk_private;
263 struct ieee80211vap *vap = ctx->tc_vap;
264 struct ieee80211_frame *wh;
268 * Header should have extended IV and sequence number;
269 * verify the former and validate the latter.
271 wh = mtod(m, struct ieee80211_frame *);
272 ivp = mtod(m, uint8_t *) + hdrlen;
273 if ((ivp[IEEE80211_WEP_IVLEN] & IEEE80211_WEP_EXTIV) == 0) {
275 * No extended IV; discard frame.
277 IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO, wh->i_addr2,
278 "%s", "missing ExtIV for TKIP cipher");
279 vap->iv_stats.is_rx_tkipformat++;
283 * Handle TKIP counter measures requirement.
285 if (vap->iv_flags & IEEE80211_F_COUNTERM) {
286 IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO, wh->i_addr2,
287 "discard frame due to countermeasures (%s)", __func__);
288 vap->iv_stats.is_crypto_tkipcm++;
292 tid = ieee80211_gettid(wh);
293 ctx->rx_rsc = READ_6(ivp[2], ivp[0], ivp[4], ivp[5], ivp[6], ivp[7]);
294 if (ctx->rx_rsc <= k->wk_keyrsc[tid] &&
295 (k->wk_flags & IEEE80211_KEY_NOREPLAY) == 0) {
297 * Replay violation; notify upper layer.
299 ieee80211_notify_replay_failure(vap, wh, k, ctx->rx_rsc, tid);
300 vap->iv_stats.is_rx_tkipreplay++;
304 * NB: We can't update the rsc in the key until MIC is verified.
306 * We assume we are not preempted between doing the check above
307 * and updating wk_keyrsc when stripping the MIC in tkip_demic.
308 * Otherwise we might process another packet and discard it as
313 * Check if the device handled the decrypt in hardware.
314 * If so we just strip the header; otherwise we need to
315 * handle the decrypt in software.
317 if ((k->wk_flags & IEEE80211_KEY_SWDECRYPT) &&
318 !tkip_decrypt(ctx, k, m, hdrlen))
322 * Copy up 802.11 header and strip crypto bits.
324 memmove(mtod(m, uint8_t *) + tkip.ic_header, mtod(m, void *), hdrlen);
325 m_adj(m, tkip.ic_header);
326 m_adj(m, -tkip.ic_trailer);
332 * Verify and strip MIC from the frame.
335 tkip_demic(struct ieee80211_key *k, struct mbuf *m, int force)
337 struct tkip_ctx *ctx = k->wk_private;
338 struct ieee80211_frame *wh;
341 wh = mtod(m, struct ieee80211_frame *);
342 if ((k->wk_flags & IEEE80211_KEY_SWDEMIC) || force) {
343 struct ieee80211vap *vap = ctx->tc_vap;
344 int hdrlen = ieee80211_hdrspace(vap->iv_ic, wh);
345 u8 mic[IEEE80211_WEP_MICLEN];
346 u8 mic0[IEEE80211_WEP_MICLEN];
348 vap->iv_stats.is_crypto_tkipdemic++;
350 michael_mic(ctx, k->wk_rxmic,
351 m, hdrlen, m->m_pkthdr.len - (hdrlen + tkip.ic_miclen),
353 m_copydata(m, m->m_pkthdr.len - tkip.ic_miclen,
354 tkip.ic_miclen, mic0);
355 if (memcmp(mic, mic0, tkip.ic_miclen)) {
356 /* NB: 802.11 layer handles statistic and debug msg */
357 ieee80211_notify_michael_failure(vap, wh,
358 k->wk_rxkeyix != IEEE80211_KEYIX_NONE ?
359 k->wk_rxkeyix : k->wk_keyix);
364 * Strip MIC from the tail.
366 m_adj(m, -tkip.ic_miclen);
369 * Ok to update rsc now that MIC has been verified.
371 tid = ieee80211_gettid(wh);
372 k->wk_keyrsc[tid] = ctx->rx_rsc;
378 * Host AP crypt: host-based TKIP encryption implementation for Host AP driver
380 * Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi>
382 * This program is free software; you can redistribute it and/or modify
383 * it under the terms of the GNU General Public License version 2 as
384 * published by the Free Software Foundation. See README and COPYING for
387 * Alternatively, this software may be distributed under the terms of BSD
391 static const __u32 crc32_table[256] = {
392 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
393 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
394 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
395 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
396 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
397 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
398 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
399 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
400 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
401 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
402 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
403 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
404 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
405 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
406 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
407 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
408 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
409 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
410 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
411 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
412 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
413 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
414 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
415 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
416 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
417 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
418 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
419 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
420 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
421 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
422 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
423 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
424 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
425 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
426 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
427 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
428 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
429 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
430 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
431 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
432 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
433 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
434 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
435 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
436 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
437 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
438 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
439 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
440 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
441 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
442 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
446 static __inline u16 RotR1(u16 val)
448 return (val >> 1) | (val << 15);
451 static __inline u8 Lo8(u16 val)
456 static __inline u8 Hi8(u16 val)
461 static __inline u16 Lo16(u32 val)
466 static __inline u16 Hi16(u32 val)
471 static __inline u16 Mk16(u8 hi, u8 lo)
473 return lo | (((u16) hi) << 8);
476 static __inline u16 Mk16_le(const u16 *v)
481 static const u16 Sbox[256] = {
482 0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154,
483 0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A,
484 0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B,
485 0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B,
486 0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F,
487 0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F,
488 0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5,
489 0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F,
490 0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB,
491 0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397,
492 0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED,
493 0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A,
494 0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194,
495 0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3,
496 0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104,
497 0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D,
498 0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39,
499 0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695,
500 0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83,
501 0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76,
502 0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4,
503 0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B,
504 0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0,
505 0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018,
506 0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751,
507 0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85,
508 0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12,
509 0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9,
510 0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7,
511 0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A,
512 0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8,
513 0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A,
516 static __inline u16 _S_(u16 v)
518 u16 t = Sbox[Hi8(v)];
519 return Sbox[Lo8(v)] ^ ((t << 8) | (t >> 8));
522 #define PHASE1_LOOP_COUNT 8
524 static void tkip_mixing_phase1(u16 *TTAK, const u8 *TK, const u8 *TA, u32 IV32)
528 /* Initialize the 80-bit TTAK from TSC (IV32) and TA[0..5] */
529 TTAK[0] = Lo16(IV32);
530 TTAK[1] = Hi16(IV32);
531 TTAK[2] = Mk16(TA[1], TA[0]);
532 TTAK[3] = Mk16(TA[3], TA[2]);
533 TTAK[4] = Mk16(TA[5], TA[4]);
535 for (i = 0; i < PHASE1_LOOP_COUNT; i++) {
537 TTAK[0] += _S_(TTAK[4] ^ Mk16(TK[1 + j], TK[0 + j]));
538 TTAK[1] += _S_(TTAK[0] ^ Mk16(TK[5 + j], TK[4 + j]));
539 TTAK[2] += _S_(TTAK[1] ^ Mk16(TK[9 + j], TK[8 + j]));
540 TTAK[3] += _S_(TTAK[2] ^ Mk16(TK[13 + j], TK[12 + j]));
541 TTAK[4] += _S_(TTAK[3] ^ Mk16(TK[1 + j], TK[0 + j])) + i;
546 #error "Don't know native byte order"
549 static void tkip_mixing_phase2(u8 *WEPSeed, const u8 *TK, const u16 *TTAK,
552 /* Make temporary area overlap WEP seed so that the final copy can be
553 * avoided on little endian hosts. */
554 u16 *PPK = (u16 *) &WEPSeed[4];
556 /* Step 1 - make copy of TTAK and bring in TSC */
562 PPK[5] = TTAK[4] + IV16;
564 /* Step 2 - 96-bit bijective mixing using S-box */
565 PPK[0] += _S_(PPK[5] ^ Mk16_le((const u16 *) &TK[0]));
566 PPK[1] += _S_(PPK[0] ^ Mk16_le((const u16 *) &TK[2]));
567 PPK[2] += _S_(PPK[1] ^ Mk16_le((const u16 *) &TK[4]));
568 PPK[3] += _S_(PPK[2] ^ Mk16_le((const u16 *) &TK[6]));
569 PPK[4] += _S_(PPK[3] ^ Mk16_le((const u16 *) &TK[8]));
570 PPK[5] += _S_(PPK[4] ^ Mk16_le((const u16 *) &TK[10]));
572 PPK[0] += RotR1(PPK[5] ^ Mk16_le((const u16 *) &TK[12]));
573 PPK[1] += RotR1(PPK[0] ^ Mk16_le((const u16 *) &TK[14]));
574 PPK[2] += RotR1(PPK[1]);
575 PPK[3] += RotR1(PPK[2]);
576 PPK[4] += RotR1(PPK[3]);
577 PPK[5] += RotR1(PPK[4]);
579 /* Step 3 - bring in last of TK bits, assign 24-bit WEP IV value
580 * WEPSeed[0..2] is transmitted as WEP IV */
581 WEPSeed[0] = Hi8(IV16);
582 WEPSeed[1] = (Hi8(IV16) | 0x20) & 0x7F;
583 WEPSeed[2] = Lo8(IV16);
584 WEPSeed[3] = Lo8((PPK[5] ^ Mk16_le((const u16 *) &TK[0])) >> 1);
586 #if _BYTE_ORDER == _BIG_ENDIAN
589 for (i = 0; i < 6; i++)
590 PPK[i] = (PPK[i] << 8) | (PPK[i] >> 8);
596 wep_encrypt(u8 *key, struct mbuf *m0, u_int off, size_t data_len,
597 uint8_t icv[IEEE80211_WEP_CRCLEN])
604 #define S_SWAP(a,b) do { u8 t = S[a]; S[a] = S[b]; S[b] = t; } while(0)
606 /* Setup RC4 state */
607 for (i = 0; i < 256; i++)
610 for (i = 0; i < 256; i++) {
611 j = (j + S[i] + key[i & 0x0f]) & 0xff;
615 /* Compute CRC32 over unencrypted data and apply RC4 to data */
619 pos = mtod(m, uint8_t *) + off;
620 buflen = m->m_len - off;
622 if (buflen > data_len)
625 for (k = 0; k < buflen; k++) {
626 crc = crc32_table[(crc ^ *pos) & 0xff] ^ (crc >> 8);
628 j = (j + S[i]) & 0xff;
630 *pos++ ^= S[(S[i] + S[j]) & 0xff];
634 KASSERT(data_len == 0,
635 ("out of buffers with data_len %zu\n", data_len));
638 pos = mtod(m, uint8_t *);
643 /* Append little-endian CRC32 and encrypt it to produce ICV */
648 for (k = 0; k < IEEE80211_WEP_CRCLEN; k++) {
650 j = (j + S[i]) & 0xff;
652 icv[k] ^= S[(S[i] + S[j]) & 0xff];
657 wep_decrypt(u8 *key, struct mbuf *m, u_int off, size_t data_len)
664 /* Setup RC4 state */
665 for (i = 0; i < 256; i++)
668 for (i = 0; i < 256; i++) {
669 j = (j + S[i] + key[i & 0x0f]) & 0xff;
673 /* Apply RC4 to data and compute CRC32 over decrypted data */
676 pos = mtod(m, uint8_t *) + off;
677 buflen = m->m_len - off;
679 if (buflen > data_len)
682 for (k = 0; k < buflen; k++) {
684 j = (j + S[i]) & 0xff;
686 *pos ^= S[(S[i] + S[j]) & 0xff];
687 crc = crc32_table[(crc ^ *pos) & 0xff] ^ (crc >> 8);
692 KASSERT(data_len == 0,
693 ("out of buffers with data_len %zu\n", data_len));
696 pos = mtod(m, uint8_t *);
701 /* Encrypt little-endian CRC32 and verify that it matches with the
707 for (k = 0; k < 4; k++) {
709 j = (j + S[i]) & 0xff;
711 if ((icv[k] ^ S[(S[i] + S[j]) & 0xff]) != *pos++) {
712 /* ICV mismatch - drop frame */
721 static __inline u32 rotl(u32 val, int bits)
723 return (val << bits) | (val >> (32 - bits));
727 static __inline u32 rotr(u32 val, int bits)
729 return (val >> bits) | (val << (32 - bits));
733 static __inline u32 xswap(u32 val)
735 return ((val & 0x00ff00ff) << 8) | ((val & 0xff00ff00) >> 8);
739 #define michael_block(l, r) \
752 static __inline u32 get_le32_split(u8 b0, u8 b1, u8 b2, u8 b3)
754 return b0 | (b1 << 8) | (b2 << 16) | (b3 << 24);
757 static __inline u32 get_le32(const u8 *p)
759 return get_le32_split(p[0], p[1], p[2], p[3]);
763 static __inline void put_le32(u8 *p, u32 v)
772 * Craft pseudo header used to calculate the MIC.
775 michael_mic_hdr(const struct ieee80211_frame *wh0, uint8_t hdr[16])
777 const struct ieee80211_frame_addr4 *wh =
778 (const struct ieee80211_frame_addr4 *) wh0;
780 switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) {
781 case IEEE80211_FC1_DIR_NODS:
782 IEEE80211_ADDR_COPY(hdr, wh->i_addr1); /* DA */
783 IEEE80211_ADDR_COPY(hdr + IEEE80211_ADDR_LEN, wh->i_addr2);
785 case IEEE80211_FC1_DIR_TODS:
786 IEEE80211_ADDR_COPY(hdr, wh->i_addr3); /* DA */
787 IEEE80211_ADDR_COPY(hdr + IEEE80211_ADDR_LEN, wh->i_addr2);
789 case IEEE80211_FC1_DIR_FROMDS:
790 IEEE80211_ADDR_COPY(hdr, wh->i_addr1); /* DA */
791 IEEE80211_ADDR_COPY(hdr + IEEE80211_ADDR_LEN, wh->i_addr3);
793 case IEEE80211_FC1_DIR_DSTODS:
794 IEEE80211_ADDR_COPY(hdr, wh->i_addr3); /* DA */
795 IEEE80211_ADDR_COPY(hdr + IEEE80211_ADDR_LEN, wh->i_addr4);
799 if (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_QOS) {
800 const struct ieee80211_qosframe *qwh =
801 (const struct ieee80211_qosframe *) wh;
802 hdr[12] = qwh->i_qos[0] & IEEE80211_QOS_TID;
805 hdr[13] = hdr[14] = hdr[15] = 0; /* reserved */
809 michael_mic(struct tkip_ctx *ctx, const u8 *key,
810 struct mbuf *m, u_int off, size_t data_len,
811 u8 mic[IEEE80211_WEP_MICLEN])
818 michael_mic_hdr(mtod(m, struct ieee80211_frame *), hdr);
821 r = get_le32(key + 4);
823 /* Michael MIC pseudo header: DA, SA, 3 x 0, Priority */
826 l ^= get_le32(&hdr[4]);
828 l ^= get_le32(&hdr[8]);
830 l ^= get_le32(&hdr[12]);
833 /* first buffer has special handling */
834 data = mtod(m, const uint8_t *) + off;
835 space = m->m_len - off;
837 if (space > data_len)
839 /* collect 32-bit blocks from current buffer */
840 while (space >= sizeof(uint32_t)) {
843 data += sizeof(uint32_t), space -= sizeof(uint32_t);
844 data_len -= sizeof(uint32_t);
847 * NB: when space is zero we make one more trip around
848 * the loop to advance to the next mbuf where there is
849 * data. This handles the case where there are 4*n
850 * bytes in an mbuf followed by <4 bytes in a later mbuf.
851 * By making an extra trip we'll drop out of the loop
852 * with m pointing at the mbuf with 3 bytes and space
853 * set as required by the remainder handling below.
856 (data_len < sizeof(uint32_t) && space != 0))
860 KASSERT(0, ("out of data, data_len %zu\n", data_len));
864 const uint8_t *data_next;
866 * Block straddles buffers, split references.
868 data_next = mtod(m, const uint8_t *);
869 KASSERT(m->m_len >= sizeof(uint32_t) - space,
870 ("not enough data in following buffer, "
871 "m_len %u need %zu\n", m->m_len,
872 sizeof(uint32_t) - space));
875 l ^= get_le32_split(data[0], data_next[0],
876 data_next[1], data_next[2]);
877 data = data_next + 3;
878 space = m->m_len - 3;
881 l ^= get_le32_split(data[0], data[1],
882 data_next[0], data_next[1]);
883 data = data_next + 2;
884 space = m->m_len - 2;
887 l ^= get_le32_split(data[0], data[1],
888 data[2], data_next[0]);
889 data = data_next + 1;
890 space = m->m_len - 1;
894 data_len -= sizeof(uint32_t);
897 * Setup for next buffer.
899 data = mtod(m, const uint8_t *);
904 * Catch degenerate cases like mbuf[4*n+1 bytes] followed by
905 * mbuf[2 bytes]. I don't believe these should happen; if they
906 * do then we'll need more involved logic.
908 KASSERT(data_len <= space,
909 ("not enough data, data_len %zu space %u\n", data_len, space));
911 /* Last block and padding (0x5a, 4..7 x 0) */
914 l ^= get_le32_split(0x5a, 0, 0, 0);
917 l ^= get_le32_split(data[0], 0x5a, 0, 0);
920 l ^= get_le32_split(data[0], data[1], 0x5a, 0);
923 l ^= get_le32_split(data[0], data[1], data[2], 0x5a);
931 put_le32(mic + 4, r);
935 tkip_encrypt(struct tkip_ctx *ctx, struct ieee80211_key *key,
936 struct mbuf *m, int hdrlen)
938 struct ieee80211_frame *wh;
939 uint8_t icv[IEEE80211_WEP_CRCLEN];
941 ctx->tc_vap->iv_stats.is_crypto_tkip++;
943 wh = mtod(m, struct ieee80211_frame *);
944 if ((u16)(key->wk_keytsc) == 0 || key->wk_keytsc == 1) {
945 tkip_mixing_phase1(ctx->tx_ttak, key->wk_key, wh->i_addr2,
946 (u32)(key->wk_keytsc >> 16));
948 tkip_mixing_phase2(ctx->tx_rc4key, key->wk_key, ctx->tx_ttak,
949 (u16) key->wk_keytsc);
951 wep_encrypt(ctx->tx_rc4key,
952 m, hdrlen + tkip.ic_header,
953 m->m_pkthdr.len - (hdrlen + tkip.ic_header),
955 (void) m_append(m, IEEE80211_WEP_CRCLEN, icv); /* XXX check return */
961 tkip_decrypt(struct tkip_ctx *ctx, struct ieee80211_key *key,
962 struct mbuf *m, int hdrlen)
964 struct ieee80211_frame *wh;
965 struct ieee80211vap *vap = ctx->tc_vap;
970 vap->iv_stats.is_crypto_tkip++;
972 wh = mtod(m, struct ieee80211_frame *);
973 /* NB: tkip_decap already verified header and left seq in rx_rsc */
974 iv16 = (u16) ctx->rx_rsc;
975 iv32 = (u32) (ctx->rx_rsc >> 16);
977 tid = ieee80211_gettid(wh);
978 if (iv32 != (u32)(key->wk_keyrsc[tid] >> 16) || !ctx->rx_phase1_done) {
979 tkip_mixing_phase1(ctx->rx_ttak, key->wk_key,
981 ctx->rx_phase1_done = 1;
983 tkip_mixing_phase2(ctx->rx_rc4key, key->wk_key, ctx->rx_ttak, iv16);
985 /* NB: m is unstripped; deduct headers + ICV to get payload */
986 if (wep_decrypt(ctx->rx_rc4key,
987 m, hdrlen + tkip.ic_header,
988 m->m_pkthdr.len - (hdrlen + tkip.ic_header + tkip.ic_trailer))) {
989 if (iv32 != (u32)(key->wk_keyrsc[tid] >> 16)) {
990 /* Previously cached Phase1 result was already lost, so
991 * it needs to be recalculated for the next packet. */
992 ctx->rx_phase1_done = 0;
994 IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO, wh->i_addr2,
995 "%s", "TKIP ICV mismatch on decrypt");
996 vap->iv_stats.is_rx_tkipicv++;
1005 IEEE80211_CRYPTO_MODULE(tkip, 1);