diff options
author | Jouni Malinen <jouni@qca.qualcomm.com> | 2015-01-24 12:52:07 -0500 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2015-01-27 05:07:35 -0500 |
commit | 2b2ba0db1c820d04d5143452d70012cd44d7b578 (patch) | |
tree | 7c186fc249d191d9ecba66e740e7a4c922a986d5 /net | |
parent | 00b9cfa3ff38401bd70c34b250ca13e5ea347b4a (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.c | 21 | ||||
-rw-r--r-- | net/mac80211/aes_ccm.h | 10 | ||||
-rw-r--r-- | net/mac80211/cfg.c | 2 | ||||
-rw-r--r-- | net/mac80211/debugfs_key.c | 3 | ||||
-rw-r--r-- | net/mac80211/key.c | 27 | ||||
-rw-r--r-- | net/mac80211/main.c | 6 | ||||
-rw-r--r-- | net/mac80211/rx.c | 15 | ||||
-rw-r--r-- | net/mac80211/tx.c | 7 | ||||
-rw-r--r-- | net/mac80211/wpa.c | 22 | ||||
-rw-r--r-- | net/mac80211/wpa.h | 6 |
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 | ||
22 | void ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, | 22 | void 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 | ||
47 | int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, | 48 | int 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 | ||
75 | struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[]) | 76 | struct 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 | ||
15 | struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[]); | 15 | struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[], |
16 | size_t key_len, | ||
17 | size_t mic_len); | ||
16 | void ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, | 18 | void 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); | ||
18 | int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, | 21 | int 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); | ||
20 | void ieee80211_aes_key_free(struct crypto_aead *tfm); | 24 | void 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 | ||
397 | static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) | 397 | static 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 | ||
469 | ieee80211_tx_result | 470 | ieee80211_tx_result |
470 | ieee80211_crypto_ccmp_encrypt(struct ieee80211_tx_data *tx) | 471 | ieee80211_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 | ||
485 | ieee80211_rx_result | 487 | ieee80211_rx_result |
486 | ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) | 488 | ieee80211_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 | |||
24 | ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx); | 24 | ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx); |
25 | 25 | ||
26 | ieee80211_tx_result | 26 | ieee80211_tx_result |
27 | ieee80211_crypto_ccmp_encrypt(struct ieee80211_tx_data *tx); | 27 | ieee80211_crypto_ccmp_encrypt(struct ieee80211_tx_data *tx, |
28 | unsigned int mic_len); | ||
28 | ieee80211_rx_result | 29 | ieee80211_rx_result |
29 | ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx); | 30 | ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx, |
31 | unsigned int mic_len); | ||
30 | 32 | ||
31 | ieee80211_tx_result | 33 | ieee80211_tx_result |
32 | ieee80211_crypto_aes_cmac_encrypt(struct ieee80211_tx_data *tx); | 34 | ieee80211_crypto_aes_cmac_encrypt(struct ieee80211_tx_data *tx); |