diff options
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/aes_ccm.c | 46 | ||||
-rw-r--r-- | net/mac80211/aes_ccm.h | 8 | ||||
-rw-r--r-- | net/mac80211/aes_gcm.c | 43 | ||||
-rw-r--r-- | net/mac80211/aes_gcm.h | 6 | ||||
-rw-r--r-- | net/mac80211/aes_gmac.c | 26 | ||||
-rw-r--r-- | net/mac80211/aes_gmac.h | 4 | ||||
-rw-r--r-- | net/mac80211/offchannel.c | 2 | ||||
-rw-r--r-- | net/mac80211/rx.c | 51 | ||||
-rw-r--r-- | net/mac80211/wpa.c | 22 |
9 files changed, 135 insertions, 73 deletions
diff --git a/net/mac80211/aes_ccm.c b/net/mac80211/aes_ccm.c index 7663c28ba353..a4e0d59a40dd 100644 --- a/net/mac80211/aes_ccm.c +++ b/net/mac80211/aes_ccm.c | |||
@@ -18,21 +18,24 @@ | |||
18 | #include "key.h" | 18 | #include "key.h" |
19 | #include "aes_ccm.h" | 19 | #include "aes_ccm.h" |
20 | 20 | ||
21 | void ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, | 21 | int ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, |
22 | u8 *data, size_t data_len, u8 *mic, | 22 | u8 *data, size_t data_len, u8 *mic, |
23 | size_t mic_len) | 23 | size_t mic_len) |
24 | { | 24 | { |
25 | struct scatterlist sg[3]; | 25 | struct scatterlist sg[3]; |
26 | struct aead_request *aead_req; | ||
27 | int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm); | ||
28 | u8 *__aad; | ||
26 | 29 | ||
27 | char aead_req_data[sizeof(struct aead_request) + | 30 | aead_req = kzalloc(reqsize + CCM_AAD_LEN, GFP_ATOMIC); |
28 | crypto_aead_reqsize(tfm)] | 31 | if (!aead_req) |
29 | __aligned(__alignof__(struct aead_request)); | 32 | return -ENOMEM; |
30 | struct aead_request *aead_req = (void *) aead_req_data; | ||
31 | 33 | ||
32 | memset(aead_req, 0, sizeof(aead_req_data)); | 34 | __aad = (u8 *)aead_req + reqsize; |
35 | memcpy(__aad, aad, CCM_AAD_LEN); | ||
33 | 36 | ||
34 | sg_init_table(sg, 3); | 37 | sg_init_table(sg, 3); |
35 | sg_set_buf(&sg[0], &aad[2], be16_to_cpup((__be16 *)aad)); | 38 | sg_set_buf(&sg[0], &__aad[2], be16_to_cpup((__be16 *)__aad)); |
36 | sg_set_buf(&sg[1], data, data_len); | 39 | sg_set_buf(&sg[1], data, data_len); |
37 | sg_set_buf(&sg[2], mic, mic_len); | 40 | sg_set_buf(&sg[2], mic, mic_len); |
38 | 41 | ||
@@ -41,6 +44,9 @@ void ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, | |||
41 | aead_request_set_ad(aead_req, sg[0].length); | 44 | aead_request_set_ad(aead_req, sg[0].length); |
42 | 45 | ||
43 | crypto_aead_encrypt(aead_req); | 46 | crypto_aead_encrypt(aead_req); |
47 | kzfree(aead_req); | ||
48 | |||
49 | return 0; | ||
44 | } | 50 | } |
45 | 51 | ||
46 | int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, | 52 | int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, |
@@ -48,18 +54,23 @@ int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, | |||
48 | size_t mic_len) | 54 | size_t mic_len) |
49 | { | 55 | { |
50 | struct scatterlist sg[3]; | 56 | struct scatterlist sg[3]; |
51 | char aead_req_data[sizeof(struct aead_request) + | 57 | struct aead_request *aead_req; |
52 | crypto_aead_reqsize(tfm)] | 58 | int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm); |
53 | __aligned(__alignof__(struct aead_request)); | 59 | u8 *__aad; |
54 | struct aead_request *aead_req = (void *) aead_req_data; | 60 | int err; |
55 | 61 | ||
56 | if (data_len == 0) | 62 | if (data_len == 0) |
57 | return -EINVAL; | 63 | return -EINVAL; |
58 | 64 | ||
59 | memset(aead_req, 0, sizeof(aead_req_data)); | 65 | aead_req = kzalloc(reqsize + CCM_AAD_LEN, GFP_ATOMIC); |
66 | if (!aead_req) | ||
67 | return -ENOMEM; | ||
68 | |||
69 | __aad = (u8 *)aead_req + reqsize; | ||
70 | memcpy(__aad, aad, CCM_AAD_LEN); | ||
60 | 71 | ||
61 | sg_init_table(sg, 3); | 72 | sg_init_table(sg, 3); |
62 | sg_set_buf(&sg[0], &aad[2], be16_to_cpup((__be16 *)aad)); | 73 | sg_set_buf(&sg[0], &__aad[2], be16_to_cpup((__be16 *)__aad)); |
63 | sg_set_buf(&sg[1], data, data_len); | 74 | sg_set_buf(&sg[1], data, data_len); |
64 | sg_set_buf(&sg[2], mic, mic_len); | 75 | sg_set_buf(&sg[2], mic, mic_len); |
65 | 76 | ||
@@ -67,7 +78,10 @@ int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, | |||
67 | aead_request_set_crypt(aead_req, sg, sg, data_len + mic_len, b_0); | 78 | aead_request_set_crypt(aead_req, sg, sg, data_len + mic_len, b_0); |
68 | aead_request_set_ad(aead_req, sg[0].length); | 79 | aead_request_set_ad(aead_req, sg[0].length); |
69 | 80 | ||
70 | return crypto_aead_decrypt(aead_req); | 81 | err = crypto_aead_decrypt(aead_req); |
82 | kzfree(aead_req); | ||
83 | |||
84 | return err; | ||
71 | } | 85 | } |
72 | 86 | ||
73 | struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[], | 87 | struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[], |
diff --git a/net/mac80211/aes_ccm.h b/net/mac80211/aes_ccm.h index 6a73d1e4d186..fcd3254c5cf0 100644 --- a/net/mac80211/aes_ccm.h +++ b/net/mac80211/aes_ccm.h | |||
@@ -12,12 +12,14 @@ | |||
12 | 12 | ||
13 | #include <linux/crypto.h> | 13 | #include <linux/crypto.h> |
14 | 14 | ||
15 | #define CCM_AAD_LEN 32 | ||
16 | |||
15 | struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[], | 17 | struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[], |
16 | size_t key_len, | 18 | size_t key_len, |
17 | size_t mic_len); | 19 | size_t mic_len); |
18 | void ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, | 20 | int ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, |
19 | u8 *data, size_t data_len, u8 *mic, | 21 | u8 *data, size_t data_len, u8 *mic, |
20 | size_t mic_len); | 22 | size_t mic_len); |
21 | int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, | 23 | int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, |
22 | u8 *data, size_t data_len, u8 *mic, | 24 | u8 *data, size_t data_len, u8 *mic, |
23 | size_t mic_len); | 25 | size_t mic_len); |
diff --git a/net/mac80211/aes_gcm.c b/net/mac80211/aes_gcm.c index 3afe361fd27c..8a4397cc1b08 100644 --- a/net/mac80211/aes_gcm.c +++ b/net/mac80211/aes_gcm.c | |||
@@ -15,20 +15,23 @@ | |||
15 | #include "key.h" | 15 | #include "key.h" |
16 | #include "aes_gcm.h" | 16 | #include "aes_gcm.h" |
17 | 17 | ||
18 | void ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad, | 18 | int ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad, |
19 | u8 *data, size_t data_len, u8 *mic) | 19 | u8 *data, size_t data_len, u8 *mic) |
20 | { | 20 | { |
21 | struct scatterlist sg[3]; | 21 | struct scatterlist sg[3]; |
22 | struct aead_request *aead_req; | ||
23 | int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm); | ||
24 | u8 *__aad; | ||
22 | 25 | ||
23 | char aead_req_data[sizeof(struct aead_request) + | 26 | aead_req = kzalloc(reqsize + GCM_AAD_LEN, GFP_ATOMIC); |
24 | crypto_aead_reqsize(tfm)] | 27 | if (!aead_req) |
25 | __aligned(__alignof__(struct aead_request)); | 28 | return -ENOMEM; |
26 | struct aead_request *aead_req = (void *)aead_req_data; | ||
27 | 29 | ||
28 | memset(aead_req, 0, sizeof(aead_req_data)); | 30 | __aad = (u8 *)aead_req + reqsize; |
31 | memcpy(__aad, aad, GCM_AAD_LEN); | ||
29 | 32 | ||
30 | sg_init_table(sg, 3); | 33 | sg_init_table(sg, 3); |
31 | sg_set_buf(&sg[0], &aad[2], be16_to_cpup((__be16 *)aad)); | 34 | sg_set_buf(&sg[0], &__aad[2], be16_to_cpup((__be16 *)__aad)); |
32 | sg_set_buf(&sg[1], data, data_len); | 35 | sg_set_buf(&sg[1], data, data_len); |
33 | sg_set_buf(&sg[2], mic, IEEE80211_GCMP_MIC_LEN); | 36 | sg_set_buf(&sg[2], mic, IEEE80211_GCMP_MIC_LEN); |
34 | 37 | ||
@@ -37,24 +40,31 @@ void ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad, | |||
37 | aead_request_set_ad(aead_req, sg[0].length); | 40 | aead_request_set_ad(aead_req, sg[0].length); |
38 | 41 | ||
39 | crypto_aead_encrypt(aead_req); | 42 | crypto_aead_encrypt(aead_req); |
43 | kzfree(aead_req); | ||
44 | return 0; | ||
40 | } | 45 | } |
41 | 46 | ||
42 | int ieee80211_aes_gcm_decrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad, | 47 | int ieee80211_aes_gcm_decrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad, |
43 | u8 *data, size_t data_len, u8 *mic) | 48 | u8 *data, size_t data_len, u8 *mic) |
44 | { | 49 | { |
45 | struct scatterlist sg[3]; | 50 | struct scatterlist sg[3]; |
46 | char aead_req_data[sizeof(struct aead_request) + | 51 | struct aead_request *aead_req; |
47 | crypto_aead_reqsize(tfm)] | 52 | int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm); |
48 | __aligned(__alignof__(struct aead_request)); | 53 | u8 *__aad; |
49 | struct aead_request *aead_req = (void *)aead_req_data; | 54 | int err; |
50 | 55 | ||
51 | if (data_len == 0) | 56 | if (data_len == 0) |
52 | return -EINVAL; | 57 | return -EINVAL; |
53 | 58 | ||
54 | memset(aead_req, 0, sizeof(aead_req_data)); | 59 | aead_req = kzalloc(reqsize + GCM_AAD_LEN, GFP_ATOMIC); |
60 | if (!aead_req) | ||
61 | return -ENOMEM; | ||
62 | |||
63 | __aad = (u8 *)aead_req + reqsize; | ||
64 | memcpy(__aad, aad, GCM_AAD_LEN); | ||
55 | 65 | ||
56 | sg_init_table(sg, 3); | 66 | sg_init_table(sg, 3); |
57 | sg_set_buf(&sg[0], &aad[2], be16_to_cpup((__be16 *)aad)); | 67 | sg_set_buf(&sg[0], &__aad[2], be16_to_cpup((__be16 *)__aad)); |
58 | sg_set_buf(&sg[1], data, data_len); | 68 | sg_set_buf(&sg[1], data, data_len); |
59 | sg_set_buf(&sg[2], mic, IEEE80211_GCMP_MIC_LEN); | 69 | sg_set_buf(&sg[2], mic, IEEE80211_GCMP_MIC_LEN); |
60 | 70 | ||
@@ -63,7 +73,10 @@ int ieee80211_aes_gcm_decrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad, | |||
63 | data_len + IEEE80211_GCMP_MIC_LEN, j_0); | 73 | data_len + IEEE80211_GCMP_MIC_LEN, j_0); |
64 | aead_request_set_ad(aead_req, sg[0].length); | 74 | aead_request_set_ad(aead_req, sg[0].length); |
65 | 75 | ||
66 | return crypto_aead_decrypt(aead_req); | 76 | err = crypto_aead_decrypt(aead_req); |
77 | kzfree(aead_req); | ||
78 | |||
79 | return err; | ||
67 | } | 80 | } |
68 | 81 | ||
69 | struct crypto_aead *ieee80211_aes_gcm_key_setup_encrypt(const u8 key[], | 82 | struct crypto_aead *ieee80211_aes_gcm_key_setup_encrypt(const u8 key[], |
diff --git a/net/mac80211/aes_gcm.h b/net/mac80211/aes_gcm.h index 1347fda6b76a..55aed5352494 100644 --- a/net/mac80211/aes_gcm.h +++ b/net/mac80211/aes_gcm.h | |||
@@ -11,8 +11,10 @@ | |||
11 | 11 | ||
12 | #include <linux/crypto.h> | 12 | #include <linux/crypto.h> |
13 | 13 | ||
14 | void ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad, | 14 | #define GCM_AAD_LEN 32 |
15 | u8 *data, size_t data_len, u8 *mic); | 15 | |
16 | int ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad, | ||
17 | u8 *data, size_t data_len, u8 *mic); | ||
16 | int ieee80211_aes_gcm_decrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad, | 18 | int ieee80211_aes_gcm_decrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad, |
17 | u8 *data, size_t data_len, u8 *mic); | 19 | u8 *data, size_t data_len, u8 *mic); |
18 | struct crypto_aead *ieee80211_aes_gcm_key_setup_encrypt(const u8 key[], | 20 | struct crypto_aead *ieee80211_aes_gcm_key_setup_encrypt(const u8 key[], |
diff --git a/net/mac80211/aes_gmac.c b/net/mac80211/aes_gmac.c index 3ddd927aaf30..bd72a862ddb7 100644 --- a/net/mac80211/aes_gmac.c +++ b/net/mac80211/aes_gmac.c | |||
@@ -17,28 +17,27 @@ | |||
17 | #include "key.h" | 17 | #include "key.h" |
18 | #include "aes_gmac.h" | 18 | #include "aes_gmac.h" |
19 | 19 | ||
20 | #define GMAC_MIC_LEN 16 | ||
21 | #define GMAC_NONCE_LEN 12 | ||
22 | #define AAD_LEN 20 | ||
23 | |||
24 | int ieee80211_aes_gmac(struct crypto_aead *tfm, const u8 *aad, u8 *nonce, | 20 | int ieee80211_aes_gmac(struct crypto_aead *tfm, const u8 *aad, u8 *nonce, |
25 | const u8 *data, size_t data_len, u8 *mic) | 21 | const u8 *data, size_t data_len, u8 *mic) |
26 | { | 22 | { |
27 | struct scatterlist sg[4]; | 23 | struct scatterlist sg[4]; |
28 | char aead_req_data[sizeof(struct aead_request) + | 24 | u8 *zero, *__aad, iv[AES_BLOCK_SIZE]; |
29 | crypto_aead_reqsize(tfm)] | 25 | struct aead_request *aead_req; |
30 | __aligned(__alignof__(struct aead_request)); | 26 | int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm); |
31 | struct aead_request *aead_req = (void *)aead_req_data; | ||
32 | u8 zero[GMAC_MIC_LEN], iv[AES_BLOCK_SIZE]; | ||
33 | 27 | ||
34 | if (data_len < GMAC_MIC_LEN) | 28 | if (data_len < GMAC_MIC_LEN) |
35 | return -EINVAL; | 29 | return -EINVAL; |
36 | 30 | ||
37 | memset(aead_req, 0, sizeof(aead_req_data)); | 31 | aead_req = kzalloc(reqsize + GMAC_MIC_LEN + GMAC_AAD_LEN, GFP_ATOMIC); |
32 | if (!aead_req) | ||
33 | return -ENOMEM; | ||
34 | |||
35 | zero = (u8 *)aead_req + reqsize; | ||
36 | __aad = zero + GMAC_MIC_LEN; | ||
37 | memcpy(__aad, aad, GMAC_AAD_LEN); | ||
38 | 38 | ||
39 | memset(zero, 0, GMAC_MIC_LEN); | ||
40 | sg_init_table(sg, 4); | 39 | sg_init_table(sg, 4); |
41 | sg_set_buf(&sg[0], aad, AAD_LEN); | 40 | sg_set_buf(&sg[0], __aad, GMAC_AAD_LEN); |
42 | sg_set_buf(&sg[1], data, data_len - GMAC_MIC_LEN); | 41 | sg_set_buf(&sg[1], data, data_len - GMAC_MIC_LEN); |
43 | sg_set_buf(&sg[2], zero, GMAC_MIC_LEN); | 42 | sg_set_buf(&sg[2], zero, GMAC_MIC_LEN); |
44 | sg_set_buf(&sg[3], mic, GMAC_MIC_LEN); | 43 | sg_set_buf(&sg[3], mic, GMAC_MIC_LEN); |
@@ -49,9 +48,10 @@ int ieee80211_aes_gmac(struct crypto_aead *tfm, const u8 *aad, u8 *nonce, | |||
49 | 48 | ||
50 | aead_request_set_tfm(aead_req, tfm); | 49 | aead_request_set_tfm(aead_req, tfm); |
51 | aead_request_set_crypt(aead_req, sg, sg, 0, iv); | 50 | aead_request_set_crypt(aead_req, sg, sg, 0, iv); |
52 | aead_request_set_ad(aead_req, AAD_LEN + data_len); | 51 | aead_request_set_ad(aead_req, GMAC_AAD_LEN + data_len); |
53 | 52 | ||
54 | crypto_aead_encrypt(aead_req); | 53 | crypto_aead_encrypt(aead_req); |
54 | kzfree(aead_req); | ||
55 | 55 | ||
56 | return 0; | 56 | return 0; |
57 | } | 57 | } |
diff --git a/net/mac80211/aes_gmac.h b/net/mac80211/aes_gmac.h index d328204d73a8..32e6442c95be 100644 --- a/net/mac80211/aes_gmac.h +++ b/net/mac80211/aes_gmac.h | |||
@@ -11,6 +11,10 @@ | |||
11 | 11 | ||
12 | #include <linux/crypto.h> | 12 | #include <linux/crypto.h> |
13 | 13 | ||
14 | #define GMAC_AAD_LEN 20 | ||
15 | #define GMAC_MIC_LEN 16 | ||
16 | #define GMAC_NONCE_LEN 12 | ||
17 | |||
14 | struct crypto_aead *ieee80211_aes_gmac_key_setup(const u8 key[], | 18 | struct crypto_aead *ieee80211_aes_gmac_key_setup(const u8 key[], |
15 | size_t key_len); | 19 | size_t key_len); |
16 | int ieee80211_aes_gmac(struct crypto_aead *tfm, const u8 *aad, u8 *nonce, | 20 | int ieee80211_aes_gmac(struct crypto_aead *tfm, const u8 *aad, u8 *nonce, |
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c index c3f610bba3fe..eede5c6db8d5 100644 --- a/net/mac80211/offchannel.c +++ b/net/mac80211/offchannel.c | |||
@@ -820,7 +820,7 @@ int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, | |||
820 | mgmt->u.action.category == WLAN_CATEGORY_SPECTRUM_MGMT) | 820 | mgmt->u.action.category == WLAN_CATEGORY_SPECTRUM_MGMT) |
821 | break; | 821 | break; |
822 | rcu_read_lock(); | 822 | rcu_read_lock(); |
823 | sta = sta_info_get(sdata, mgmt->da); | 823 | sta = sta_info_get_bss(sdata, mgmt->da); |
824 | rcu_read_unlock(); | 824 | rcu_read_unlock(); |
825 | if (!sta) | 825 | if (!sta) |
826 | return -ENOLINK; | 826 | return -ENOLINK; |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 6175db385ba7..a47bbc973f2d 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -2298,6 +2298,8 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx) | |||
2298 | __le16 fc = hdr->frame_control; | 2298 | __le16 fc = hdr->frame_control; |
2299 | struct sk_buff_head frame_list; | 2299 | struct sk_buff_head frame_list; |
2300 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb); | 2300 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb); |
2301 | struct ethhdr ethhdr; | ||
2302 | const u8 *check_da = ethhdr.h_dest, *check_sa = ethhdr.h_source; | ||
2301 | 2303 | ||
2302 | if (unlikely(!ieee80211_is_data(fc))) | 2304 | if (unlikely(!ieee80211_is_data(fc))) |
2303 | return RX_CONTINUE; | 2305 | return RX_CONTINUE; |
@@ -2308,24 +2310,53 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx) | |||
2308 | if (!(status->rx_flags & IEEE80211_RX_AMSDU)) | 2310 | if (!(status->rx_flags & IEEE80211_RX_AMSDU)) |
2309 | return RX_CONTINUE; | 2311 | return RX_CONTINUE; |
2310 | 2312 | ||
2311 | if (ieee80211_has_a4(hdr->frame_control) && | 2313 | if (unlikely(ieee80211_has_a4(hdr->frame_control))) { |
2312 | rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN && | 2314 | switch (rx->sdata->vif.type) { |
2313 | !rx->sdata->u.vlan.sta) | 2315 | case NL80211_IFTYPE_AP_VLAN: |
2314 | return RX_DROP_UNUSABLE; | 2316 | if (!rx->sdata->u.vlan.sta) |
2317 | return RX_DROP_UNUSABLE; | ||
2318 | break; | ||
2319 | case NL80211_IFTYPE_STATION: | ||
2320 | if (!rx->sdata->u.mgd.use_4addr) | ||
2321 | return RX_DROP_UNUSABLE; | ||
2322 | break; | ||
2323 | default: | ||
2324 | return RX_DROP_UNUSABLE; | ||
2325 | } | ||
2326 | check_da = NULL; | ||
2327 | check_sa = NULL; | ||
2328 | } else switch (rx->sdata->vif.type) { | ||
2329 | case NL80211_IFTYPE_AP: | ||
2330 | case NL80211_IFTYPE_AP_VLAN: | ||
2331 | check_da = NULL; | ||
2332 | break; | ||
2333 | case NL80211_IFTYPE_STATION: | ||
2334 | if (!rx->sta || | ||
2335 | !test_sta_flag(rx->sta, WLAN_STA_TDLS_PEER)) | ||
2336 | check_sa = NULL; | ||
2337 | break; | ||
2338 | case NL80211_IFTYPE_MESH_POINT: | ||
2339 | check_sa = NULL; | ||
2340 | break; | ||
2341 | default: | ||
2342 | break; | ||
2343 | } | ||
2315 | 2344 | ||
2316 | if (is_multicast_ether_addr(hdr->addr1) && | 2345 | if (is_multicast_ether_addr(hdr->addr1)) |
2317 | ((rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN && | ||
2318 | rx->sdata->u.vlan.sta) || | ||
2319 | (rx->sdata->vif.type == NL80211_IFTYPE_STATION && | ||
2320 | rx->sdata->u.mgd.use_4addr))) | ||
2321 | return RX_DROP_UNUSABLE; | 2346 | return RX_DROP_UNUSABLE; |
2322 | 2347 | ||
2323 | skb->dev = dev; | 2348 | skb->dev = dev; |
2324 | __skb_queue_head_init(&frame_list); | 2349 | __skb_queue_head_init(&frame_list); |
2325 | 2350 | ||
2351 | if (ieee80211_data_to_8023_exthdr(skb, ðhdr, | ||
2352 | rx->sdata->vif.addr, | ||
2353 | rx->sdata->vif.type)) | ||
2354 | return RX_DROP_UNUSABLE; | ||
2355 | |||
2326 | ieee80211_amsdu_to_8023s(skb, &frame_list, dev->dev_addr, | 2356 | ieee80211_amsdu_to_8023s(skb, &frame_list, dev->dev_addr, |
2327 | rx->sdata->vif.type, | 2357 | rx->sdata->vif.type, |
2328 | rx->local->hw.extra_tx_headroom, true); | 2358 | rx->local->hw.extra_tx_headroom, |
2359 | check_da, check_sa); | ||
2329 | 2360 | ||
2330 | while (!skb_queue_empty(&frame_list)) { | 2361 | while (!skb_queue_empty(&frame_list)) { |
2331 | rx->skb = __skb_dequeue(&frame_list); | 2362 | rx->skb = __skb_dequeue(&frame_list); |
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index b48c1e13e281..42ce9bd4426f 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c | |||
@@ -405,7 +405,7 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb, | |||
405 | u8 *pos; | 405 | u8 *pos; |
406 | u8 pn[6]; | 406 | u8 pn[6]; |
407 | u64 pn64; | 407 | u64 pn64; |
408 | u8 aad[2 * AES_BLOCK_SIZE]; | 408 | u8 aad[CCM_AAD_LEN]; |
409 | u8 b_0[AES_BLOCK_SIZE]; | 409 | u8 b_0[AES_BLOCK_SIZE]; |
410 | 410 | ||
411 | if (info->control.hw_key && | 411 | if (info->control.hw_key && |
@@ -461,10 +461,8 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb, | |||
461 | 461 | ||
462 | pos += IEEE80211_CCMP_HDR_LEN; | 462 | pos += IEEE80211_CCMP_HDR_LEN; |
463 | ccmp_special_blocks(skb, pn, b_0, aad); | 463 | ccmp_special_blocks(skb, pn, b_0, aad); |
464 | ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, b_0, aad, pos, len, | 464 | return ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, b_0, aad, pos, len, |
465 | skb_put(skb, mic_len), mic_len); | 465 | skb_put(skb, mic_len), mic_len); |
466 | |||
467 | return 0; | ||
468 | } | 466 | } |
469 | 467 | ||
470 | 468 | ||
@@ -639,7 +637,7 @@ static int gcmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) | |||
639 | u8 *pos; | 637 | u8 *pos; |
640 | u8 pn[6]; | 638 | u8 pn[6]; |
641 | u64 pn64; | 639 | u64 pn64; |
642 | u8 aad[2 * AES_BLOCK_SIZE]; | 640 | u8 aad[GCM_AAD_LEN]; |
643 | u8 j_0[AES_BLOCK_SIZE]; | 641 | u8 j_0[AES_BLOCK_SIZE]; |
644 | 642 | ||
645 | if (info->control.hw_key && | 643 | if (info->control.hw_key && |
@@ -696,10 +694,8 @@ static int gcmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) | |||
696 | 694 | ||
697 | pos += IEEE80211_GCMP_HDR_LEN; | 695 | pos += IEEE80211_GCMP_HDR_LEN; |
698 | gcmp_special_blocks(skb, pn, j_0, aad); | 696 | gcmp_special_blocks(skb, pn, j_0, aad); |
699 | ieee80211_aes_gcm_encrypt(key->u.gcmp.tfm, j_0, aad, pos, len, | 697 | return ieee80211_aes_gcm_encrypt(key->u.gcmp.tfm, j_0, aad, pos, len, |
700 | skb_put(skb, IEEE80211_GCMP_MIC_LEN)); | 698 | skb_put(skb, IEEE80211_GCMP_MIC_LEN)); |
701 | |||
702 | return 0; | ||
703 | } | 699 | } |
704 | 700 | ||
705 | ieee80211_tx_result | 701 | ieee80211_tx_result |
@@ -1123,9 +1119,9 @@ ieee80211_crypto_aes_gmac_encrypt(struct ieee80211_tx_data *tx) | |||
1123 | struct ieee80211_key *key = tx->key; | 1119 | struct ieee80211_key *key = tx->key; |
1124 | struct ieee80211_mmie_16 *mmie; | 1120 | struct ieee80211_mmie_16 *mmie; |
1125 | struct ieee80211_hdr *hdr; | 1121 | struct ieee80211_hdr *hdr; |
1126 | u8 aad[20]; | 1122 | u8 aad[GMAC_AAD_LEN]; |
1127 | u64 pn64; | 1123 | u64 pn64; |
1128 | u8 nonce[12]; | 1124 | u8 nonce[GMAC_NONCE_LEN]; |
1129 | 1125 | ||
1130 | if (WARN_ON(skb_queue_len(&tx->skbs) != 1)) | 1126 | if (WARN_ON(skb_queue_len(&tx->skbs) != 1)) |
1131 | return TX_DROP; | 1127 | return TX_DROP; |
@@ -1171,7 +1167,7 @@ ieee80211_crypto_aes_gmac_decrypt(struct ieee80211_rx_data *rx) | |||
1171 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | 1167 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); |
1172 | struct ieee80211_key *key = rx->key; | 1168 | struct ieee80211_key *key = rx->key; |
1173 | struct ieee80211_mmie_16 *mmie; | 1169 | struct ieee80211_mmie_16 *mmie; |
1174 | u8 aad[20], mic[16], ipn[6], nonce[12]; | 1170 | u8 aad[GMAC_AAD_LEN], mic[GMAC_MIC_LEN], ipn[6], nonce[GMAC_NONCE_LEN]; |
1175 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 1171 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
1176 | 1172 | ||
1177 | if (!ieee80211_is_mgmt(hdr->frame_control)) | 1173 | if (!ieee80211_is_mgmt(hdr->frame_control)) |