aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2011-07-06 16:00:35 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-07-08 11:11:20 -0400
commit75396ae6d433b49482e377e6f8dbf1f42ad53f3a (patch)
tree07fb506f08f3cca7d67d2fd365cc059240b6957b /net/mac80211
parentaba83a0b301c32dbb91c017f33307611e1a1d384 (diff)
mac80211: fix CMAC races
Just like TKIP and CCMP, CMAC has the PN race. It might not actually be possible to hit it now since there aren't multiple ACs for management frames, but fix it anyway. Also move scratch buffers onto the stack. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/aes_cmac.c8
-rw-r--r--net/mac80211/aes_cmac.h2
-rw-r--r--net/mac80211/cfg.c13
-rw-r--r--net/mac80211/debugfs_key.c7
-rw-r--r--net/mac80211/key.h5
-rw-r--r--net/mac80211/wpa.c30
6 files changed, 33 insertions, 32 deletions
diff --git a/net/mac80211/aes_cmac.c b/net/mac80211/aes_cmac.c
index d502b2684a66..08b0f1768aad 100644
--- a/net/mac80211/aes_cmac.c
+++ b/net/mac80211/aes_cmac.c
@@ -35,10 +35,10 @@ static void gf_mulx(u8 *pad)
35} 35}
36 36
37 37
38static void aes_128_cmac_vector(struct crypto_cipher *tfm, u8 *scratch, 38static void aes_128_cmac_vector(struct crypto_cipher *tfm, size_t num_elem,
39 size_t num_elem,
40 const u8 *addr[], const size_t *len, u8 *mac) 39 const u8 *addr[], const size_t *len, u8 *mac)
41{ 40{
41 u8 scratch[2 * AES_BLOCK_SIZE];
42 u8 *cbc, *pad; 42 u8 *cbc, *pad;
43 const u8 *pos, *end; 43 const u8 *pos, *end;
44 size_t i, e, left, total_len; 44 size_t i, e, left, total_len;
@@ -95,7 +95,7 @@ static void aes_128_cmac_vector(struct crypto_cipher *tfm, u8 *scratch,
95} 95}
96 96
97 97
98void ieee80211_aes_cmac(struct crypto_cipher *tfm, u8 *scratch, const u8 *aad, 98void ieee80211_aes_cmac(struct crypto_cipher *tfm, const u8 *aad,
99 const u8 *data, size_t data_len, u8 *mic) 99 const u8 *data, size_t data_len, u8 *mic)
100{ 100{
101 const u8 *addr[3]; 101 const u8 *addr[3];
@@ -110,7 +110,7 @@ void ieee80211_aes_cmac(struct crypto_cipher *tfm, u8 *scratch, const u8 *aad,
110 addr[2] = zero; 110 addr[2] = zero;
111 len[2] = CMAC_TLEN; 111 len[2] = CMAC_TLEN;
112 112
113 aes_128_cmac_vector(tfm, scratch, 3, addr, len, mic); 113 aes_128_cmac_vector(tfm, 3, addr, len, mic);
114} 114}
115 115
116 116
diff --git a/net/mac80211/aes_cmac.h b/net/mac80211/aes_cmac.h
index 0eb9a4831508..20785a647254 100644
--- a/net/mac80211/aes_cmac.h
+++ b/net/mac80211/aes_cmac.h
@@ -12,7 +12,7 @@
12#include <linux/crypto.h> 12#include <linux/crypto.h>
13 13
14struct crypto_cipher * ieee80211_aes_cmac_key_setup(const u8 key[]); 14struct crypto_cipher * ieee80211_aes_cmac_key_setup(const u8 key[]);
15void ieee80211_aes_cmac(struct crypto_cipher *tfm, u8 *scratch, const u8 *aad, 15void ieee80211_aes_cmac(struct crypto_cipher *tfm, const u8 *aad,
16 const u8 *data, size_t data_len, u8 *mic); 16 const u8 *data, size_t data_len, u8 *mic);
17void ieee80211_aes_cmac_key_free(struct crypto_cipher *tfm); 17void ieee80211_aes_cmac_key_free(struct crypto_cipher *tfm);
18 18
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 3000b4c3b525..bfc36e904764 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -268,12 +268,13 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
268 params.seq_len = 6; 268 params.seq_len = 6;
269 break; 269 break;
270 case WLAN_CIPHER_SUITE_AES_CMAC: 270 case WLAN_CIPHER_SUITE_AES_CMAC:
271 seq[0] = key->u.aes_cmac.tx_pn[5]; 271 pn64 = atomic64_read(&key->u.aes_cmac.tx_pn);
272 seq[1] = key->u.aes_cmac.tx_pn[4]; 272 seq[0] = pn64;
273 seq[2] = key->u.aes_cmac.tx_pn[3]; 273 seq[1] = pn64 >> 8;
274 seq[3] = key->u.aes_cmac.tx_pn[2]; 274 seq[2] = pn64 >> 16;
275 seq[4] = key->u.aes_cmac.tx_pn[1]; 275 seq[3] = pn64 >> 24;
276 seq[5] = key->u.aes_cmac.tx_pn[0]; 276 seq[4] = pn64 >> 32;
277 seq[5] = pn64 >> 40;
277 params.seq = seq; 278 params.seq = seq;
278 params.seq_len = 6; 279 params.seq_len = 6;
279 break; 280 break;
diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c
index 4433760db4c7..38e6101190d9 100644
--- a/net/mac80211/debugfs_key.c
+++ b/net/mac80211/debugfs_key.c
@@ -78,7 +78,6 @@ KEY_OPS(algorithm);
78static ssize_t key_tx_spec_read(struct file *file, char __user *userbuf, 78static ssize_t key_tx_spec_read(struct file *file, char __user *userbuf,
79 size_t count, loff_t *ppos) 79 size_t count, loff_t *ppos)
80{ 80{
81 const u8 *tpn;
82 u64 pn; 81 u64 pn;
83 char buf[20]; 82 char buf[20];
84 int len; 83 int len;
@@ -101,10 +100,10 @@ static ssize_t key_tx_spec_read(struct file *file, char __user *userbuf,
101 (u8)(pn >> 16), (u8)(pn >> 8), (u8)pn); 100 (u8)(pn >> 16), (u8)(pn >> 8), (u8)pn);
102 break; 101 break;
103 case WLAN_CIPHER_SUITE_AES_CMAC: 102 case WLAN_CIPHER_SUITE_AES_CMAC:
104 tpn = key->u.aes_cmac.tx_pn; 103 pn = atomic64_read(&key->u.aes_cmac.tx_pn);
105 len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n", 104 len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n",
106 tpn[0], tpn[1], tpn[2], tpn[3], tpn[4], 105 (u8)(pn >> 40), (u8)(pn >> 32), (u8)(pn >> 24),
107 tpn[5]); 106 (u8)(pn >> 16), (u8)(pn >> 8), (u8)pn);
108 break; 107 break;
109 default: 108 default:
110 return 0; 109 return 0;
diff --git a/net/mac80211/key.h b/net/mac80211/key.h
index 05ce4c0203fc..fcb52eb2f92f 100644
--- a/net/mac80211/key.h
+++ b/net/mac80211/key.h
@@ -97,14 +97,11 @@ struct ieee80211_key {
97#endif 97#endif
98 } ccmp; 98 } ccmp;
99 struct { 99 struct {
100 u8 tx_pn[6]; 100 atomic64_t tx_pn;
101 u8 rx_pn[6]; 101 u8 rx_pn[6];
102 struct crypto_cipher *tfm; 102 struct crypto_cipher *tfm;
103 u32 replays; /* dot11RSNAStatsCMACReplays */ 103 u32 replays; /* dot11RSNAStatsCMACReplays */
104 u32 icverrors; /* dot11RSNAStatsCMACICVErrors */ 104 u32 icverrors; /* dot11RSNAStatsCMACICVErrors */
105 /* scratch buffers for virt_to_page() (crypto API) */
106 u8 tx_crypto_buf[2 * AES_BLOCK_LEN];
107 u8 rx_crypto_buf[2 * AES_BLOCK_LEN];
108 } aes_cmac; 105 } aes_cmac;
109 } u; 106 } u;
110 107
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c
index 7691e4edc74a..3452d5e0a3cb 100644
--- a/net/mac80211/wpa.c
+++ b/net/mac80211/wpa.c
@@ -523,6 +523,16 @@ static void bip_aad(struct sk_buff *skb, u8 *aad)
523} 523}
524 524
525 525
526static inline void bip_ipn_set64(u8 *d, u64 pn)
527{
528 *d++ = pn;
529 *d++ = pn >> 8;
530 *d++ = pn >> 16;
531 *d++ = pn >> 24;
532 *d++ = pn >> 32;
533 *d = pn >> 40;
534}
535
526static inline void bip_ipn_swap(u8 *d, const u8 *s) 536static inline void bip_ipn_swap(u8 *d, const u8 *s)
527{ 537{
528 *d++ = s[5]; 538 *d++ = s[5];
@@ -541,8 +551,8 @@ ieee80211_crypto_aes_cmac_encrypt(struct ieee80211_tx_data *tx)
541 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 551 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
542 struct ieee80211_key *key = tx->key; 552 struct ieee80211_key *key = tx->key;
543 struct ieee80211_mmie *mmie; 553 struct ieee80211_mmie *mmie;
544 u8 *pn, aad[20]; 554 u8 aad[20];
545 int i; 555 u64 pn64;
546 556
547 if (info->control.hw_key) 557 if (info->control.hw_key)
548 return 0; 558 return 0;
@@ -556,22 +566,17 @@ ieee80211_crypto_aes_cmac_encrypt(struct ieee80211_tx_data *tx)
556 mmie->key_id = cpu_to_le16(key->conf.keyidx); 566 mmie->key_id = cpu_to_le16(key->conf.keyidx);
557 567
558 /* PN = PN + 1 */ 568 /* PN = PN + 1 */
559 pn = key->u.aes_cmac.tx_pn; 569 pn64 = atomic64_inc_return(&key->u.aes_cmac.tx_pn);
560 570
561 for (i = sizeof(key->u.aes_cmac.tx_pn) - 1; i >= 0; i--) { 571 bip_ipn_set64(mmie->sequence_number, pn64);
562 pn[i]++;
563 if (pn[i])
564 break;
565 }
566 bip_ipn_swap(mmie->sequence_number, pn);
567 572
568 bip_aad(skb, aad); 573 bip_aad(skb, aad);
569 574
570 /* 575 /*
571 * MIC = AES-128-CMAC(IGTK, AAD || Management Frame Body || MMIE, 64) 576 * MIC = AES-128-CMAC(IGTK, AAD || Management Frame Body || MMIE, 64)
572 */ 577 */
573 ieee80211_aes_cmac(key->u.aes_cmac.tfm, key->u.aes_cmac.tx_crypto_buf, 578 ieee80211_aes_cmac(key->u.aes_cmac.tfm, aad,
574 aad, skb->data + 24, skb->len - 24, mmie->mic); 579 skb->data + 24, skb->len - 24, mmie->mic);
575 580
576 return TX_CONTINUE; 581 return TX_CONTINUE;
577} 582}
@@ -609,8 +614,7 @@ ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx)
609 if (!(status->flag & RX_FLAG_DECRYPTED)) { 614 if (!(status->flag & RX_FLAG_DECRYPTED)) {
610 /* hardware didn't decrypt/verify MIC */ 615 /* hardware didn't decrypt/verify MIC */
611 bip_aad(skb, aad); 616 bip_aad(skb, aad);
612 ieee80211_aes_cmac(key->u.aes_cmac.tfm, 617 ieee80211_aes_cmac(key->u.aes_cmac.tfm, aad,
613 key->u.aes_cmac.rx_crypto_buf, aad,
614 skb->data + 24, skb->len - 24, mic); 618 skb->data + 24, skb->len - 24, mic);
615 if (memcmp(mic, mmie->mic, sizeof(mmie->mic)) != 0) { 619 if (memcmp(mic, mmie->mic, sizeof(mmie->mic)) != 0) {
616 key->u.aes_cmac.icverrors++; 620 key->u.aes_cmac.icverrors++;