Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mac80211: move TKIP TX IVs to public part of key struct

Some drivers/devices might want to set the IVs by
themselves (and still let mac80211 generate MMIC).

Specifically, this is needed when the device does
offloading at certain times, and the driver has
to make sure that the IVs of new tx frames (from
the host) are synchronized with IVs that were
potentially used during the offloading.

Similarly to CCMP, move the TX IVs of TKIP keys to the
public part of the key struct, and export a function
to add the IV right into the crypto header.

The public tx_pn field is defined as atomic64, so define
TKIP_PN_TO_IV16/32 helper macros to convert it to iv16/32
when needed.

Since the iv32 used for the p1k cache is taken
directly from the frame, we can safely remove
iv16/32 from being protected by tkip.txlock.

Signed-off-by: Eliad Peller <eliadx.peller@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>

authored by

Eliad Peller and committed by
Johannes Berg
f8079d43 109843b0

+60 -41
+20 -3
include/net/mac80211.h
··· 1521 1521 * wants to be given when a frame is transmitted and needs to be 1522 1522 * encrypted in hardware. 1523 1523 * @cipher: The key's cipher suite selector. 1524 - * @tx_pn: PN used for TX on non-TKIP keys, may be used by the driver 1525 - * as well if it needs to do software PN assignment by itself 1526 - * (e.g. due to TSO) 1524 + * @tx_pn: PN used for TX keys, may be used by the driver as well if it 1525 + * needs to do software PN assignment by itself (e.g. due to TSO) 1527 1526 * @flags: key flags, see &enum ieee80211_key_flags. 1528 1527 * @keyidx: the key index (0-3) 1529 1528 * @keylen: key material length ··· 1547 1548 }; 1548 1549 1549 1550 #define IEEE80211_MAX_PN_LEN 16 1551 + 1552 + #define TKIP_PN_TO_IV16(pn) ((u16)(pn & 0xffff)) 1553 + #define TKIP_PN_TO_IV32(pn) ((u32)((pn >> 16) & 0xffffffff)) 1550 1554 1551 1555 /** 1552 1556 * struct ieee80211_key_seq - key sequence counter ··· 4447 4445 */ 4448 4446 void ieee80211_get_tkip_p2k(struct ieee80211_key_conf *keyconf, 4449 4447 struct sk_buff *skb, u8 *p2k); 4448 + 4449 + /** 4450 + * ieee80211_tkip_add_iv - write TKIP IV and Ext. IV to pos 4451 + * 4452 + * @pos: start of crypto header 4453 + * @keyconf: the parameter passed with the set key 4454 + * @pn: PN to add 4455 + * 4456 + * Returns: pointer to the octet following IVs (i.e. beginning of 4457 + * the packet payload) 4458 + * 4459 + * This function writes the tkip IV value to pos (which should 4460 + * point to the crypto header) 4461 + */ 4462 + u8 *ieee80211_tkip_add_iv(u8 *pos, struct ieee80211_key_conf *keyconf, u64 pn); 4450 4463 4451 4464 /** 4452 4465 * ieee80211_get_key_tx_seq - get key TX sequence counter
+3 -2
net/mac80211/cfg.c
··· 339 339 340 340 switch (key->conf.cipher) { 341 341 case WLAN_CIPHER_SUITE_TKIP: 342 - iv32 = key->u.tkip.tx.iv32; 343 - iv16 = key->u.tkip.tx.iv16; 342 + pn64 = atomic64_read(&key->conf.tx_pn); 343 + iv32 = TKIP_PN_TO_IV32(pn64); 344 + iv16 = TKIP_PN_TO_IV16(pn64); 344 345 345 346 if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE && 346 347 !(key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) {
+3 -2
net/mac80211/debugfs_key.c
··· 132 132 len = scnprintf(buf, sizeof(buf), "\n"); 133 133 break; 134 134 case WLAN_CIPHER_SUITE_TKIP: 135 + pn = atomic64_read(&key->conf.tx_pn); 135 136 len = scnprintf(buf, sizeof(buf), "%08x %04x\n", 136 - key->u.tkip.tx.iv32, 137 - key->u.tkip.tx.iv16); 137 + TKIP_PN_TO_IV32(pn), 138 + TKIP_PN_TO_IV16(pn)); 138 139 break; 139 140 case WLAN_CIPHER_SUITE_CCMP: 140 141 case WLAN_CIPHER_SUITE_CCMP_256:
+5 -4
net/mac80211/key.c
··· 945 945 946 946 switch (key->conf.cipher) { 947 947 case WLAN_CIPHER_SUITE_TKIP: 948 - seq->tkip.iv32 = key->u.tkip.tx.iv32; 949 - seq->tkip.iv16 = key->u.tkip.tx.iv16; 948 + pn64 = atomic64_read(&key->conf.tx_pn); 949 + seq->tkip.iv32 = TKIP_PN_TO_IV32(pn64); 950 + seq->tkip.iv16 = TKIP_PN_TO_IV16(pn64); 950 951 break; 951 952 case WLAN_CIPHER_SUITE_CCMP: 952 953 case WLAN_CIPHER_SUITE_CCMP_256: ··· 1040 1039 1041 1040 switch (key->conf.cipher) { 1042 1041 case WLAN_CIPHER_SUITE_TKIP: 1043 - key->u.tkip.tx.iv32 = seq->tkip.iv32; 1044 - key->u.tkip.tx.iv16 = seq->tkip.iv16; 1042 + pn64 = (u64)seq->tkip.iv16 | ((u64)seq->tkip.iv32 << 16); 1043 + atomic64_set(&key->conf.tx_pn, pn64); 1045 1044 break; 1046 1045 case WLAN_CIPHER_SUITE_CCMP: 1047 1046 case WLAN_CIPHER_SUITE_CCMP_256:
+7 -3
net/mac80211/key.h
··· 44 44 }; 45 45 46 46 struct tkip_ctx { 47 - u32 iv32; /* current iv32 */ 48 - u16 iv16; /* current iv16 */ 49 47 u16 p1k[5]; /* p1k cache */ 50 48 u32 p1k_iv32; /* iv32 for which p1k computed */ 51 49 enum ieee80211_internal_tkip_state state; 50 + }; 51 + 52 + struct tkip_ctx_rx { 53 + struct tkip_ctx ctx; 54 + u32 iv32; /* current iv32 */ 55 + u16 iv16; /* current iv16 */ 52 56 }; 53 57 54 58 struct ieee80211_key { ··· 75 71 struct tkip_ctx tx; 76 72 77 73 /* last received RSC */ 78 - struct tkip_ctx rx[IEEE80211_NUM_TIDS]; 74 + struct tkip_ctx_rx rx[IEEE80211_NUM_TIDS]; 79 75 80 76 /* number of mic failures */ 81 77 u32 mic_failures;
+18 -18
net/mac80211/tkip.c
··· 1 1 /* 2 2 * Copyright 2002-2004, Instant802 Networks, Inc. 3 3 * Copyright 2005, Devicescape Software, Inc. 4 + * Copyright (C) 2016 Intel Deutschland GmbH 4 5 * 5 6 * This program is free software; you can redistribute it and/or modify 6 7 * it under the terms of the GNU General Public License version 2 as ··· 143 142 /* Add TKIP IV and Ext. IV at @pos. @iv0, @iv1, and @iv2 are the first octets 144 143 * of the IV. Returns pointer to the octet following IVs (i.e., beginning of 145 144 * the packet payload). */ 146 - u8 *ieee80211_tkip_add_iv(u8 *pos, struct ieee80211_key *key) 145 + u8 *ieee80211_tkip_add_iv(u8 *pos, struct ieee80211_key_conf *keyconf, u64 pn) 147 146 { 148 - lockdep_assert_held(&key->u.tkip.txlock); 149 - 150 - pos = write_tkip_iv(pos, key->u.tkip.tx.iv16); 151 - *pos++ = (key->conf.keyidx << 6) | (1 << 5) /* Ext IV */; 152 - put_unaligned_le32(key->u.tkip.tx.iv32, pos); 147 + pos = write_tkip_iv(pos, TKIP_PN_TO_IV16(pn)); 148 + *pos++ = (keyconf->keyidx << 6) | (1 << 5) /* Ext IV */; 149 + put_unaligned_le32(TKIP_PN_TO_IV32(pn), pos); 153 150 return pos + 4; 154 151 } 152 + EXPORT_SYMBOL_GPL(ieee80211_tkip_add_iv); 155 153 156 154 static void ieee80211_compute_tkip_p1k(struct ieee80211_key *key, u32 iv32) 157 155 { ··· 250 250 u8 rc4key[16], keyid, *pos = payload; 251 251 int res; 252 252 const u8 *tk = &key->conf.key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY]; 253 + struct tkip_ctx_rx *rx_ctx = &key->u.tkip.rx[queue]; 253 254 254 255 if (payload_len < 12) 255 256 return -1; ··· 266 265 if ((keyid >> 6) != key->conf.keyidx) 267 266 return TKIP_DECRYPT_INVALID_KEYIDX; 268 267 269 - if (key->u.tkip.rx[queue].state != TKIP_STATE_NOT_INIT && 270 - (iv32 < key->u.tkip.rx[queue].iv32 || 271 - (iv32 == key->u.tkip.rx[queue].iv32 && 272 - iv16 <= key->u.tkip.rx[queue].iv16))) 268 + if (rx_ctx->ctx.state != TKIP_STATE_NOT_INIT && 269 + (iv32 < rx_ctx->iv32 || 270 + (iv32 == rx_ctx->iv32 && iv16 <= rx_ctx->iv16))) 273 271 return TKIP_DECRYPT_REPLAY; 274 272 275 273 if (only_iv) { 276 274 res = TKIP_DECRYPT_OK; 277 - key->u.tkip.rx[queue].state = TKIP_STATE_PHASE1_HW_UPLOADED; 275 + rx_ctx->ctx.state = TKIP_STATE_PHASE1_HW_UPLOADED; 278 276 goto done; 279 277 } 280 278 281 - if (key->u.tkip.rx[queue].state == TKIP_STATE_NOT_INIT || 282 - key->u.tkip.rx[queue].iv32 != iv32) { 279 + if (rx_ctx->ctx.state == TKIP_STATE_NOT_INIT || 280 + rx_ctx->iv32 != iv32) { 283 281 /* IV16 wrapped around - perform TKIP phase 1 */ 284 - tkip_mixing_phase1(tk, &key->u.tkip.rx[queue], ta, iv32); 282 + tkip_mixing_phase1(tk, &rx_ctx->ctx, ta, iv32); 285 283 } 286 284 if (key->local->ops->update_tkip_key && 287 285 key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE && 288 - key->u.tkip.rx[queue].state != TKIP_STATE_PHASE1_HW_UPLOADED) { 286 + rx_ctx->ctx.state != TKIP_STATE_PHASE1_HW_UPLOADED) { 289 287 struct ieee80211_sub_if_data *sdata = key->sdata; 290 288 291 289 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) 292 290 sdata = container_of(key->sdata->bss, 293 291 struct ieee80211_sub_if_data, u.ap); 294 292 drv_update_tkip_key(key->local, sdata, &key->conf, key->sta, 295 - iv32, key->u.tkip.rx[queue].p1k); 296 - key->u.tkip.rx[queue].state = TKIP_STATE_PHASE1_HW_UPLOADED; 293 + iv32, rx_ctx->ctx.p1k); 294 + rx_ctx->ctx.state = TKIP_STATE_PHASE1_HW_UPLOADED; 297 295 } 298 296 299 - tkip_mixing_phase2(tk, &key->u.tkip.rx[queue], iv16, rc4key); 297 + tkip_mixing_phase2(tk, &rx_ctx->ctx, iv16, rc4key); 300 298 301 299 res = ieee80211_wep_decrypt_data(tfm, rc4key, 16, pos, payload_len - 12); 302 300 done:
-2
net/mac80211/tkip.h
··· 13 13 #include <linux/crypto.h> 14 14 #include "key.h" 15 15 16 - u8 *ieee80211_tkip_add_iv(u8 *pos, struct ieee80211_key *key); 17 - 18 16 int ieee80211_tkip_encrypt_data(struct crypto_cipher *tfm, 19 17 struct ieee80211_key *key, 20 18 struct sk_buff *skb,
+4 -7
net/mac80211/wpa.c
··· 1 1 /* 2 2 * Copyright 2002-2004, Instant802 Networks, Inc. 3 3 * Copyright 2008, Jouni Malinen <j@w1.fi> 4 + * Copyright (C) 2016 Intel Deutschland GmbH 4 5 * 5 6 * This program is free software; you can redistribute it and/or modify 6 7 * it under the terms of the GNU General Public License version 2 as ··· 184 183 return RX_DROP_UNUSABLE; 185 184 } 186 185 187 - 188 186 static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) 189 187 { 190 188 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; ··· 191 191 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 192 192 unsigned int hdrlen; 193 193 int len, tail; 194 + u64 pn; 194 195 u8 *pos; 195 196 196 197 if (info->control.hw_key && ··· 223 222 return 0; 224 223 225 224 /* Increase IV for the frame */ 226 - spin_lock(&key->u.tkip.txlock); 227 - key->u.tkip.tx.iv16++; 228 - if (key->u.tkip.tx.iv16 == 0) 229 - key->u.tkip.tx.iv32++; 230 - pos = ieee80211_tkip_add_iv(pos, key); 231 - spin_unlock(&key->u.tkip.txlock); 225 + pn = atomic64_inc_return(&key->conf.tx_pn); 226 + pos = ieee80211_tkip_add_iv(pos, &key->conf, pn); 232 227 233 228 /* hwaccel - with software IV */ 234 229 if (info->control.hw_key)