ieee80211_crypto_tkip.c revision 182437
113675Sdyson/*- 213675Sdyson * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting 313675Sdyson * All rights reserved. 413675Sdyson * 513675Sdyson * Redistribution and use in source and binary forms, with or without 613675Sdyson * modification, are permitted provided that the following conditions 713675Sdyson * are met: 813675Sdyson * 1. Redistributions of source code must retain the above copyright 913675Sdyson * notice, this list of conditions and the following disclaimer. 1013675Sdyson * 2. Redistributions in binary form must reproduce the above copyright 1113675Sdyson * notice, this list of conditions and the following disclaimer in the 1213675Sdyson * documentation and/or other materials provided with the distribution. 1313675Sdyson * 1413675Sdyson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1513675Sdyson * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1614037Sdyson * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1713675Sdyson * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 1813675Sdyson * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 1950477Speter * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2013675Sdyson * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2113675Sdyson * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2213675Sdyson * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2313675Sdyson * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2413675Sdyson */ 2513675Sdyson 2613675Sdyson#include <sys/cdefs.h> 2713675Sdyson__FBSDID("$FreeBSD: head/sys/net80211/ieee80211_crypto_tkip.c 182437 2008-08-29 08:44:51Z avatar $"); 2813675Sdyson 2913907Sdyson/* 3013907Sdyson * IEEE 802.11i TKIP crypto support. 3113907Sdyson * 3213907Sdyson * Part of this module is derived from similar code in the Host 3313907Sdyson * AP driver. The code is used with the consent of the author and 3413907Sdyson * it's license is included below. 3513907Sdyson */ 3613907Sdyson#include "opt_wlan.h" 3713907Sdyson 3813907Sdyson#include <sys/param.h> 3913913Sdyson#include <sys/systm.h> 4013907Sdyson#include <sys/mbuf.h> 4113907Sdyson#include <sys/malloc.h> 4213907Sdyson#include <sys/kernel.h> 4313907Sdyson#include <sys/module.h> 4413907Sdyson#include <sys/endian.h> 4513907Sdyson 4613907Sdyson#include <sys/socket.h> 4713907Sdyson 4813913Sdyson#include <net/if.h> 4913907Sdyson#include <net/if_media.h> 5013907Sdyson#include <net/ethernet.h> 5113907Sdyson 5213675Sdyson#include <net80211/ieee80211_var.h> 5313675Sdyson 5424131Sbdestatic void *tkip_attach(struct ieee80211vap *, struct ieee80211_key *); 5513675Sdysonstatic void tkip_detach(struct ieee80211_key *); 5613675Sdysonstatic int tkip_setkey(struct ieee80211_key *); 5724206Sbdestatic int tkip_encap(struct ieee80211_key *, struct mbuf *m, uint8_t keyid); 5891372Salfredstatic int tkip_enmic(struct ieee80211_key *, struct mbuf *, int); 5976166Smarkmstatic int tkip_decap(struct ieee80211_key *, struct mbuf *, int); 6076827Salfredstatic int tkip_demic(struct ieee80211_key *, struct mbuf *, int); 6124206Sbde 6213675Sdysonstatic const struct ieee80211_cipher tkip = { 6391968Salfred .ic_name = "TKIP", 6429356Speter .ic_cipher = IEEE80211_CIPHER_TKIP, 6570834Swollman .ic_header = IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN + 6613675Sdyson IEEE80211_WEP_EXTIVLEN, 6713675Sdyson .ic_trailer = IEEE80211_WEP_CRCLEN, 6813675Sdyson .ic_miclen = IEEE80211_WEP_MICLEN, 6976166Smarkm .ic_attach = tkip_attach, 7055112Sbde .ic_detach = tkip_detach, 7134924Sbde .ic_setkey = tkip_setkey, 7259288Sjlemon .ic_encap = tkip_encap, 7313675Sdyson .ic_decap = tkip_decap, 7413675Sdyson .ic_enmic = tkip_enmic, 7513675Sdyson .ic_demic = tkip_demic, 7613675Sdyson}; 7713675Sdyson 7813675Sdysontypedef uint8_t u8; 7913675Sdysontypedef uint16_t u16; 8013675Sdysontypedef uint32_t __u32; 8113907Sdysontypedef uint32_t u32; 8227899Sdyson 8313675Sdysonstruct tkip_ctx { 8414037Sdyson struct ieee80211vap *tc_vap; /* for diagnostics+statistics */ 8514037Sdyson 8614037Sdyson u16 tx_ttak[5]; 8714037Sdyson int tx_phase1_done; 8814037Sdyson u8 tx_rc4key[16]; /* XXX for test module; make locals? */ 8914037Sdyson 9014037Sdyson u16 rx_ttak[5]; 9114037Sdyson int rx_phase1_done; 9214037Sdyson u8 rx_rc4key[16]; /* XXX for test module; make locals? */ 9314037Sdyson uint64_t rx_rsc; /* held until MIC verified */ 9491413Salfred}; 9591413Salfred 9691413Salfredstatic void michael_mic(struct tkip_ctx *, const u8 *key, 9791413Salfred struct mbuf *m, u_int off, size_t data_len, 9891413Salfred u8 mic[IEEE80211_WEP_MICLEN]); 9991413Salfredstatic int tkip_encrypt(struct tkip_ctx *, struct ieee80211_key *, 10091413Salfred struct mbuf *, int hdr_len); 10191413Salfredstatic int tkip_decrypt(struct tkip_ctx *, struct ieee80211_key *, 10291413Salfred struct mbuf *, int hdr_len); 10391413Salfred 10413675Sdyson/* number of references from net80211 layer */ 10572521Sjlemonstatic int nrefs = 0; 10672521Sjlemon 10772521Sjlemonstatic void * 10872521Sjlemontkip_attach(struct ieee80211vap *vap, struct ieee80211_key *k) 10913675Sdyson{ 11059288Sjlemon struct tkip_ctx *ctx; 11159288Sjlemon 11259288Sjlemon MALLOC(ctx, struct tkip_ctx *, sizeof(struct tkip_ctx), 11359288Sjlemon M_80211_CRYPTO, M_NOWAIT | M_ZERO); 11472521Sjlemon if (ctx == NULL) { 11572521Sjlemon vap->iv_stats.is_crypto_nomem++; 11672521Sjlemon return NULL; 11772521Sjlemon } 11859288Sjlemon 11992305Salfred ctx->tc_vap = vap; 12091362Salfred nrefs++; /* NB: we assume caller locking */ 12192305Salfred return ctx; 12292305Salfred} 12392305Salfred 12492305Salfredstatic void 12591362Salfredtkip_detach(struct ieee80211_key *k) 12691362Salfred{ 12772521Sjlemon struct tkip_ctx *ctx = k->wk_private; 12891362Salfred 12991362Salfred FREE(ctx, M_80211_CRYPTO); 13091362Salfred KASSERT(nrefs > 0, ("imbalanced attach/detach")); 13192305Salfred nrefs--; /* NB: we assume caller locking */ 13291362Salfred} 13391362Salfred 13413675Sdysonstatic int 13513675Sdysontkip_setkey(struct ieee80211_key *k) 13613675Sdyson{ 13713675Sdyson struct tkip_ctx *ctx = k->wk_private; 13813675Sdyson 13913675Sdyson if (k->wk_keylen != (128/NBBY)) { 14013907Sdyson (void) ctx; /* XXX */ 14113907Sdyson IEEE80211_DPRINTF(ctx->tc_vap, IEEE80211_MSG_CRYPTO, 14213675Sdyson "%s: Invalid key length %u, expecting %u\n", 14313907Sdyson __func__, k->wk_keylen, 128/NBBY); 14413907Sdyson return 0; 14513907Sdyson } 14613907Sdyson k->wk_keytsc = 1; /* TSC starts at 1 */ 14713907Sdyson return 1; 14813907Sdyson} 14913907Sdyson 15013907Sdyson/* 15113907Sdyson * Add privacy headers and do any s/w encryption required. 15213907Sdyson */ 15313907Sdysonstatic int 15417163Sdysontkip_encap(struct ieee80211_key *k, struct mbuf *m, uint8_t keyid) 15517163Sdyson{ 15617163Sdyson struct tkip_ctx *ctx = k->wk_private; 15717163Sdyson struct ieee80211vap *vap = ctx->tc_vap; 15817163Sdyson struct ieee80211com *ic = vap->iv_ic; 15933181Seivind uint8_t *ivp; 16017163Sdyson int hdrlen; 16117124Sbde 16213907Sdyson /* 16391413Salfred * Handle TKIP counter measures requirement. 16491413Salfred */ 16591413Salfred if (vap->iv_flags & IEEE80211_F_COUNTERM) { 16691413Salfred#ifdef IEEE80211_DEBUG 16791413Salfred struct ieee80211_frame *wh = mtod(m, struct ieee80211_frame *); 16891413Salfred#endif 16991413Salfred 17014037Sdyson IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO, wh->i_addr2, 17191413Salfred "discard frame due to countermeasures (%s)", __func__); 17291413Salfred vap->iv_stats.is_crypto_tkipcm++; 17391413Salfred return 0; 17491413Salfred } 17514037Sdyson hdrlen = ieee80211_hdrspace(ic, mtod(m, void *)); 17691413Salfred 17713675Sdyson /* 17833181Seivind * Copy down 802.11 header and add the IV, KeyID, and ExtIV. 17927899Sdyson */ 18091372Salfred M_PREPEND(m, tkip.ic_header, M_NOWAIT); 18191372Salfred if (m == NULL) 18291372Salfred return 0; 18391372Salfred ivp = mtod(m, uint8_t *); 18491372Salfred memmove(ivp, ivp + tkip.ic_header, hdrlen); 18592654Sjeff ivp += hdrlen; 18692654Sjeff 18791372Salfred ivp[0] = k->wk_keytsc >> 8; /* TSC1 */ 18891372Salfred ivp[1] = (ivp[0] | 0x20) & 0x7f; /* WEP seed */ 18913675Sdyson ivp[2] = k->wk_keytsc >> 0; /* TSC0 */ 19013675Sdyson ivp[3] = keyid | IEEE80211_WEP_EXTIV; /* KeyID | ExtID */ 19113675Sdyson ivp[4] = k->wk_keytsc >> 16; /* TSC2 */ 19213675Sdyson ivp[5] = k->wk_keytsc >> 24; /* TSC3 */ 19313675Sdyson ivp[6] = k->wk_keytsc >> 32; /* TSC4 */ 19413675Sdyson ivp[7] = k->wk_keytsc >> 40; /* TSC5 */ 19583366Sjulian 19683366Sjulian /* 19713675Sdyson * Finally, do software encrypt if neeed. 19813675Sdyson */ 19913675Sdyson if (k->wk_flags & IEEE80211_KEY_SWENCRYPT) { 20013675Sdyson if (!tkip_encrypt(ctx, k, m, hdrlen)) 20183366Sjulian return 0; 20213675Sdyson /* NB: tkip_encrypt handles wk_keytsc */ 20313675Sdyson } else 20491968Salfred k->wk_keytsc++; 20513675Sdyson 20691362Salfred return 1; 20791372Salfred} 20827899Sdyson 20991968Salfred/* 21091968Salfred * Add MIC to the frame as needed. 21176756Salfred */ 21276364Salfredstatic int 21376364Salfredtkip_enmic(struct ieee80211_key *k, struct mbuf *m, int force) 21476364Salfred{ 21591968Salfred struct tkip_ctx *ctx = k->wk_private; 21676364Salfred 21776364Salfred if (force || (k->wk_flags & IEEE80211_KEY_SWENMIC)) { 21876364Salfred struct ieee80211_frame *wh = mtod(m, struct ieee80211_frame *); 21913907Sdyson struct ieee80211vap *vap = ctx->tc_vap; 22013907Sdyson struct ieee80211com *ic = vap->iv_ic; 22113675Sdyson int hdrlen; 22283366Sjulian uint8_t mic[IEEE80211_WEP_MICLEN]; 22370915Sdwmalone 22470915Sdwmalone vap->iv_stats.is_crypto_tkipenmic++; 22570915Sdwmalone 22691968Salfred hdrlen = ieee80211_hdrspace(ic, wh); 22770915Sdwmalone 22870915Sdwmalone michael_mic(ctx, k->wk_txmic, 22970915Sdwmalone m, hdrlen, m->m_pkthdr.len - hdrlen, mic); 23083366Sjulian return m_append(m, tkip.ic_miclen, mic); 23170915Sdwmalone } 23270803Sdwmalone return 1; 23370803Sdwmalone} 23470803Sdwmalone 23570803Sdwmalonestatic __inline uint64_t 23670803SdwmaloneREAD_6(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5) 23770803Sdwmalone{ 23889306Salfred uint32_t iv32 = (b0 << 0) | (b1 << 8) | (b2 << 16) | (b3 << 24); 23913675Sdyson uint16_t iv16 = (b4 << 0) | (b5 << 8); 24013675Sdyson return (((uint64_t)iv16) << 32) | iv32; 24149413Sgreen} 24213675Sdyson 24389306Salfred/* 24483366Sjulian * Validate and strip privacy headers (and trailer) for a 24570915Sdwmalone * received frame. If necessary, decrypt the frame using 24689306Salfred * the specified key. 24783366Sjulian */ 24883366Sjulianstatic int 24989306Salfredtkip_decap(struct ieee80211_key *k, struct mbuf *m, int hdrlen) 25083366Sjulian{ 25189306Salfred struct tkip_ctx *ctx = k->wk_private; 25289306Salfred struct ieee80211vap *vap = ctx->tc_vap; 25383366Sjulian struct ieee80211_frame *wh; 25470915Sdwmalone uint8_t *ivp, tid; 25570915Sdwmalone 25691968Salfred /* 25770915Sdwmalone * Header should have extended IV and sequence number; 25870915Sdwmalone * verify the former and validate the latter. 25989306Salfred */ 26013675Sdyson wh = mtod(m, struct ieee80211_frame *); 26113675Sdyson ivp = mtod(m, uint8_t *) + hdrlen; 26249413Sgreen if ((ivp[IEEE80211_WEP_IVLEN] & IEEE80211_WEP_EXTIV) == 0) { 26313675Sdyson /* 26489306Salfred * No extended IV; discard frame. 26583366Sjulian */ 26613675Sdyson IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO, wh->i_addr2, 26713675Sdyson "%s", "missing ExtIV for TKIP cipher"); 26891968Salfred vap->iv_stats.is_rx_tkipformat++; 26991968Salfred return 0; 27083366Sjulian } 27113675Sdyson /* 27213675Sdyson * Handle TKIP counter measures requirement. 27313675Sdyson */ 27413675Sdyson if (vap->iv_flags & IEEE80211_F_COUNTERM) { 27513909Sdyson IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO, wh->i_addr2, 27613909Sdyson "discard frame due to countermeasures (%s)", __func__); 27776364Salfred vap->iv_stats.is_crypto_tkipcm++; 27876364Salfred return 0; 27976364Salfred } 28013909Sdyson 28176364Salfred tid = ieee80211_gettid(wh); 28276364Salfred ctx->rx_rsc = READ_6(ivp[2], ivp[0], ivp[4], ivp[5], ivp[6], ivp[7]); 28313675Sdyson if (ctx->rx_rsc <= k->wk_keyrsc[tid]) { 28476364Salfred /* 28513675Sdyson * Replay violation; notify upper layer. 28676364Salfred */ 28776364Salfred ieee80211_notify_replay_failure(vap, wh, k, ctx->rx_rsc); 28813688Sdyson vap->iv_stats.is_rx_tkipreplay++; 28913675Sdyson return 0; 29079224Sdillon } 29191412Salfred /* 29291412Salfred * NB: We can't update the rsc in the key until MIC is verified. 29379224Sdillon * 29476364Salfred * We assume we are not preempted between doing the check above 29513675Sdyson * and updating wk_keyrsc when stripping the MIC in tkip_demic. 29613675Sdyson * Otherwise we might process another packet and discard it as 29713675Sdyson * a replay. 29814037Sdyson */ 29913675Sdyson 30076364Salfred /* 30176364Salfred * Check if the device handled the decrypt in hardware. 30213675Sdyson * If so we just strip the header; otherwise we need to 30313675Sdyson * handle the decrypt in software. 30413675Sdyson */ 30513675Sdyson if ((k->wk_flags & IEEE80211_KEY_SWDECRYPT) && 30614037Sdyson !tkip_decrypt(ctx, k, m, hdrlen)) 30713675Sdyson return 0; 30876364Salfred 30976364Salfred /* 31013688Sdyson * Copy up 802.11 header and strip crypto bits. 31113675Sdyson */ 31276364Salfred memmove(mtod(m, uint8_t *) + tkip.ic_header, mtod(m, void *), hdrlen); 31376364Salfred m_adj(m, tkip.ic_header); 31476364Salfred m_adj(m, -tkip.ic_trailer); 31576364Salfred 31676364Salfred return 1; 31776364Salfred} 31876364Salfred 31976364Salfred/* 32076364Salfred * Verify and strip MIC from the frame. 32176364Salfred */ 32276364Salfredstatic int 32376364Salfredtkip_demic(struct ieee80211_key *k, struct mbuf *m, int force) 32476364Salfred{ 32513907Sdyson struct tkip_ctx *ctx = k->wk_private; 32676364Salfred struct ieee80211_frame *wh; 32713907Sdyson uint8_t tid; 32813688Sdyson 32913907Sdyson wh = mtod(m, struct ieee80211_frame *); 33013907Sdyson if ((k->wk_flags & IEEE80211_KEY_SWDEMIC) || force) { 33113907Sdyson struct ieee80211vap *vap = ctx->tc_vap; 33276364Salfred int hdrlen = ieee80211_hdrspace(vap->iv_ic, wh); 33376364Salfred u8 mic[IEEE80211_WEP_MICLEN]; 33476364Salfred u8 mic0[IEEE80211_WEP_MICLEN]; 33576364Salfred 33613907Sdyson vap->iv_stats.is_crypto_tkipdemic++; 33776364Salfred 33813907Sdyson michael_mic(ctx, k->wk_rxmic, 33976364Salfred m, hdrlen, m->m_pkthdr.len - (hdrlen + tkip.ic_miclen), 34076364Salfred mic); 34176364Salfred m_copydata(m, m->m_pkthdr.len - tkip.ic_miclen, 34217163Sdyson tkip.ic_miclen, mic0); 34376364Salfred if (memcmp(mic, mic0, tkip.ic_miclen)) { 34476364Salfred /* NB: 802.11 layer handles statistic and debug msg */ 34576364Salfred ieee80211_notify_michael_failure(vap, wh, 34676364Salfred k->wk_rxkeyix != IEEE80211_KEYIX_NONE ? 34776364Salfred k->wk_rxkeyix : k->wk_keyix); 34876364Salfred return 0; 34976364Salfred } 35076364Salfred } 35176364Salfred /* 35276364Salfred * Strip MIC from the tail. 35376364Salfred */ 35476754Salfred m_adj(m, -tkip.ic_miclen); 35513675Sdyson 35613675Sdyson /* 35713675Sdyson * Ok to update rsc now that MIC has been verified. 35813907Sdyson */ 35914037Sdyson tid = ieee80211_gettid(wh); 36013907Sdyson k->wk_keyrsc[tid] = ctx->rx_rsc; 36113907Sdyson 36213907Sdyson return 1; 36313907Sdyson} 36413907Sdyson 36513907Sdyson/* 36613907Sdyson * Host AP crypt: host-based TKIP encryption implementation for Host AP driver 36717124Sbde * 36814037Sdyson * Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi> 36976364Salfred * 37091412Salfred * This program is free software; you can redistribute it and/or modify 37176364Salfred * it under the terms of the GNU General Public License version 2 as 37276760Salfred * published by the Free Software Foundation. See README and COPYING for 37376364Salfred * more details. 37476364Salfred * 37576364Salfred * Alternatively, this software may be distributed under the terms of BSD 37676364Salfred * license. 37776364Salfred */ 37876364Salfred 37976364Salfredstatic const __u32 crc32_table[256] = { 38013675Sdyson 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, 38113675Sdyson 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, 38213675Sdyson 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, 38313675Sdyson 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, 38413675Sdyson 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, 38513675Sdyson 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, 38613675Sdyson 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, 38713907Sdyson 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, 38813675Sdyson 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, 38913907Sdyson 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, 39013675Sdyson 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, 39113776Sdyson 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, 39276364Salfred 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, 39391362Salfred 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, 39491362Salfred 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, 39513675Sdyson 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, 39691362Salfred 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, 39791362Salfred 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, 39876760Salfred 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, 39976760Salfred 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, 40076760Salfred 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, 40113675Sdyson 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, 40291362Salfred 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, 40376760Salfred 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, 40413675Sdyson 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, 40513675Sdyson 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, 40613675Sdyson 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, 40713675Sdyson 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, 40813675Sdyson 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, 40913675Sdyson 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, 41013675Sdyson 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, 41113675Sdyson 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, 41213675Sdyson 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, 41376364Salfred 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, 41491362Salfred 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, 41591362Salfred 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, 41613675Sdyson 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, 41713675Sdyson 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, 41814177Sdyson 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, 41913675Sdyson 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, 42013675Sdyson 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, 42113675Sdyson 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, 42214037Sdyson 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, 42314037Sdyson 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, 42414037Sdyson 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, 42514037Sdyson 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, 42676364Salfred 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, 42714037Sdyson 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, 42814037Sdyson 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, 42914037Sdyson 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, 43014037Sdyson 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, 43141086Struckman 0x2d02ef8dL 43241086Struckman}; 43359288Sjlemon 43414037Sdysonstatic __inline u16 RotR1(u16 val) 43514037Sdyson{ 43613675Sdyson return (val >> 1) | (val << 15); 43713675Sdyson} 43883366Sjulian 43913675Sdysonstatic __inline u8 Lo8(u16 val) 44013675Sdyson{ 44113675Sdyson return val & 0xff; 44283366Sjulian} 44345311Sdt 44413675Sdysonstatic __inline u8 Hi8(u16 val) 44513675Sdyson{ 44647748Salc return val >> 8; 44713675Sdyson} 44818863Sdyson 44913675Sdysonstatic __inline u16 Lo16(u32 val) 45091362Salfred{ 45113675Sdyson return val & 0xffff; 45247748Salc} 45347748Salc 45447748Salcstatic __inline u16 Hi16(u32 val) 45547748Salc{ 45613675Sdyson return val >> 16; 45713907Sdyson} 45813907Sdyson 45913907Sdysonstatic __inline u16 Mk16(u8 hi, u8 lo) 46013675Sdyson{ 46118863Sdyson return lo | (((u16) hi) << 8); 46213675Sdyson} 46313675Sdyson 46418863Sdysonstatic __inline u16 Mk16_le(const u16 *v) 46518863Sdyson{ 46647748Salc return le16toh(*v); 46791362Salfred} 46847748Salc 46913675Sdysonstatic const u16 Sbox[256] = { 47091362Salfred 0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154, 47176760Salfred 0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A, 47213675Sdyson 0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B, 47376760Salfred 0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B, 47413675Sdyson 0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F, 47513675Sdyson 0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F, 47613675Sdyson 0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5, 47713675Sdyson 0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F, 47813675Sdyson 0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB, 47947748Salc 0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397, 48047748Salc 0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED, 48147748Salc 0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A, 48247748Salc 0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194, 48347748Salc 0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3, 48447748Salc 0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104, 48547748Salc 0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D, 48647748Salc 0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39, 48747748Salc 0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695, 48847748Salc 0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83, 48913675Sdyson 0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76, 49014037Sdyson 0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4, 49113907Sdyson 0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B, 49213907Sdyson 0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0, 49313907Sdyson 0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018, 49413907Sdyson 0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751, 49547748Salc 0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85, 49647748Salc 0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12, 49718863Sdyson 0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9, 49818863Sdyson 0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7, 49947748Salc 0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A, 50076760Salfred 0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8, 50176760Salfred 0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A, 50291362Salfred}; 50347748Salc 50491362Salfredstatic __inline u16 _S_(u16 v) 50513907Sdyson{ 50613907Sdyson u16 t = Sbox[Hi8(v)]; 50713907Sdyson return Sbox[Lo8(v)] ^ ((t << 8) | (t >> 8)); 50813907Sdyson} 50913907Sdyson 51013907Sdyson#define PHASE1_LOOP_COUNT 8 51113907Sdyson 51213907Sdysonstatic void tkip_mixing_phase1(u16 *TTAK, const u8 *TK, const u8 *TA, u32 IV32) 51313907Sdyson{ 51414037Sdyson int i, j; 51513675Sdyson 51613675Sdyson /* Initialize the 80-bit TTAK from TSC (IV32) and TA[0..5] */ 51713675Sdyson TTAK[0] = Lo16(IV32); 51876760Salfred TTAK[1] = Hi16(IV32); 51913675Sdyson TTAK[2] = Mk16(TA[1], TA[0]); 52076760Salfred TTAK[3] = Mk16(TA[3], TA[2]); 52113675Sdyson TTAK[4] = Mk16(TA[5], TA[4]); 52243623Sdillon 52313675Sdyson for (i = 0; i < PHASE1_LOOP_COUNT; i++) { 52413675Sdyson j = 2 * (i & 1); 52513675Sdyson TTAK[0] += _S_(TTAK[4] ^ Mk16(TK[1 + j], TK[0 + j])); 52613675Sdyson TTAK[1] += _S_(TTAK[0] ^ Mk16(TK[5 + j], TK[4 + j])); 52713675Sdyson TTAK[2] += _S_(TTAK[1] ^ Mk16(TK[9 + j], TK[8 + j])); 52813675Sdyson TTAK[3] += _S_(TTAK[2] ^ Mk16(TK[13 + j], TK[12 + j])); 52913675Sdyson TTAK[4] += _S_(TTAK[3] ^ Mk16(TK[1 + j], TK[0 + j])) + i; 53043623Sdillon } 53143623Sdillon} 53247748Salc 53343623Sdillon#ifndef _BYTE_ORDER 53447748Salc#error "Don't know native byte order" 53513675Sdyson#endif 53616960Sdyson 53743623Sdillonstatic void tkip_mixing_phase2(u8 *WEPSeed, const u8 *TK, const u16 *TTAK, 53847748Salc u16 IV16) 53947748Salc{ 54047748Salc /* Make temporary area overlap WEP seed so that the final copy can be 54143623Sdillon * avoided on little endian hosts. */ 54247748Salc u16 *PPK = (u16 *) &WEPSeed[4]; 54343623Sdillon 54413675Sdyson /* Step 1 - make copy of TTAK and bring in TSC */ 54547748Salc PPK[0] = TTAK[0]; 54647748Salc PPK[1] = TTAK[1]; 54713675Sdyson PPK[2] = TTAK[2]; 54876760Salfred PPK[3] = TTAK[3]; 54947748Salc PPK[4] = TTAK[4]; 55076760Salfred PPK[5] = TTAK[4] + IV16; 55147748Salc 55291362Salfred /* Step 2 - 96-bit bijective mixing using S-box */ 55391362Salfred PPK[0] += _S_(PPK[5] ^ Mk16_le((const u16 *) &TK[0])); 55477140Salfred PPK[1] += _S_(PPK[0] ^ Mk16_le((const u16 *) &TK[2])); 55547748Salc PPK[2] += _S_(PPK[1] ^ Mk16_le((const u16 *) &TK[4])); 55613675Sdyson PPK[3] += _S_(PPK[2] ^ Mk16_le((const u16 *) &TK[6])); 55747748Salc PPK[4] += _S_(PPK[3] ^ Mk16_le((const u16 *) &TK[8])); 55847748Salc PPK[5] += _S_(PPK[4] ^ Mk16_le((const u16 *) &TK[10])); 55913675Sdyson 56013675Sdyson PPK[0] += RotR1(PPK[5] ^ Mk16_le((const u16 *) &TK[12])); 56147748Salc PPK[1] += RotR1(PPK[0] ^ Mk16_le((const u16 *) &TK[14])); 56213675Sdyson PPK[2] += RotR1(PPK[1]); 56391362Salfred PPK[3] += RotR1(PPK[2]); 56424101Sbde PPK[4] += RotR1(PPK[3]); 56555112Sbde PPK[5] += RotR1(PPK[4]); 56647748Salc 56747748Salc /* Step 3 - bring in last of TK bits, assign 24-bit WEP IV value 56813913Sdyson * WEPSeed[0..2] is transmitted as WEP IV */ 56947748Salc WEPSeed[0] = Hi8(IV16); 57047748Salc WEPSeed[1] = (Hi8(IV16) | 0x20) & 0x7F; 57147748Salc WEPSeed[2] = Lo8(IV16); 57213675Sdyson WEPSeed[3] = Lo8((PPK[5] ^ Mk16_le((const u16 *) &TK[0])) >> 1); 57313675Sdyson 57413675Sdyson#if _BYTE_ORDER == _BIG_ENDIAN 57513675Sdyson { 57613675Sdyson int i; 57747748Salc for (i = 0; i < 6; i++) 57813675Sdyson PPK[i] = (PPK[i] << 8) | (PPK[i] >> 8); 57913675Sdyson } 58013675Sdyson#endif 58113675Sdyson} 58213675Sdyson 58313675Sdysonstatic void 58414037Sdysonwep_encrypt(u8 *key, struct mbuf *m0, u_int off, size_t data_len, 58514802Sdyson uint8_t icv[IEEE80211_WEP_CRCLEN]) 58614037Sdyson{ 58714037Sdyson u32 i, j, k, crc; 58891362Salfred size_t buflen; 58976760Salfred u8 S[256]; 59013675Sdyson u8 *pos; 59113675Sdyson struct mbuf *m; 59214037Sdyson#define S_SWAP(a,b) do { u8 t = S[a]; S[a] = S[b]; S[b] = t; } while(0) 59313907Sdyson 59413907Sdyson /* Setup RC4 state */ 59513907Sdyson for (i = 0; i < 256; i++) 59613907Sdyson S[i] = i; 59713675Sdyson j = 0; 59813907Sdyson for (i = 0; i < 256; i++) { 59913907Sdyson j = (j + S[i] + key[i & 0x0f]) & 0xff; 60013675Sdyson S_SWAP(i, j); 60113675Sdyson } 60218863Sdyson 60313907Sdyson /* Compute CRC32 over unencrypted data and apply RC4 to data */ 60413907Sdyson crc = ~0; 60513907Sdyson i = j = 0; 60679224Sdillon m = m0; 60791412Salfred pos = mtod(m, uint8_t *) + off; 60879224Sdillon buflen = m->m_len - off; 60918863Sdyson for (;;) { 61013907Sdyson if (buflen > data_len) 61113907Sdyson buflen = data_len; 61213907Sdyson data_len -= buflen; 61340286Sdg for (k = 0; k < buflen; k++) { 61476760Salfred crc = crc32_table[(crc ^ *pos) & 0xff] ^ (crc >> 8); 61576760Salfred i = (i + 1) & 0xff; 61613907Sdyson j = (j + S[i]) & 0xff; 61713907Sdyson S_SWAP(i, j); 61851474Sdillon *pos++ ^= S[(S[i] + S[j]) & 0xff]; 61951474Sdillon } 62013907Sdyson m = m->m_next; 62176760Salfred if (m == NULL) { 62276760Salfred KASSERT(data_len == 0, 62340700Sdg ("out of buffers with data_len %zu\n", data_len)); 62476760Salfred break; 62513907Sdyson } 62613907Sdyson pos = mtod(m, uint8_t *); 62713907Sdyson buflen = m->m_len; 62813907Sdyson } 62913907Sdyson crc = ~crc; 63013907Sdyson 63113907Sdyson /* Append little-endian CRC32 and encrypt it to produce ICV */ 63213907Sdyson icv[0] = crc; 63313907Sdyson icv[1] = crc >> 8; 63413907Sdyson icv[2] = crc >> 16; 63513907Sdyson icv[3] = crc >> 24; 63676760Salfred for (k = 0; k < IEEE80211_WEP_CRCLEN; k++) { 63776760Salfred i = (i + 1) & 0xff; 63813907Sdyson j = (j + S[i]) & 0xff; 63913907Sdyson S_SWAP(i, j); 64013907Sdyson icv[k] ^= S[(S[i] + S[j]) & 0xff]; 64113907Sdyson } 64213907Sdyson} 64313907Sdyson 64413912Sdysonstatic int 64513912Sdysonwep_decrypt(u8 *key, struct mbuf *m, u_int off, size_t data_len) 64613912Sdyson{ 64713912Sdyson u32 i, j, k, crc; 64813907Sdyson u8 S[256]; 64913912Sdyson u8 *pos, icv[4]; 65013912Sdyson size_t buflen; 65113907Sdyson 65213907Sdyson /* Setup RC4 state */ 65313907Sdyson for (i = 0; i < 256; i++) 65413907Sdyson S[i] = i; 65513907Sdyson j = 0; 65613907Sdyson for (i = 0; i < 256; i++) { 65713907Sdyson j = (j + S[i] + key[i & 0x0f]) & 0xff; 65813907Sdyson S_SWAP(i, j); 65913907Sdyson } 66013907Sdyson 66113907Sdyson /* Apply RC4 to data and compute CRC32 over decrypted data */ 66213907Sdyson crc = ~0; 66313907Sdyson i = j = 0; 66413907Sdyson pos = mtod(m, uint8_t *) + off; 66576760Salfred buflen = m->m_len - off; 66613907Sdyson for (;;) { 66713907Sdyson if (buflen > data_len) 66813907Sdyson buflen = data_len; 66913907Sdyson data_len -= buflen; 67013907Sdyson for (k = 0; k < buflen; k++) { 67113907Sdyson i = (i + 1) & 0xff; 67213907Sdyson j = (j + S[i]) & 0xff; 67376760Salfred S_SWAP(i, j); 67413907Sdyson *pos ^= S[(S[i] + S[j]) & 0xff]; 67513907Sdyson crc = crc32_table[(crc ^ *pos) & 0xff] ^ (crc >> 8); 67676364Salfred pos++; 67779224Sdillon } 67891412Salfred m = m->m_next; 67979224Sdillon if (m == NULL) { 68017163Sdyson KASSERT(data_len == 0, 68117163Sdyson ("out of buffers with data_len %zu\n", data_len)); 68213907Sdyson break; 68313907Sdyson } 68413907Sdyson pos = mtod(m, uint8_t *); 68513907Sdyson buflen = m->m_len; 68613907Sdyson } 68713912Sdyson crc = ~crc; 68813912Sdyson 68913907Sdyson /* Encrypt little-endian CRC32 and verify that it matches with the 69013907Sdyson * received ICV */ 69176760Salfred icv[0] = crc; 69240700Sdg icv[1] = crc >> 8; 69391653Stanimura icv[2] = crc >> 16; 69413907Sdyson icv[3] = crc >> 24; 69513907Sdyson for (k = 0; k < 4; k++) { 69613907Sdyson i = (i + 1) & 0xff; 69713907Sdyson j = (j + S[i]) & 0xff; 69813907Sdyson S_SWAP(i, j); 69913907Sdyson if ((icv[k] ^ S[(S[i] + S[j]) & 0xff]) != *pos++) { 70013907Sdyson /* ICV mismatch - drop frame */ 70113907Sdyson return -1; 70213907Sdyson } 70376364Salfred } 70413907Sdyson 70513907Sdyson return 0; 70613907Sdyson} 70713907Sdyson 70891362Salfred 70913907Sdysonstatic __inline u32 rotl(u32 val, int bits) 71013907Sdyson{ 71176760Salfred return (val << bits) | (val >> (32 - bits)); 71276760Salfred} 71313907Sdyson 71413907Sdyson 71513907Sdysonstatic __inline u32 rotr(u32 val, int bits) 71613907Sdyson{ 71713907Sdyson return (val >> bits) | (val << (32 - bits)); 71813907Sdyson} 71991412Salfred 72013907Sdyson 72191412Salfredstatic __inline u32 xswap(u32 val) 72213907Sdyson{ 72313907Sdyson return ((val & 0x00ff00ff) << 8) | ((val & 0xff00ff00) >> 8); 72413907Sdyson} 72513907Sdyson 72613907Sdyson 72713907Sdyson#define michael_block(l, r) \ 72813907Sdysondo { \ 72913907Sdyson r ^= rotl(l, 17); \ 73013907Sdyson l += r; \ 73113907Sdyson r ^= xswap(l); \ 73213907Sdyson l += r; \ 73313907Sdyson r ^= rotl(l, 3); \ 73413907Sdyson l += r; \ 73513907Sdyson r ^= rotr(l, 2); \ 73613907Sdyson l += r; \ 73776364Salfred} while (0) 73813951Sdyson 73991362Salfred 74013907Sdysonstatic __inline u32 get_le32_split(u8 b0, u8 b1, u8 b2, u8 b3) 74176760Salfred{ 74213951Sdyson return b0 | (b1 << 8) | (b2 << 16) | (b3 << 24); 74313951Sdyson} 74413951Sdyson 74513992Sdysonstatic __inline u32 get_le32(const u8 *p) 74691362Salfred{ 74791362Salfred return get_le32_split(p[0], p[1], p[2], p[3]); 74814802Sdyson} 74913907Sdyson 75014802Sdyson 75114802Sdysonstatic __inline void put_le32(u8 *p, u32 v) 75214802Sdyson{ 75314802Sdyson p[0] = v; 75413907Sdyson p[1] = v >> 8; 75513907Sdyson p[2] = v >> 16; 75613951Sdyson p[3] = v >> 24; 75776760Salfred} 75813951Sdyson 75913951Sdyson/* 76013951Sdyson * Craft pseudo header used to calculate the MIC. 76113951Sdyson */ 76213992Sdysonstatic void 76391362Salfredmichael_mic_hdr(const struct ieee80211_frame *wh0, uint8_t hdr[16]) 76491362Salfred{ 76514802Sdyson const struct ieee80211_frame_addr4 *wh = 76613907Sdyson (const struct ieee80211_frame_addr4 *) wh0; 76714802Sdyson 76814802Sdyson switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) { 76914802Sdyson case IEEE80211_FC1_DIR_NODS: 77013907Sdyson IEEE80211_ADDR_COPY(hdr, wh->i_addr1); /* DA */ 77113951Sdyson IEEE80211_ADDR_COPY(hdr + IEEE80211_ADDR_LEN, wh->i_addr2); 77213907Sdyson break; 77313907Sdyson case IEEE80211_FC1_DIR_TODS: 77413951Sdyson IEEE80211_ADDR_COPY(hdr, wh->i_addr3); /* DA */ 77513951Sdyson IEEE80211_ADDR_COPY(hdr + IEEE80211_ADDR_LEN, wh->i_addr2); 77692305Salfred break; 77791362Salfred case IEEE80211_FC1_DIR_FROMDS: 77813907Sdyson IEEE80211_ADDR_COPY(hdr, wh->i_addr1); /* DA */ 77991362Salfred IEEE80211_ADDR_COPY(hdr + IEEE80211_ADDR_LEN, wh->i_addr3); 78092305Salfred break; 78113907Sdyson case IEEE80211_FC1_DIR_DSTODS: 78213907Sdyson IEEE80211_ADDR_COPY(hdr, wh->i_addr3); /* DA */ 78313907Sdyson IEEE80211_ADDR_COPY(hdr + IEEE80211_ADDR_LEN, wh->i_addr4); 78413907Sdyson break; 78513907Sdyson } 78613907Sdyson 78713907Sdyson if (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_QOS) { 78813907Sdyson const struct ieee80211_qosframe *qwh = 78913907Sdyson (const struct ieee80211_qosframe *) wh; 79091362Salfred hdr[12] = qwh->i_qos[0] & IEEE80211_QOS_TID; 79113907Sdyson } else 79291362Salfred hdr[12] = 0; 79313907Sdyson hdr[13] = hdr[14] = hdr[15] = 0; /* reserved */ 79414037Sdyson} 79514802Sdyson 79614802Sdysonstatic void 79713907Sdysonmichael_mic(struct tkip_ctx *ctx, const u8 *key, 79813992Sdyson struct mbuf *m, u_int off, size_t data_len, 79913992Sdyson u8 mic[IEEE80211_WEP_MICLEN]) 80013992Sdyson{ 80113992Sdyson uint8_t hdr[16]; 80214037Sdyson u32 l, r; 80391362Salfred const uint8_t *data; 80491362Salfred u_int space; 80513907Sdyson 80613907Sdyson michael_mic_hdr(mtod(m, struct ieee80211_frame *), hdr); 80713907Sdyson 80813907Sdyson l = get_le32(key); 80913907Sdyson r = get_le32(key + 4); 81013907Sdyson 81113907Sdyson /* Michael MIC pseudo header: DA, SA, 3 x 0, Priority */ 81213907Sdyson l ^= get_le32(hdr); 81313907Sdyson michael_block(l, r); 81413907Sdyson l ^= get_le32(&hdr[4]); 81591412Salfred michael_block(l, r); 81613907Sdyson l ^= get_le32(&hdr[8]); 81791412Salfred michael_block(l, r); 81813907Sdyson l ^= get_le32(&hdr[12]); 81913907Sdyson michael_block(l, r); 82076760Salfred 82113907Sdyson /* first buffer has special handling */ 82213907Sdyson data = mtod(m, const uint8_t *) + off; 82313907Sdyson space = m->m_len - off; 82476760Salfred for (;;) { 82513907Sdyson if (space > data_len) 82614037Sdyson space = data_len; 82713907Sdyson /* collect 32-bit blocks from current buffer */ 82816960Sdyson while (space >= sizeof(uint32_t)) { 82983366Sjulian l ^= get_le32(data); 83016960Sdyson michael_block(l, r); 83113907Sdyson data += sizeof(uint32_t), space -= sizeof(uint32_t); 83216960Sdyson data_len -= sizeof(uint32_t); 83383366Sjulian } 83445311Sdt /* 83513907Sdyson * NB: when space is zero we make one more trip around 83613675Sdyson * the loop to advance to the next mbuf where there is 83713913Sdyson * data. This handles the case where there are 4*n 83816960Sdyson * bytes in an mbuf followed by <4 bytes in a later mbuf. 83916960Sdyson * By making an extra trip we'll drop out of the loop 84016960Sdyson * with m pointing at the mbuf with 3 bytes and space 84116960Sdyson * set as required by the remainder handling below. 84216960Sdyson */ 84391395Salfred if (data_len == 0 || 84413675Sdyson (data_len < sizeof(uint32_t) && space != 0)) 84513675Sdyson break; 84613675Sdyson m = m->m_next; 84716960Sdyson if (m == NULL) { 84891395Salfred KASSERT(0, ("out of data, data_len %zu\n", data_len)); 84976760Salfred break; 85013675Sdyson } 85177676Sdillon if (space != 0) { 85213675Sdyson const uint8_t *data_next; 85317163Sdyson /* 85417163Sdyson * Block straddles buffers, split references. 85517163Sdyson */ 85617163Sdyson data_next = mtod(m, const uint8_t *); 85717163Sdyson KASSERT(m->m_len >= sizeof(uint32_t) - space, 85817163Sdyson ("not enough data in following buffer, " 85917163Sdyson "m_len %u need %zu\n", m->m_len, 86017163Sdyson sizeof(uint32_t) - space)); 86117163Sdyson switch (space) { 86217163Sdyson case 1: 86313907Sdyson l ^= get_le32_split(data[0], data_next[0], 86492305Salfred data_next[1], data_next[2]); 86576364Salfred data = data_next + 3; 86676364Salfred space = m->m_len - 3; 86792305Salfred break; 86813907Sdyson case 2: 86913907Sdyson l ^= get_le32_split(data[0], data[1], 87013907Sdyson data_next[0], data_next[1]); 87177676Sdillon data = data_next + 2; 87277676Sdillon space = m->m_len - 2; 87377676Sdillon break; 87477676Sdillon case 3: 87577676Sdillon l ^= get_le32_split(data[0], data[1], 87677676Sdillon data[2], data_next[0]); 87777676Sdillon data = data_next + 1; 87877676Sdillon space = m->m_len - 1; 87977676Sdillon break; 88077676Sdillon } 88177676Sdillon michael_block(l, r); 88277676Sdillon data_len -= sizeof(uint32_t); 88391395Salfred } else { 88477676Sdillon /* 88577676Sdillon * Setup for next buffer. 88676364Salfred */ 88776364Salfred data = mtod(m, const uint8_t *); 88813907Sdyson space = m->m_len; 88913913Sdyson } 89077676Sdillon } 89113675Sdyson /* 89213907Sdyson * Catch degenerate cases like mbuf[4*n+1 bytes] followed by 89376760Salfred * mbuf[2 bytes]. I don't believe these should happen; if they 89414037Sdyson * do then we'll need more involved logic. 89513907Sdyson */ 89613907Sdyson KASSERT(data_len <= space, 89713907Sdyson ("not enough data, data_len %zu space %u\n", data_len, space)); 89816416Sdyson 89916416Sdyson /* Last block and padding (0x5a, 4..7 x 0) */ 90058505Sdillon switch (data_len) { 90158505Sdillon case 0: 90258505Sdillon l ^= get_le32_split(0x5a, 0, 0, 0); 90313907Sdyson break; 90417163Sdyson case 1: 90517163Sdyson l ^= get_le32_split(data[0], 0x5a, 0, 0); 90617163Sdyson break; 90713907Sdyson case 2: 90813907Sdyson l ^= get_le32_split(data[0], data[1], 0x5a, 0); 90976760Salfred break; 91013907Sdyson case 3: 91113907Sdyson l ^= get_le32_split(data[0], data[1], data[2], 0x5a); 91291362Salfred break; 91314037Sdyson } 91413907Sdyson michael_block(l, r); 91513907Sdyson /* l ^= 0; */ 91613907Sdyson michael_block(l, r); 91713907Sdyson 91813907Sdyson put_le32(mic, l); 91958505Sdillon put_le32(mic + 4, r); 92058505Sdillon} 92113907Sdyson 92213907Sdysonstatic int 92313907Sdysontkip_encrypt(struct tkip_ctx *ctx, struct ieee80211_key *key, 92413992Sdyson struct mbuf *m, int hdrlen) 92513992Sdyson{ 92613992Sdyson struct ieee80211_frame *wh; 92713992Sdyson uint8_t icv[IEEE80211_WEP_CRCLEN]; 92891395Salfred 92991362Salfred ctx->tc_vap->iv_stats.is_crypto_tkip++; 93058505Sdillon 93158505Sdillon wh = mtod(m, struct ieee80211_frame *); 93213907Sdyson if (!ctx->tx_phase1_done) { 93313907Sdyson tkip_mixing_phase1(ctx->tx_ttak, key->wk_key, wh->i_addr2, 93413907Sdyson (u32)(key->wk_keytsc >> 16)); 93558505Sdillon ctx->tx_phase1_done = 1; 93658505Sdillon } 93758505Sdillon tkip_mixing_phase2(ctx->tx_rc4key, key->wk_key, ctx->tx_ttak, 93858505Sdillon (u16) key->wk_keytsc); 93913907Sdyson 94013907Sdyson wep_encrypt(ctx->tx_rc4key, 94114644Sdyson m, hdrlen + tkip.ic_header, 94214644Sdyson m->m_pkthdr.len - (hdrlen + tkip.ic_header), 94313913Sdyson icv); 94413913Sdyson (void) m_append(m, IEEE80211_WEP_CRCLEN, icv); /* XXX check return */ 94513907Sdyson 94617163Sdyson key->wk_keytsc++; 94713907Sdyson if ((u16)(key->wk_keytsc) == 0) 94854534Stegge ctx->tx_phase1_done = 0; 94954534Stegge return 1; 95076760Salfred} 95113907Sdyson 95213907Sdysonstatic int 95313907Sdysontkip_decrypt(struct tkip_ctx *ctx, struct ieee80211_key *key, 95413907Sdyson struct mbuf *m, int hdrlen) 95513907Sdyson{ 95613907Sdyson struct ieee80211_frame *wh; 95713907Sdyson struct ieee80211vap *vap = ctx->tc_vap; 95813907Sdyson u32 iv32; 95954534Stegge u16 iv16; 96054534Stegge u8 tid; 96154534Stegge 96258505Sdillon vap->iv_stats.is_crypto_tkip++; 96358505Sdillon 96458505Sdillon wh = mtod(m, struct ieee80211_frame *); 96554534Stegge /* NB: tkip_decap already verified header and left seq in rx_rsc */ 96654534Stegge iv16 = (u16) ctx->rx_rsc; 96754534Stegge iv32 = (u32) (ctx->rx_rsc >> 16); 96854534Stegge 96954534Stegge tid = ieee80211_gettid(wh); 97054534Stegge if (iv32 != (u32)(key->wk_keyrsc[tid] >> 16) || !ctx->rx_phase1_done) { 97154534Stegge tkip_mixing_phase1(ctx->rx_ttak, key->wk_key, 97254534Stegge wh->i_addr2, iv32); 97354534Stegge ctx->rx_phase1_done = 1; 97454534Stegge } 97554534Stegge tkip_mixing_phase2(ctx->rx_rc4key, key->wk_key, ctx->rx_ttak, iv16); 97654534Stegge 97754534Stegge /* NB: m is unstripped; deduct headers + ICV to get payload */ 97854534Stegge if (wep_decrypt(ctx->rx_rc4key, 97954534Stegge m, hdrlen + tkip.ic_header, 98054534Stegge m->m_pkthdr.len - (hdrlen + tkip.ic_header + tkip.ic_trailer))) { 98154534Stegge if (iv32 != (u32)(key->wk_keyrsc[tid] >> 16)) { 98254534Stegge /* Previously cached Phase1 result was already lost, so 98354534Stegge * it needs to be recalculated for the next packet. */ 98454534Stegge ctx->rx_phase1_done = 0; 98554534Stegge } 98654534Stegge IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO, wh->i_addr2, 98754534Stegge "%s", "TKIP ICV mismatch on decrypt"); 98854534Stegge vap->iv_stats.is_rx_tkipicv++; 98954534Stegge return 0; 99054534Stegge } 99154534Stegge return 1; 99254534Stegge} 99354534Stegge 99491395Salfred/* 99554534Stegge * Module glue. 99654534Stegge */ 99791395SalfredIEEE80211_CRYPTO_MODULE(tkip, 1); 99854534Stegge