From owner-p4-projects@FreeBSD.ORG Tue Jul 29 16:24:40 2008 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 7EDF71065673; Tue, 29 Jul 2008 16:24:40 +0000 (UTC) Delivered-To: perforce@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 42D201065672 for ; Tue, 29 Jul 2008 16:24:40 +0000 (UTC) (envelope-from sam@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id DE0FD8FC15 for ; Tue, 29 Jul 2008 16:24:39 +0000 (UTC) (envelope-from sam@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.2/8.14.2) with ESMTP id m6TGOd3q042165 for ; Tue, 29 Jul 2008 16:24:39 GMT (envelope-from sam@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.2/8.14.1/Submit) id m6TGOdLq042163 for perforce@freebsd.org; Tue, 29 Jul 2008 16:24:39 GMT (envelope-from sam@freebsd.org) Date: Tue, 29 Jul 2008 16:24:39 GMT Message-Id: <200807291624.m6TGOdLq042163@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to sam@freebsd.org using -f From: Sam Leffler To: Perforce Change Reviews Cc: Subject: PERFORCE change 146211 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 29 Jul 2008 16:24:40 -0000 http://perforce.freebsd.org/chv.cgi?CH=146211 Change 146211 by sam@sam_ebb on 2008/07/29 16:24:34 Changes to support devices that require the phase 1 ttak: o add new key flags IEEE80211_KEY_CIPHER[01] for use by cipher modules (and drivers) o change TKIP to use IEEE80211_KEY_CIPHER0 to calculate the phase 1 ttak on transmit and pre-calculate the initial receive hash on key change; this enables use by devices such as the Intel 4965 Affected files ... .. //depot/projects/vap/sys/net80211/ieee80211_crypto.h#19 edit .. //depot/projects/vap/sys/net80211/ieee80211_crypto_tkip.c#14 edit Differences ... ==== //depot/projects/vap/sys/net80211/ieee80211_crypto.h#19 (text+ko) ==== @@ -83,6 +83,8 @@ #define IEEE80211_KEY_SWENMIC 0x0040 /* host-based enmic */ #define IEEE80211_KEY_SWDEMIC 0x0080 /* host-based demic */ #define IEEE80211_KEY_DEVKEY 0x0100 /* device key request completed */ +#define IEEE80211_KEY_CIPHER0 0x1000 /* cipher-specific action 0 */ +#define IEEE80211_KEY_CIPHER1 0x2000 /* cipher-specific action 1 */ ieee80211_keyix wk_keyix; /* h/w key index */ ieee80211_keyix wk_rxkeyix; /* optional h/w rx key index */ uint8_t wk_key[IEEE80211_KEYBUF_SIZE+IEEE80211_MICBUF_SIZE]; ==== //depot/projects/vap/sys/net80211/ieee80211_crypto_tkip.c#14 (text+ko) ==== @@ -96,10 +96,14 @@ static void michael_mic(struct tkip_ctx *, const u8 *key, struct mbuf *m, u_int off, size_t data_len, u8 mic[IEEE80211_WEP_MICLEN]); -static int tkip_encrypt(struct tkip_ctx *, struct ieee80211_key *, - struct mbuf *, int hdr_len); -static int tkip_decrypt(struct tkip_ctx *, struct ieee80211_key *, - struct mbuf *, int hdr_len); + +static void tkip_mixing_phase1(u16 *TTAK, const u8 *TK, const u8 *TA, + u32 IV32); +static void tkip_mixing_phase2(u8 *WEPSeed, const u8 *TK, const u16 *TTAK, + u16 IV16); +static void wep_encrypt(u8 *key, struct mbuf *m0, u_int off, size_t data_len, + uint8_t icv[IEEE80211_WEP_CRCLEN]); +static int wep_decrypt(u8 *key, struct mbuf *m, u_int off, size_t data_len); /* number of references from net80211 layer */ static int nrefs = 0; @@ -144,6 +148,20 @@ return 0; } k->wk_keytsc = 1; /* TSC starts at 1 */ + if (k->wk_flags & IEEE80211_KEY_CIPHER0) { + /* + * We're responsible for Phase 1 calcs for transmit but + * for receive the hardware needs an initial value + * pre-calculated. + * + * NB: this only works for unicast keys + * NB: we assume the rsc is the same for all tid's + */ + KASSERT((k->wk_flags & IEEE80211_KEY_SWDECRYPT) == 0, + ("CIPHER0+SWDECRYPT not supported")); + tkip_mixing_phase1(ctx->rx_ttak, k->wk_key, k->wk_macaddr, + (u32)(k->wk_keyrsc[0] >> 16)); + } return 1; } @@ -196,10 +214,33 @@ /* * Finally, do software encrypt if neeed. */ - if (k->wk_flags & IEEE80211_KEY_SWENCRYPT) { - if (!tkip_encrypt(ctx, k, m, hdrlen)) - return 0; - /* NB: tkip_encrypt handles wk_keytsc */ + if (k->wk_flags & (IEEE80211_KEY_SWENCRYPT | IEEE80211_KEY_CIPHER0)) { + struct ieee80211_frame *wh; + + wh = mtod(m, struct ieee80211_frame *); + if (!ctx->tx_phase1_done) { + tkip_mixing_phase1(ctx->tx_ttak, k->wk_key, + wh->i_addr2, (u32)(k->wk_keytsc >> 16)); + ctx->tx_phase1_done = 1; + } + if (k->wk_flags & IEEE80211_KEY_SWENCRYPT) { + uint8_t icv[IEEE80211_WEP_CRCLEN]; + + tkip_mixing_phase2(ctx->tx_rc4key, k->wk_key, + ctx->tx_ttak, (u16) k->wk_keytsc); + + vap->iv_stats.is_crypto_tkip++; + + wep_encrypt(ctx->tx_rc4key, + m, hdrlen + tkip.ic_header, + m->m_pkthdr.len - (hdrlen + tkip.ic_header), + icv); + /* XXX check return */ + (void) m_append(m, IEEE80211_WEP_CRCLEN, icv); + } + k->wk_keytsc++; + if ((u16)(k->wk_keytsc) == 0) + ctx->tx_phase1_done = 0; } else k->wk_keytsc++; @@ -302,9 +343,46 @@ * If so we just strip the header; otherwise we need to * handle the decrypt in software. */ - if ((k->wk_flags & IEEE80211_KEY_SWDECRYPT) && - !tkip_decrypt(ctx, k, m, hdrlen)) - return 0; + if (k->wk_flags & IEEE80211_KEY_SWDECRYPT) { + u32 iv32; + + /* NB: already verified header and left seq # in rx_rsc */ + iv32 = (u32) (ctx->rx_rsc >> 16); + + if (iv32 != (u32)(k->wk_keyrsc[tid] >> 16) || + !ctx->rx_phase1_done) { + tkip_mixing_phase1(ctx->rx_ttak, k->wk_key, + wh->i_addr2, iv32); + ctx->rx_phase1_done = 1; + } + + tkip_mixing_phase2(ctx->rx_rc4key, k->wk_key, + ctx->rx_ttak, (u16) ctx->rx_rsc); + + vap->iv_stats.is_crypto_tkip++; + + /* + * NB: m is unstripped; deduct headers + ICV + * to get payload + */ + if (wep_decrypt(ctx->rx_rc4key, + m, hdrlen + tkip.ic_header, + m->m_pkthdr.len - (hdrlen + tkip.ic_header + tkip.ic_trailer))) { + if (iv32 != (u32)(k->wk_keyrsc[tid] >> 16)) { + /* + * Previously cached Phase1 result was + * already lost, so it needs to be + * recalculated for the next packet. + */ + ctx->rx_phase1_done = 0; + } + IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO, + wh->i_addr2, + "%s", "TKIP ICV mismatch on decrypt"); + vap->iv_stats.is_rx_tkipicv++; + return 0; + } + } /* * Copy up 802.11 header and strip crypto bits. @@ -509,7 +587,8 @@ #define PHASE1_LOOP_COUNT 8 -static void tkip_mixing_phase1(u16 *TTAK, const u8 *TK, const u8 *TA, u32 IV32) +static void +tkip_mixing_phase1(u16 *TTAK, const u8 *TK, const u8 *TA, u32 IV32) { int i, j; @@ -901,78 +980,6 @@ put_le32(mic + 4, r); } -static int -tkip_encrypt(struct tkip_ctx *ctx, struct ieee80211_key *key, - struct mbuf *m, int hdrlen) -{ - struct ieee80211_frame *wh; - uint8_t icv[IEEE80211_WEP_CRCLEN]; - - ctx->tc_vap->iv_stats.is_crypto_tkip++; - - wh = mtod(m, struct ieee80211_frame *); - if (!ctx->tx_phase1_done) { - tkip_mixing_phase1(ctx->tx_ttak, key->wk_key, wh->i_addr2, - (u32)(key->wk_keytsc >> 16)); - ctx->tx_phase1_done = 1; - } - tkip_mixing_phase2(ctx->tx_rc4key, key->wk_key, ctx->tx_ttak, - (u16) key->wk_keytsc); - - wep_encrypt(ctx->tx_rc4key, - m, hdrlen + tkip.ic_header, - m->m_pkthdr.len - (hdrlen + tkip.ic_header), - icv); - (void) m_append(m, IEEE80211_WEP_CRCLEN, icv); /* XXX check return */ - - key->wk_keytsc++; - if ((u16)(key->wk_keytsc) == 0) - ctx->tx_phase1_done = 0; - return 1; -} - -static int -tkip_decrypt(struct tkip_ctx *ctx, struct ieee80211_key *key, - struct mbuf *m, int hdrlen) -{ - struct ieee80211_frame *wh; - struct ieee80211vap *vap = ctx->tc_vap; - u32 iv32; - u16 iv16; - u8 tid; - - vap->iv_stats.is_crypto_tkip++; - - wh = mtod(m, struct ieee80211_frame *); - /* NB: tkip_decap already verified header and left seq in rx_rsc */ - iv16 = (u16) ctx->rx_rsc; - iv32 = (u32) (ctx->rx_rsc >> 16); - - tid = ieee80211_gettid(wh); - if (iv32 != (u32)(key->wk_keyrsc[tid] >> 16) || !ctx->rx_phase1_done) { - tkip_mixing_phase1(ctx->rx_ttak, key->wk_key, - wh->i_addr2, iv32); - ctx->rx_phase1_done = 1; - } - tkip_mixing_phase2(ctx->rx_rc4key, key->wk_key, ctx->rx_ttak, iv16); - - /* NB: m is unstripped; deduct headers + ICV to get payload */ - if (wep_decrypt(ctx->rx_rc4key, - m, hdrlen + tkip.ic_header, - m->m_pkthdr.len - (hdrlen + tkip.ic_header + tkip.ic_trailer))) { - if (iv32 != (u32)(key->wk_keyrsc[tid] >> 16)) { - /* Previously cached Phase1 result was already lost, so - * it needs to be recalculated for the next packet. */ - ctx->rx_phase1_done = 0; - } - IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO, wh->i_addr2, - "%s", "TKIP ICV mismatch on decrypt"); - vap->iv_stats.is_rx_tkipicv++; - return 0; - } - return 1; -} - /* * Module glue. */