From: Tomas Winkler <tomas.winkler@xxxxxxxxx> This patch fixes TKIP encryption for fragmented packets. Each fragmet needs it's own phase2 key. Signed-off-by: Tomas Winkler <tomas.winkler@xxxxxxxxx> Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@xxxxxxxxx> --- net/mac80211/ieee80211_i.h | 2 ++ net/mac80211/tx.c | 12 ++++++++++++ net/mac80211/wpa.c | 18 +++++++++++++----- 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 7f10ff5..5c7b8e2 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -156,6 +156,7 @@ struct ieee80211_tx_data { struct sta_info *sta; u16 fc, ethertype; struct ieee80211_key *key; + u8 tkip_key[16]; unsigned int flags; struct ieee80211_tx_control *control; @@ -170,6 +171,7 @@ struct ieee80211_tx_data { * in skb) */ int num_extra_frag; struct sk_buff **extra_frag; + u8 *frag_tkip_key; /* size 16 * num_extra_frag */ }; diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 80f4343..ee09464 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1078,6 +1078,11 @@ static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb, if (skb) { ieee80211_dump_frame(wiphy_name(local->hw.wiphy), "TX to low-level driver", skb); + + if (tx->key && (tx->key->conf.flags & + IEEE80211_KEY_FLAG_TKIP_REQ_TX_P2_KEY)) + memcpy(control->tkip_key, tx->tkip_key, 16); + ret = local->ops->tx(local_to_hw(local), skb, control); if (ret) return IEEE80211_TX_AGAIN; @@ -1092,6 +1097,11 @@ static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb, for (i = 0; i < tx->num_extra_frag; i++) { if (!tx->extra_frag[i]) continue; + + if (tx->frag_tkip_key) + memcpy(control->tkip_key, + &tx->frag_tkip_key[i * 16], 16); + if (__ieee80211_queue_stopped(local, control->queue)) return IEEE80211_TX_FRAG_AGAIN; if (i == tx->num_extra_frag) { @@ -1119,6 +1129,8 @@ static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb, } kfree(tx->extra_frag); tx->extra_frag = NULL; + kfree(tx->frag_tkip_key); + tx->frag_tkip_key = NULL; } return IEEE80211_TX_OK; } diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index cc1702e..60f2349 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c @@ -228,10 +228,8 @@ static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, 0x7f), (u8) key->u.tkip.iv16); - if (key->conf.flags & IEEE80211_KEY_FLAG_TKIP_REQ_TX_P2_KEY) - ieee80211_tkip_gen_rc4key(key, hdr->addr2, - tx->control->tkip_key); tx->control->key_idx = tx->key->conf.hw_key_idx; + return 0; } @@ -249,6 +247,7 @@ ieee80211_tx_result ieee80211_crypto_tkip_encrypt(struct ieee80211_tx_data *tx) { struct sk_buff *skb = tx->skb; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; int wpa_test = 0, test = 0; tx->control->icv_len = TKIP_ICV_LEN; @@ -266,12 +265,21 @@ ieee80211_crypto_tkip_encrypt(struct ieee80211_tx_data *tx) if (tkip_encrypt_skb(tx, skb, test) < 0) return TX_DROP; + if (tx->key->conf.flags & IEEE80211_KEY_FLAG_TKIP_REQ_TX_P2_KEY) + ieee80211_tkip_gen_rc4key(tx->key, hdr->addr2, tx->tkip_key); + + if (tx->extra_frag) { int i; + if (tx->key->conf.flags & IEEE80211_KEY_FLAG_TKIP_REQ_TX_P2_KEY) + tx->frag_tkip_key = + kzalloc(tx->num_extra_frag * 16, GFP_ATOMIC); for (i = 0; i < tx->num_extra_frag; i++) { - if (tkip_encrypt_skb(tx, tx->extra_frag[i], test) - < 0) + if (tkip_encrypt_skb(tx, tx->extra_frag[i], test) < 0) return TX_DROP; + if (tx->key->conf.flags & IEEE80211_KEY_FLAG_TKIP_REQ_TX_P2_KEY) + ieee80211_tkip_gen_rc4key(tx->key, hdr->addr2, + &tx->frag_tkip_key[i * 16]); } } -- 1.5.3.4 -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html