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