aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJouni Malinen <jouni@qca.qualcomm.com>2015-01-24 12:52:07 -0500
committerJohannes Berg <johannes.berg@intel.com>2015-01-27 05:07:35 -0500
commit2b2ba0db1c820d04d5143452d70012cd44d7b578 (patch)
tree7c186fc249d191d9ecba66e740e7a4c922a986d5 /net
parent00b9cfa3ff38401bd70c34b250ca13e5ea347b4a (diff)
mac80111: Add CCMP-256 cipher
This allows mac80211 to configure CCMP-256 to the driver and also use software-implementation within mac80211 when the driver does not support this with hardware accelaration. Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com> [squash ccmp256 -> mic_len argument change] Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/aes_ccm.c21
-rw-r--r--net/mac80211/aes_ccm.h10
-rw-r--r--net/mac80211/cfg.c2
-rw-r--r--net/mac80211/debugfs_key.c3
-rw-r--r--net/mac80211/key.c27
-rw-r--r--net/mac80211/main.c6
-rw-r--r--net/mac80211/rx.c15
-rw-r--r--net/mac80211/tx.c7
-rw-r--r--net/mac80211/wpa.c22
-rw-r--r--net/mac80211/wpa.h6
10 files changed, 88 insertions, 31 deletions
diff --git a/net/mac80211/aes_ccm.c b/net/mac80211/aes_ccm.c
index 09d9caaec591..7869bb40acaa 100644
--- a/net/mac80211/aes_ccm.c
+++ b/net/mac80211/aes_ccm.c
@@ -20,7 +20,8 @@
20#include "aes_ccm.h" 20#include "aes_ccm.h"
21 21
22void ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, 22void ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
23 u8 *data, size_t data_len, u8 *mic) 23 u8 *data, size_t data_len, u8 *mic,
24 size_t mic_len)
24{ 25{
25 struct scatterlist assoc, pt, ct[2]; 26 struct scatterlist assoc, pt, ct[2];
26 27
@@ -35,7 +36,7 @@ void ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
35 sg_init_one(&assoc, &aad[2], be16_to_cpup((__be16 *)aad)); 36 sg_init_one(&assoc, &aad[2], be16_to_cpup((__be16 *)aad));
36 sg_init_table(ct, 2); 37 sg_init_table(ct, 2);
37 sg_set_buf(&ct[0], data, data_len); 38 sg_set_buf(&ct[0], data, data_len);
38 sg_set_buf(&ct[1], mic, IEEE80211_CCMP_MIC_LEN); 39 sg_set_buf(&ct[1], mic, mic_len);
39 40
40 aead_request_set_tfm(aead_req, tfm); 41 aead_request_set_tfm(aead_req, tfm);
41 aead_request_set_assoc(aead_req, &assoc, assoc.length); 42 aead_request_set_assoc(aead_req, &assoc, assoc.length);
@@ -45,7 +46,8 @@ void ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
45} 46}
46 47
47int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, 48int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
48 u8 *data, size_t data_len, u8 *mic) 49 u8 *data, size_t data_len, u8 *mic,
50 size_t mic_len)
49{ 51{
50 struct scatterlist assoc, pt, ct[2]; 52 struct scatterlist assoc, pt, ct[2];
51 char aead_req_data[sizeof(struct aead_request) + 53 char aead_req_data[sizeof(struct aead_request) +
@@ -62,17 +64,18 @@ int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
62 sg_init_one(&assoc, &aad[2], be16_to_cpup((__be16 *)aad)); 64 sg_init_one(&assoc, &aad[2], be16_to_cpup((__be16 *)aad));
63 sg_init_table(ct, 2); 65 sg_init_table(ct, 2);
64 sg_set_buf(&ct[0], data, data_len); 66 sg_set_buf(&ct[0], data, data_len);
65 sg_set_buf(&ct[1], mic, IEEE80211_CCMP_MIC_LEN); 67 sg_set_buf(&ct[1], mic, mic_len);
66 68
67 aead_request_set_tfm(aead_req, tfm); 69 aead_request_set_tfm(aead_req, tfm);
68 aead_request_set_assoc(aead_req, &assoc, assoc.length); 70 aead_request_set_assoc(aead_req, &assoc, assoc.length);
69 aead_request_set_crypt(aead_req, ct, &pt, 71 aead_request_set_crypt(aead_req, ct, &pt, data_len + mic_len, b_0);
70 data_len + IEEE80211_CCMP_MIC_LEN, b_0);
71 72
72 return crypto_aead_decrypt(aead_req); 73 return crypto_aead_decrypt(aead_req);
73} 74}
74 75
75struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[]) 76struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[],
77 size_t key_len,
78 size_t mic_len)
76{ 79{
77 struct crypto_aead *tfm; 80 struct crypto_aead *tfm;
78 int err; 81 int err;
@@ -81,9 +84,9 @@ struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[])
81 if (IS_ERR(tfm)) 84 if (IS_ERR(tfm))
82 return tfm; 85 return tfm;
83 86
84 err = crypto_aead_setkey(tfm, key, WLAN_KEY_LEN_CCMP); 87 err = crypto_aead_setkey(tfm, key, key_len);
85 if (!err) 88 if (!err)
86 err = crypto_aead_setauthsize(tfm, IEEE80211_CCMP_MIC_LEN); 89 err = crypto_aead_setauthsize(tfm, mic_len);
87 if (!err) 90 if (!err)
88 return tfm; 91 return tfm;
89 92
diff --git a/net/mac80211/aes_ccm.h b/net/mac80211/aes_ccm.h
index 2c7ab1948a2e..6a73d1e4d186 100644
--- a/net/mac80211/aes_ccm.h
+++ b/net/mac80211/aes_ccm.h
@@ -12,11 +12,15 @@
12 12
13#include <linux/crypto.h> 13#include <linux/crypto.h>
14 14
15struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[]); 15struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[],
16 size_t key_len,
17 size_t mic_len);
16void ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, 18void ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
17 u8 *data, size_t data_len, u8 *mic); 19 u8 *data, size_t data_len, u8 *mic,
20 size_t mic_len);
18int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, 21int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
19 u8 *data, size_t data_len, u8 *mic); 22 u8 *data, size_t data_len, u8 *mic,
23 size_t mic_len);
20void ieee80211_aes_key_free(struct crypto_aead *tfm); 24void ieee80211_aes_key_free(struct crypto_aead *tfm);
21 25
22#endif /* AES_CCM_H */ 26#endif /* AES_CCM_H */
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 1c1d061cff56..ef84441c119c 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -162,6 +162,7 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
162 return -EINVAL; 162 return -EINVAL;
163 break; 163 break;
164 case WLAN_CIPHER_SUITE_CCMP: 164 case WLAN_CIPHER_SUITE_CCMP:
165 case WLAN_CIPHER_SUITE_CCMP_256:
165 case WLAN_CIPHER_SUITE_AES_CMAC: 166 case WLAN_CIPHER_SUITE_AES_CMAC:
166 case WLAN_CIPHER_SUITE_GCMP: 167 case WLAN_CIPHER_SUITE_GCMP:
167 case WLAN_CIPHER_SUITE_GCMP_256: 168 case WLAN_CIPHER_SUITE_GCMP_256:
@@ -349,6 +350,7 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
349 params.seq_len = 6; 350 params.seq_len = 6;
350 break; 351 break;
351 case WLAN_CIPHER_SUITE_CCMP: 352 case WLAN_CIPHER_SUITE_CCMP:
353 case WLAN_CIPHER_SUITE_CCMP_256:
352 pn64 = atomic64_read(&key->u.ccmp.tx_pn); 354 pn64 = atomic64_read(&key->u.ccmp.tx_pn);
353 seq[0] = pn64; 355 seq[0] = pn64;
354 seq[1] = pn64 >> 8; 356 seq[1] = pn64 >> 8;
diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c
index 0e223e602296..64de07b16092 100644
--- a/net/mac80211/debugfs_key.c
+++ b/net/mac80211/debugfs_key.c
@@ -94,6 +94,7 @@ static ssize_t key_tx_spec_read(struct file *file, char __user *userbuf,
94 key->u.tkip.tx.iv16); 94 key->u.tkip.tx.iv16);
95 break; 95 break;
96 case WLAN_CIPHER_SUITE_CCMP: 96 case WLAN_CIPHER_SUITE_CCMP:
97 case WLAN_CIPHER_SUITE_CCMP_256:
97 pn = atomic64_read(&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 (u8)(pn >> 40), (u8)(pn >> 32), (u8)(pn >> 24), 100 (u8)(pn >> 40), (u8)(pn >> 32), (u8)(pn >> 24),
@@ -141,6 +142,7 @@ static ssize_t key_rx_spec_read(struct file *file, char __user *userbuf,
141 len = p - buf; 142 len = p - buf;
142 break; 143 break;
143 case WLAN_CIPHER_SUITE_CCMP: 144 case WLAN_CIPHER_SUITE_CCMP:
145 case WLAN_CIPHER_SUITE_CCMP_256:
144 for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++) { 146 for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++) {
145 rpn = key->u.ccmp.rx_pn[i]; 147 rpn = key->u.ccmp.rx_pn[i];
146 p += scnprintf(p, sizeof(buf)+buf-p, 148 p += scnprintf(p, sizeof(buf)+buf-p,
@@ -185,6 +187,7 @@ static ssize_t key_replays_read(struct file *file, char __user *userbuf,
185 187
186 switch (key->conf.cipher) { 188 switch (key->conf.cipher) {
187 case WLAN_CIPHER_SUITE_CCMP: 189 case WLAN_CIPHER_SUITE_CCMP:
190 case WLAN_CIPHER_SUITE_CCMP_256:
188 len = scnprintf(buf, sizeof(buf), "%u\n", key->u.ccmp.replays); 191 len = scnprintf(buf, sizeof(buf), "%u\n", key->u.ccmp.replays);
189 break; 192 break;
190 case WLAN_CIPHER_SUITE_AES_CMAC: 193 case WLAN_CIPHER_SUITE_AES_CMAC:
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index cbee2f5180ce..83c61085c3f0 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -163,6 +163,7 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
163 case WLAN_CIPHER_SUITE_WEP104: 163 case WLAN_CIPHER_SUITE_WEP104:
164 case WLAN_CIPHER_SUITE_TKIP: 164 case WLAN_CIPHER_SUITE_TKIP:
165 case WLAN_CIPHER_SUITE_CCMP: 165 case WLAN_CIPHER_SUITE_CCMP:
166 case WLAN_CIPHER_SUITE_CCMP_256:
166 case WLAN_CIPHER_SUITE_AES_CMAC: 167 case WLAN_CIPHER_SUITE_AES_CMAC:
167 case WLAN_CIPHER_SUITE_GCMP: 168 case WLAN_CIPHER_SUITE_GCMP:
168 case WLAN_CIPHER_SUITE_GCMP_256: 169 case WLAN_CIPHER_SUITE_GCMP_256:
@@ -389,7 +390,26 @@ ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
389 * Initialize AES key state here as an optimization so that 390 * Initialize AES key state here as an optimization so that
390 * it does not need to be initialized for every packet. 391 * it does not need to be initialized for every packet.
391 */ 392 */
392 key->u.ccmp.tfm = ieee80211_aes_key_setup_encrypt(key_data); 393 key->u.ccmp.tfm = ieee80211_aes_key_setup_encrypt(
394 key_data, key_len, IEEE80211_CCMP_MIC_LEN);
395 if (IS_ERR(key->u.ccmp.tfm)) {
396 err = PTR_ERR(key->u.ccmp.tfm);
397 kfree(key);
398 return ERR_PTR(err);
399 }
400 break;
401 case WLAN_CIPHER_SUITE_CCMP_256:
402 key->conf.iv_len = IEEE80211_CCMP_256_HDR_LEN;
403 key->conf.icv_len = IEEE80211_CCMP_256_MIC_LEN;
404 for (i = 0; seq && i < IEEE80211_NUM_TIDS + 1; i++)
405 for (j = 0; j < IEEE80211_CCMP_256_PN_LEN; j++)
406 key->u.ccmp.rx_pn[i][j] =
407 seq[IEEE80211_CCMP_256_PN_LEN - j - 1];
408 /* Initialize AES key state here as an optimization so that
409 * it does not need to be initialized for every packet.
410 */
411 key->u.ccmp.tfm = ieee80211_aes_key_setup_encrypt(
412 key_data, key_len, IEEE80211_CCMP_256_MIC_LEN);
393 if (IS_ERR(key->u.ccmp.tfm)) { 413 if (IS_ERR(key->u.ccmp.tfm)) {
394 err = PTR_ERR(key->u.ccmp.tfm); 414 err = PTR_ERR(key->u.ccmp.tfm);
395 kfree(key); 415 kfree(key);
@@ -457,6 +477,7 @@ static void ieee80211_key_free_common(struct ieee80211_key *key)
457{ 477{
458 switch (key->conf.cipher) { 478 switch (key->conf.cipher) {
459 case WLAN_CIPHER_SUITE_CCMP: 479 case WLAN_CIPHER_SUITE_CCMP:
480 case WLAN_CIPHER_SUITE_CCMP_256:
460 ieee80211_aes_key_free(key->u.ccmp.tfm); 481 ieee80211_aes_key_free(key->u.ccmp.tfm);
461 break; 482 break;
462 case WLAN_CIPHER_SUITE_AES_CMAC: 483 case WLAN_CIPHER_SUITE_AES_CMAC:
@@ -773,6 +794,7 @@ void ieee80211_get_key_tx_seq(struct ieee80211_key_conf *keyconf,
773 seq->tkip.iv16 = key->u.tkip.tx.iv16; 794 seq->tkip.iv16 = key->u.tkip.tx.iv16;
774 break; 795 break;
775 case WLAN_CIPHER_SUITE_CCMP: 796 case WLAN_CIPHER_SUITE_CCMP:
797 case WLAN_CIPHER_SUITE_CCMP_256:
776 pn64 = atomic64_read(&key->u.ccmp.tx_pn); 798 pn64 = atomic64_read(&key->u.ccmp.tx_pn);
777 seq->ccmp.pn[5] = pn64; 799 seq->ccmp.pn[5] = pn64;
778 seq->ccmp.pn[4] = pn64 >> 8; 800 seq->ccmp.pn[4] = pn64 >> 8;
@@ -822,6 +844,7 @@ void ieee80211_get_key_rx_seq(struct ieee80211_key_conf *keyconf,
822 seq->tkip.iv16 = key->u.tkip.rx[tid].iv16; 844 seq->tkip.iv16 = key->u.tkip.rx[tid].iv16;
823 break; 845 break;
824 case WLAN_CIPHER_SUITE_CCMP: 846 case WLAN_CIPHER_SUITE_CCMP:
847 case WLAN_CIPHER_SUITE_CCMP_256:
825 if (WARN_ON(tid < -1 || tid >= IEEE80211_NUM_TIDS)) 848 if (WARN_ON(tid < -1 || tid >= IEEE80211_NUM_TIDS))
826 return; 849 return;
827 if (tid < 0) 850 if (tid < 0)
@@ -864,6 +887,7 @@ void ieee80211_set_key_tx_seq(struct ieee80211_key_conf *keyconf,
864 key->u.tkip.tx.iv16 = seq->tkip.iv16; 887 key->u.tkip.tx.iv16 = seq->tkip.iv16;
865 break; 888 break;
866 case WLAN_CIPHER_SUITE_CCMP: 889 case WLAN_CIPHER_SUITE_CCMP:
890 case WLAN_CIPHER_SUITE_CCMP_256:
867 pn64 = (u64)seq->ccmp.pn[5] | 891 pn64 = (u64)seq->ccmp.pn[5] |
868 ((u64)seq->ccmp.pn[4] << 8) | 892 ((u64)seq->ccmp.pn[4] << 8) |
869 ((u64)seq->ccmp.pn[3] << 16) | 893 ((u64)seq->ccmp.pn[3] << 16) |
@@ -914,6 +938,7 @@ void ieee80211_set_key_rx_seq(struct ieee80211_key_conf *keyconf,
914 key->u.tkip.rx[tid].iv16 = seq->tkip.iv16; 938 key->u.tkip.rx[tid].iv16 = seq->tkip.iv16;
915 break; 939 break;
916 case WLAN_CIPHER_SUITE_CCMP: 940 case WLAN_CIPHER_SUITE_CCMP:
941 case WLAN_CIPHER_SUITE_CCMP_256:
917 if (WARN_ON(tid < -1 || tid >= IEEE80211_NUM_TIDS)) 942 if (WARN_ON(tid < -1 || tid >= IEEE80211_NUM_TIDS))
918 return; 943 return;
919 if (tid < 0) 944 if (tid < 0)
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 7223b4e16752..a5ad2d5bb29b 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -666,6 +666,7 @@ static int ieee80211_init_cipher_suites(struct ieee80211_local *local)
666 WLAN_CIPHER_SUITE_WEP104, 666 WLAN_CIPHER_SUITE_WEP104,
667 WLAN_CIPHER_SUITE_TKIP, 667 WLAN_CIPHER_SUITE_TKIP,
668 WLAN_CIPHER_SUITE_CCMP, 668 WLAN_CIPHER_SUITE_CCMP,
669 WLAN_CIPHER_SUITE_CCMP_256,
669 WLAN_CIPHER_SUITE_GCMP, 670 WLAN_CIPHER_SUITE_GCMP,
670 WLAN_CIPHER_SUITE_GCMP_256, 671 WLAN_CIPHER_SUITE_GCMP_256,
671 672
@@ -727,9 +728,9 @@ static int ieee80211_init_cipher_suites(struct ieee80211_local *local)
727 * including the schemes) 728 * including the schemes)
728 * 729 *
729 * We start counting ciphers defined by schemes, TKIP, CCMP, 730 * We start counting ciphers defined by schemes, TKIP, CCMP,
730 * GCMP, and GCMP-256 731 * CCMP-256, GCMP, and GCMP-256
731 */ 732 */
732 n_suites = local->hw.n_cipher_schemes + 4; 733 n_suites = local->hw.n_cipher_schemes + 5;
733 734
734 /* check if we have WEP40 and WEP104 */ 735 /* check if we have WEP40 and WEP104 */
735 if (have_wep) 736 if (have_wep)
@@ -744,6 +745,7 @@ static int ieee80211_init_cipher_suites(struct ieee80211_local *local)
744 return -ENOMEM; 745 return -ENOMEM;
745 746
746 suites[w++] = WLAN_CIPHER_SUITE_CCMP; 747 suites[w++] = WLAN_CIPHER_SUITE_CCMP;
748 suites[w++] = WLAN_CIPHER_SUITE_CCMP_256;
747 suites[w++] = WLAN_CIPHER_SUITE_TKIP; 749 suites[w++] = WLAN_CIPHER_SUITE_TKIP;
748 suites[w++] = WLAN_CIPHER_SUITE_GCMP; 750 suites[w++] = WLAN_CIPHER_SUITE_GCMP;
749 suites[w++] = WLAN_CIPHER_SUITE_GCMP_256; 751 suites[w++] = WLAN_CIPHER_SUITE_GCMP_256;
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index a11d2518c365..e8c6ba5ce70b 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1650,7 +1650,12 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
1650 result = ieee80211_crypto_tkip_decrypt(rx); 1650 result = ieee80211_crypto_tkip_decrypt(rx);
1651 break; 1651 break;
1652 case WLAN_CIPHER_SUITE_CCMP: 1652 case WLAN_CIPHER_SUITE_CCMP:
1653 result = ieee80211_crypto_ccmp_decrypt(rx); 1653 result = ieee80211_crypto_ccmp_decrypt(
1654 rx, IEEE80211_CCMP_MIC_LEN);
1655 break;
1656 case WLAN_CIPHER_SUITE_CCMP_256:
1657 result = ieee80211_crypto_ccmp_decrypt(
1658 rx, IEEE80211_CCMP_256_MIC_LEN);
1654 break; 1659 break;
1655 case WLAN_CIPHER_SUITE_AES_CMAC: 1660 case WLAN_CIPHER_SUITE_AES_CMAC:
1656 result = ieee80211_crypto_aes_cmac_decrypt(rx); 1661 result = ieee80211_crypto_aes_cmac_decrypt(rx);
@@ -1785,7 +1790,9 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
1785 /* This is the first fragment of a new frame. */ 1790 /* This is the first fragment of a new frame. */
1786 entry = ieee80211_reassemble_add(rx->sdata, frag, seq, 1791 entry = ieee80211_reassemble_add(rx->sdata, frag, seq,
1787 rx->seqno_idx, &(rx->skb)); 1792 rx->seqno_idx, &(rx->skb));
1788 if (rx->key && rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP && 1793 if (rx->key &&
1794 (rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP ||
1795 rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP_256) &&
1789 ieee80211_has_protected(fc)) { 1796 ieee80211_has_protected(fc)) {
1790 int queue = rx->security_idx; 1797 int queue = rx->security_idx;
1791 /* Store CCMP PN so that we can verify that the next 1798 /* Store CCMP PN so that we can verify that the next
@@ -1814,7 +1821,9 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
1814 int i; 1821 int i;
1815 u8 pn[IEEE80211_CCMP_PN_LEN], *rpn; 1822 u8 pn[IEEE80211_CCMP_PN_LEN], *rpn;
1816 int queue; 1823 int queue;
1817 if (!rx->key || rx->key->conf.cipher != WLAN_CIPHER_SUITE_CCMP) 1824 if (!rx->key ||
1825 (rx->key->conf.cipher != WLAN_CIPHER_SUITE_CCMP &&
1826 rx->key->conf.cipher != WLAN_CIPHER_SUITE_CCMP_256))
1818 return RX_DROP_UNUSABLE; 1827 return RX_DROP_UNUSABLE;
1819 memcpy(pn, entry->last_pn, IEEE80211_CCMP_PN_LEN); 1828 memcpy(pn, entry->last_pn, IEEE80211_CCMP_PN_LEN);
1820 for (i = IEEE80211_CCMP_PN_LEN - 1; i >= 0; i--) { 1829 for (i = IEEE80211_CCMP_PN_LEN - 1; i >= 0; i--) {
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index e4c6fbc4bf7a..be57e0afd019 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -626,6 +626,7 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
626 tx->key = NULL; 626 tx->key = NULL;
627 break; 627 break;
628 case WLAN_CIPHER_SUITE_CCMP: 628 case WLAN_CIPHER_SUITE_CCMP:
629 case WLAN_CIPHER_SUITE_CCMP_256:
629 case WLAN_CIPHER_SUITE_GCMP: 630 case WLAN_CIPHER_SUITE_GCMP:
630 case WLAN_CIPHER_SUITE_GCMP_256: 631 case WLAN_CIPHER_SUITE_GCMP_256:
631 if (!ieee80211_is_data_present(hdr->frame_control) && 632 if (!ieee80211_is_data_present(hdr->frame_control) &&
@@ -1013,7 +1014,11 @@ ieee80211_tx_h_encrypt(struct ieee80211_tx_data *tx)
1013 case WLAN_CIPHER_SUITE_TKIP: 1014 case WLAN_CIPHER_SUITE_TKIP:
1014 return ieee80211_crypto_tkip_encrypt(tx); 1015 return ieee80211_crypto_tkip_encrypt(tx);
1015 case WLAN_CIPHER_SUITE_CCMP: 1016 case WLAN_CIPHER_SUITE_CCMP:
1016 return ieee80211_crypto_ccmp_encrypt(tx); 1017 return ieee80211_crypto_ccmp_encrypt(
1018 tx, IEEE80211_CCMP_MIC_LEN);
1019 case WLAN_CIPHER_SUITE_CCMP_256:
1020 return ieee80211_crypto_ccmp_encrypt(
1021 tx, IEEE80211_CCMP_256_MIC_LEN);
1017 case WLAN_CIPHER_SUITE_AES_CMAC: 1022 case WLAN_CIPHER_SUITE_AES_CMAC:
1018 return ieee80211_crypto_aes_cmac_encrypt(tx); 1023 return ieee80211_crypto_aes_cmac_encrypt(tx);
1019 case WLAN_CIPHER_SUITE_GCMP: 1024 case WLAN_CIPHER_SUITE_GCMP:
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c
index 96b65c240109..ae654de9782a 100644
--- a/net/mac80211/wpa.c
+++ b/net/mac80211/wpa.c
@@ -394,7 +394,8 @@ static inline void ccmp_hdr2pn(u8 *pn, u8 *hdr)
394} 394}
395 395
396 396
397static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) 397static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb,
398 unsigned int mic_len)
398{ 399{
399 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; 400 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
400 struct ieee80211_key *key = tx->key; 401 struct ieee80211_key *key = tx->key;
@@ -425,7 +426,7 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
425 if (info->control.hw_key) 426 if (info->control.hw_key)
426 tail = 0; 427 tail = 0;
427 else 428 else
428 tail = IEEE80211_CCMP_MIC_LEN; 429 tail = mic_len;
429 430
430 if (WARN_ON(skb_tailroom(skb) < tail || 431 if (WARN_ON(skb_tailroom(skb) < tail ||
431 skb_headroom(skb) < IEEE80211_CCMP_HDR_LEN)) 432 skb_headroom(skb) < IEEE80211_CCMP_HDR_LEN))
@@ -460,21 +461,22 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
460 pos += IEEE80211_CCMP_HDR_LEN; 461 pos += IEEE80211_CCMP_HDR_LEN;
461 ccmp_special_blocks(skb, pn, b_0, aad); 462 ccmp_special_blocks(skb, pn, b_0, aad);
462 ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, b_0, aad, pos, len, 463 ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, b_0, aad, pos, len,
463 skb_put(skb, IEEE80211_CCMP_MIC_LEN)); 464 skb_put(skb, mic_len), mic_len);
464 465
465 return 0; 466 return 0;
466} 467}
467 468
468 469
469ieee80211_tx_result 470ieee80211_tx_result
470ieee80211_crypto_ccmp_encrypt(struct ieee80211_tx_data *tx) 471ieee80211_crypto_ccmp_encrypt(struct ieee80211_tx_data *tx,
472 unsigned int mic_len)
471{ 473{
472 struct sk_buff *skb; 474 struct sk_buff *skb;
473 475
474 ieee80211_tx_set_protected(tx); 476 ieee80211_tx_set_protected(tx);
475 477
476 skb_queue_walk(&tx->skbs, skb) { 478 skb_queue_walk(&tx->skbs, skb) {
477 if (ccmp_encrypt_skb(tx, skb) < 0) 479 if (ccmp_encrypt_skb(tx, skb, mic_len) < 0)
478 return TX_DROP; 480 return TX_DROP;
479 } 481 }
480 482
@@ -483,7 +485,8 @@ ieee80211_crypto_ccmp_encrypt(struct ieee80211_tx_data *tx)
483 485
484 486
485ieee80211_rx_result 487ieee80211_rx_result
486ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) 488ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx,
489 unsigned int mic_len)
487{ 490{
488 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; 491 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
489 int hdrlen; 492 int hdrlen;
@@ -500,8 +503,7 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx)
500 !ieee80211_is_robust_mgmt_frame(skb)) 503 !ieee80211_is_robust_mgmt_frame(skb))
501 return RX_CONTINUE; 504 return RX_CONTINUE;
502 505
503 data_len = skb->len - hdrlen - IEEE80211_CCMP_HDR_LEN - 506 data_len = skb->len - hdrlen - IEEE80211_CCMP_HDR_LEN - mic_len;
504 IEEE80211_CCMP_MIC_LEN;
505 if (!rx->sta || data_len < 0) 507 if (!rx->sta || data_len < 0)
506 return RX_DROP_UNUSABLE; 508 return RX_DROP_UNUSABLE;
507 509
@@ -532,14 +534,14 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx)
532 key->u.ccmp.tfm, b_0, aad, 534 key->u.ccmp.tfm, b_0, aad,
533 skb->data + hdrlen + IEEE80211_CCMP_HDR_LEN, 535 skb->data + hdrlen + IEEE80211_CCMP_HDR_LEN,
534 data_len, 536 data_len,
535 skb->data + skb->len - IEEE80211_CCMP_MIC_LEN)) 537 skb->data + skb->len - mic_len, mic_len))
536 return RX_DROP_UNUSABLE; 538 return RX_DROP_UNUSABLE;
537 } 539 }
538 540
539 memcpy(key->u.ccmp.rx_pn[queue], pn, IEEE80211_CCMP_PN_LEN); 541 memcpy(key->u.ccmp.rx_pn[queue], pn, IEEE80211_CCMP_PN_LEN);
540 542
541 /* Remove CCMP header and MIC */ 543 /* Remove CCMP header and MIC */
542 if (pskb_trim(skb, skb->len - IEEE80211_CCMP_MIC_LEN)) 544 if (pskb_trim(skb, skb->len - mic_len))
543 return RX_DROP_UNUSABLE; 545 return RX_DROP_UNUSABLE;
544 memmove(skb->data + IEEE80211_CCMP_HDR_LEN, skb->data, hdrlen); 546 memmove(skb->data + IEEE80211_CCMP_HDR_LEN, skb->data, hdrlen);
545 skb_pull(skb, IEEE80211_CCMP_HDR_LEN); 547 skb_pull(skb, IEEE80211_CCMP_HDR_LEN);
diff --git a/net/mac80211/wpa.h b/net/mac80211/wpa.h
index ea955f278351..43e109f27a89 100644
--- a/net/mac80211/wpa.h
+++ b/net/mac80211/wpa.h
@@ -24,9 +24,11 @@ ieee80211_rx_result
24ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx); 24ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx);
25 25
26ieee80211_tx_result 26ieee80211_tx_result
27ieee80211_crypto_ccmp_encrypt(struct ieee80211_tx_data *tx); 27ieee80211_crypto_ccmp_encrypt(struct ieee80211_tx_data *tx,
28 unsigned int mic_len);
28ieee80211_rx_result 29ieee80211_rx_result
29ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx); 30ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx,
31 unsigned int mic_len);
30 32
31ieee80211_tx_result 33ieee80211_tx_result
32ieee80211_crypto_aes_cmac_encrypt(struct ieee80211_tx_data *tx); 34ieee80211_crypto_aes_cmac_encrypt(struct ieee80211_tx_data *tx);