aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/mac80211/cfg.c14
-rw-r--r--net/mac80211/debugfs_key.c6
-rw-r--r--net/mac80211/key.h5
-rw-r--r--net/mac80211/wpa.c32
4 files changed, 32 insertions, 25 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 295ab747663f..3000b4c3b525 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -209,6 +209,7 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
209 u8 seq[6] = {0}; 209 u8 seq[6] = {0};
210 struct key_params params; 210 struct key_params params;
211 struct ieee80211_key *key = NULL; 211 struct ieee80211_key *key = NULL;
212 u64 pn64;
212 u32 iv32; 213 u32 iv32;
213 u16 iv16; 214 u16 iv16;
214 int err = -ENOENT; 215 int err = -ENOENT;
@@ -256,12 +257,13 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
256 params.seq_len = 6; 257 params.seq_len = 6;
257 break; 258 break;
258 case WLAN_CIPHER_SUITE_CCMP: 259 case WLAN_CIPHER_SUITE_CCMP:
259 seq[0] = key->u.ccmp.tx_pn[5]; 260 pn64 = atomic64_read(&key->u.ccmp.tx_pn);
260 seq[1] = key->u.ccmp.tx_pn[4]; 261 seq[0] = pn64;
261 seq[2] = key->u.ccmp.tx_pn[3]; 262 seq[1] = pn64 >> 8;
262 seq[3] = key->u.ccmp.tx_pn[2]; 263 seq[2] = pn64 >> 16;
263 seq[4] = key->u.ccmp.tx_pn[1]; 264 seq[3] = pn64 >> 24;
264 seq[5] = key->u.ccmp.tx_pn[0]; 265 seq[4] = pn64 >> 32;
266 seq[5] = pn64 >> 40;
265 params.seq = seq; 267 params.seq = seq;
266 params.seq_len = 6; 268 params.seq_len = 6;
267 break; 269 break;
diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c
index 33c58b85c911..4433760db4c7 100644
--- a/net/mac80211/debugfs_key.c
+++ b/net/mac80211/debugfs_key.c
@@ -79,6 +79,7 @@ static 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; 81 const u8 *tpn;
82 u64 pn;
82 char buf[20]; 83 char buf[20];
83 int len; 84 int len;
84 struct ieee80211_key *key = file->private_data; 85 struct ieee80211_key *key = file->private_data;
@@ -94,9 +95,10 @@ static ssize_t key_tx_spec_read(struct file *file, char __user *userbuf,
94 key->u.tkip.tx.iv16); 95 key->u.tkip.tx.iv16);
95 break; 96 break;
96 case WLAN_CIPHER_SUITE_CCMP: 97 case WLAN_CIPHER_SUITE_CCMP:
97 tpn = key->u.ccmp.tx_pn; 98 pn = atomic64_read(&key->u.ccmp.tx_pn);
98 len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n", 99 len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n",
99 tpn[0], tpn[1], tpn[2], tpn[3], tpn[4], tpn[5]); 100 (u8)(pn >> 40), (u8)(pn >> 32), (u8)(pn >> 24),
101 (u8)(pn >> 16), (u8)(pn >> 8), (u8)pn);
100 break; 102 break;
101 case WLAN_CIPHER_SUITE_AES_CMAC: 103 case WLAN_CIPHER_SUITE_AES_CMAC:
102 tpn = key->u.aes_cmac.tx_pn; 104 tpn = key->u.aes_cmac.tx_pn;
diff --git a/net/mac80211/key.h b/net/mac80211/key.h
index 1493c3e56b9f..05ce4c0203fc 100644
--- a/net/mac80211/key.h
+++ b/net/mac80211/key.h
@@ -82,7 +82,7 @@ struct ieee80211_key {
82 struct tkip_ctx rx[NUM_RX_DATA_QUEUES]; 82 struct tkip_ctx rx[NUM_RX_DATA_QUEUES];
83 } tkip; 83 } tkip;
84 struct { 84 struct {
85 u8 tx_pn[6]; 85 atomic64_t tx_pn;
86 /* 86 /*
87 * Last received packet number. The first 87 * Last received packet number. The first
88 * NUM_RX_DATA_QUEUES counters are used with Data 88 * NUM_RX_DATA_QUEUES counters are used with Data
@@ -92,12 +92,9 @@ struct ieee80211_key {
92 u8 rx_pn[NUM_RX_DATA_QUEUES + 1][6]; 92 u8 rx_pn[NUM_RX_DATA_QUEUES + 1][6];
93 struct crypto_cipher *tfm; 93 struct crypto_cipher *tfm;
94 u32 replays; /* dot11RSNAStatsCCMPReplays */ 94 u32 replays; /* dot11RSNAStatsCCMPReplays */
95 /* scratch buffers for virt_to_page() (crypto API) */
96#ifndef AES_BLOCK_LEN 95#ifndef AES_BLOCK_LEN
97#define AES_BLOCK_LEN 16 96#define AES_BLOCK_LEN 16
98#endif 97#endif
99 u8 tx_crypto_buf[6 * AES_BLOCK_LEN];
100 u8 rx_crypto_buf[6 * AES_BLOCK_LEN];
101 } ccmp; 98 } ccmp;
102 struct { 99 struct {
103 u8 tx_pn[6]; 100 u8 tx_pn[6];
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c
index 4ded2ae48a5f..7691e4edc74a 100644
--- a/net/mac80211/wpa.c
+++ b/net/mac80211/wpa.c
@@ -15,6 +15,7 @@
15#include <linux/gfp.h> 15#include <linux/gfp.h>
16#include <asm/unaligned.h> 16#include <asm/unaligned.h>
17#include <net/mac80211.h> 17#include <net/mac80211.h>
18#include <crypto/aes.h>
18 19
19#include "ieee80211_i.h" 20#include "ieee80211_i.h"
20#include "michael.h" 21#include "michael.h"
@@ -290,6 +291,8 @@ static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *scratch,
290 unsigned int hdrlen; 291 unsigned int hdrlen;
291 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; 292 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
292 293
294 memset(scratch, 0, 6 * AES_BLOCK_LEN);
295
293 b_0 = scratch + 3 * AES_BLOCK_LEN; 296 b_0 = scratch + 3 * AES_BLOCK_LEN;
294 aad = scratch + 4 * AES_BLOCK_LEN; 297 aad = scratch + 4 * AES_BLOCK_LEN;
295 298
@@ -380,8 +383,10 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
380 struct ieee80211_key *key = tx->key; 383 struct ieee80211_key *key = tx->key;
381 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 384 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
382 int hdrlen, len, tail; 385 int hdrlen, len, tail;
383 u8 *pos, *pn; 386 u8 *pos;
384 int i; 387 u8 pn[6];
388 u64 pn64;
389 u8 scratch[6 * AES_BLOCK_LEN];
385 390
386 if (info->control.hw_key && 391 if (info->control.hw_key &&
387 !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV)) { 392 !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV)) {
@@ -409,14 +414,14 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
409 hdr = (struct ieee80211_hdr *) pos; 414 hdr = (struct ieee80211_hdr *) pos;
410 pos += hdrlen; 415 pos += hdrlen;
411 416
412 /* PN = PN + 1 */ 417 pn64 = atomic64_inc_return(&key->u.ccmp.tx_pn);
413 pn = key->u.ccmp.tx_pn;
414 418
415 for (i = CCMP_PN_LEN - 1; i >= 0; i--) { 419 pn[5] = pn64;
416 pn[i]++; 420 pn[4] = pn64 >> 8;
417 if (pn[i]) 421 pn[3] = pn64 >> 16;
418 break; 422 pn[2] = pn64 >> 24;
419 } 423 pn[1] = pn64 >> 32;
424 pn[0] = pn64 >> 40;
420 425
421 ccmp_pn2hdr(pos, pn, key->conf.keyidx); 426 ccmp_pn2hdr(pos, pn, key->conf.keyidx);
422 427
@@ -425,8 +430,8 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
425 return 0; 430 return 0;
426 431
427 pos += CCMP_HDR_LEN; 432 pos += CCMP_HDR_LEN;
428 ccmp_special_blocks(skb, pn, key->u.ccmp.tx_crypto_buf, 0); 433 ccmp_special_blocks(skb, pn, scratch, 0);
429 ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, key->u.ccmp.tx_crypto_buf, pos, len, 434 ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, scratch, pos, len,
430 pos, skb_put(skb, CCMP_MIC_LEN)); 435 pos, skb_put(skb, CCMP_MIC_LEN));
431 436
432 return 0; 437 return 0;
@@ -482,11 +487,12 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx)
482 } 487 }
483 488
484 if (!(status->flag & RX_FLAG_DECRYPTED)) { 489 if (!(status->flag & RX_FLAG_DECRYPTED)) {
490 u8 scratch[6 * AES_BLOCK_LEN];
485 /* hardware didn't decrypt/verify MIC */ 491 /* hardware didn't decrypt/verify MIC */
486 ccmp_special_blocks(skb, pn, key->u.ccmp.rx_crypto_buf, 1); 492 ccmp_special_blocks(skb, pn, scratch, 1);
487 493
488 if (ieee80211_aes_ccm_decrypt( 494 if (ieee80211_aes_ccm_decrypt(
489 key->u.ccmp.tfm, key->u.ccmp.rx_crypto_buf, 495 key->u.ccmp.tfm, scratch,
490 skb->data + hdrlen + CCMP_HDR_LEN, data_len, 496 skb->data + hdrlen + CCMP_HDR_LEN, data_len,
491 skb->data + skb->len - CCMP_MIC_LEN, 497 skb->data + skb->len - CCMP_MIC_LEN,
492 skb->data + hdrlen + CCMP_HDR_LEN)) 498 skb->data + hdrlen + CCMP_HDR_LEN))