PERFORCE change 146211 for review
Sam Leffler
sam at FreeBSD.org
Tue Jul 29 16:24:40 UTC 2008
http://perforce.freebsd.org/chv.cgi?CH=146211
Change 146211 by sam at 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.
*/
More information about the p4-projects
mailing list