aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJouni Malinen <jouni@qca.qualcomm.com>2015-01-24 12:52:06 -0500
committerJohannes Berg <johannes.berg@intel.com>2015-01-27 05:06:09 -0500
commit00b9cfa3ff38401bd70c34b250ca13e5ea347b4a (patch)
tree1c3564bf28a6f4b49140a5e023520a1dc658d5c6
parentcfcf1682c4ca8f601a4702255958e0b1c9aa12cc (diff)
mac80111: Add GCMP and GCMP-256 ciphers
This allows mac80211 to configure GCMP and GCMP-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> [remove a spurious newline] Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r--include/net/mac80211.h15
-rw-r--r--net/mac80211/Kconfig1
-rw-r--r--net/mac80211/Makefile1
-rw-r--r--net/mac80211/aes_gcm.c95
-rw-r--r--net/mac80211/aes_gcm.h22
-rw-r--r--net/mac80211/cfg.c13
-rw-r--r--net/mac80211/debugfs_key.c22
-rw-r--r--net/mac80211/key.c74
-rw-r--r--net/mac80211/key.h11
-rw-r--r--net/mac80211/main.c9
-rw-r--r--net/mac80211/rx.c4
-rw-r--r--net/mac80211/tx.c5
-rw-r--r--net/mac80211/wpa.c224
-rw-r--r--net/mac80211/wpa.h5
14 files changed, 492 insertions, 9 deletions
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 866073e27ea2..ae6638436112 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -1294,8 +1294,8 @@ struct ieee80211_vif *wdev_to_ieee80211_vif(struct wireless_dev *wdev);
1294 * @IEEE80211_KEY_FLAG_PAIRWISE: Set by mac80211, this flag indicates 1294 * @IEEE80211_KEY_FLAG_PAIRWISE: Set by mac80211, this flag indicates
1295 * that the key is pairwise rather then a shared key. 1295 * that the key is pairwise rather then a shared key.
1296 * @IEEE80211_KEY_FLAG_SW_MGMT_TX: This flag should be set by the driver for a 1296 * @IEEE80211_KEY_FLAG_SW_MGMT_TX: This flag should be set by the driver for a
1297 * CCMP key if it requires CCMP encryption of management frames (MFP) to 1297 * CCMP/GCMP key if it requires CCMP/GCMP encryption of management frames
1298 * be done in software. 1298 * (MFP) to be done in software.
1299 * @IEEE80211_KEY_FLAG_PUT_IV_SPACE: This flag should be set by the driver 1299 * @IEEE80211_KEY_FLAG_PUT_IV_SPACE: This flag should be set by the driver
1300 * if space should be prepared for the IV, but the IV 1300 * if space should be prepared for the IV, but the IV
1301 * itself should not be generated. Do not set together with 1301 * itself should not be generated. Do not set together with
@@ -1310,7 +1310,7 @@ struct ieee80211_vif *wdev_to_ieee80211_vif(struct wireless_dev *wdev);
1310 * RX, if your crypto engine can't deal with TX you can also set the 1310 * RX, if your crypto engine can't deal with TX you can also set the
1311 * %IEEE80211_KEY_FLAG_SW_MGMT_TX flag to encrypt such frames in SW. 1311 * %IEEE80211_KEY_FLAG_SW_MGMT_TX flag to encrypt such frames in SW.
1312 * @IEEE80211_KEY_FLAG_GENERATE_IV_MGMT: This flag should be set by the 1312 * @IEEE80211_KEY_FLAG_GENERATE_IV_MGMT: This flag should be set by the
1313 * driver for a CCMP key to indicate that is requires IV generation 1313 * driver for a CCMP/GCMP key to indicate that is requires IV generation
1314 * only for managment frames (MFP). 1314 * only for managment frames (MFP).
1315 * @IEEE80211_KEY_FLAG_RESERVE_TAILROOM: This flag should be set by the 1315 * @IEEE80211_KEY_FLAG_RESERVE_TAILROOM: This flag should be set by the
1316 * driver for a key to indicate that sufficient tailroom must always 1316 * driver for a key to indicate that sufficient tailroom must always
@@ -4098,6 +4098,8 @@ void ieee80211_aes_cmac_calculate_k1_k2(struct ieee80211_key_conf *keyconf,
4098 * reverse order than in packet) 4098 * reverse order than in packet)
4099 * @aes_cmac: PN data, most significant byte first (big endian, 4099 * @aes_cmac: PN data, most significant byte first (big endian,
4100 * reverse order than in packet) 4100 * reverse order than in packet)
4101 * @gcmp: PN data, most significant byte first (big endian,
4102 * reverse order than in packet)
4101 */ 4103 */
4102struct ieee80211_key_seq { 4104struct ieee80211_key_seq {
4103 union { 4105 union {
@@ -4111,6 +4113,9 @@ struct ieee80211_key_seq {
4111 struct { 4113 struct {
4112 u8 pn[6]; 4114 u8 pn[6];
4113 } aes_cmac; 4115 } aes_cmac;
4116 struct {
4117 u8 pn[6];
4118 } gcmp;
4114 }; 4119 };
4115}; 4120};
4116 4121
@@ -4135,7 +4140,7 @@ void ieee80211_get_key_tx_seq(struct ieee80211_key_conf *keyconf,
4135 * ieee80211_get_key_rx_seq - get key RX sequence counter 4140 * ieee80211_get_key_rx_seq - get key RX sequence counter
4136 * 4141 *
4137 * @keyconf: the parameter passed with the set key 4142 * @keyconf: the parameter passed with the set key
4138 * @tid: The TID, or -1 for the management frame value (CCMP only); 4143 * @tid: The TID, or -1 for the management frame value (CCMP/GCMP only);
4139 * the value on TID 0 is also used for non-QoS frames. For 4144 * the value on TID 0 is also used for non-QoS frames. For
4140 * CMAC, only TID 0 is valid. 4145 * CMAC, only TID 0 is valid.
4141 * @seq: buffer to receive the sequence data 4146 * @seq: buffer to receive the sequence data
@@ -4171,7 +4176,7 @@ void ieee80211_set_key_tx_seq(struct ieee80211_key_conf *keyconf,
4171 * ieee80211_set_key_rx_seq - set key RX sequence counter 4176 * ieee80211_set_key_rx_seq - set key RX sequence counter
4172 * 4177 *
4173 * @keyconf: the parameter passed with the set key 4178 * @keyconf: the parameter passed with the set key
4174 * @tid: The TID, or -1 for the management frame value (CCMP only); 4179 * @tid: The TID, or -1 for the management frame value (CCMP/GCMP only);
4175 * the value on TID 0 is also used for non-QoS frames. For 4180 * the value on TID 0 is also used for non-QoS frames. For
4176 * CMAC, only TID 0 is valid. 4181 * CMAC, only TID 0 is valid.
4177 * @seq: new sequence data 4182 * @seq: new sequence data
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig
index 75cc6801a431..64a012a0c6e5 100644
--- a/net/mac80211/Kconfig
+++ b/net/mac80211/Kconfig
@@ -5,6 +5,7 @@ config MAC80211
5 select CRYPTO_ARC4 5 select CRYPTO_ARC4
6 select CRYPTO_AES 6 select CRYPTO_AES
7 select CRYPTO_CCM 7 select CRYPTO_CCM
8 select CRYPTO_GCM
8 select CRC32 9 select CRC32
9 select AVERAGE 10 select AVERAGE
10 ---help--- 11 ---help---
diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile
index e53671b1105e..0cbf93618433 100644
--- a/net/mac80211/Makefile
+++ b/net/mac80211/Makefile
@@ -15,6 +15,7 @@ mac80211-y := \
15 michael.o \ 15 michael.o \
16 tkip.o \ 16 tkip.o \
17 aes_ccm.o \ 17 aes_ccm.o \
18 aes_gcm.o \
18 aes_cmac.o \ 19 aes_cmac.o \
19 cfg.o \ 20 cfg.o \
20 ethtool.o \ 21 ethtool.o \
diff --git a/net/mac80211/aes_gcm.c b/net/mac80211/aes_gcm.c
new file mode 100644
index 000000000000..c2bf6698d738
--- /dev/null
+++ b/net/mac80211/aes_gcm.c
@@ -0,0 +1,95 @@
1/*
2 * Copyright 2014-2015, Qualcomm Atheros, Inc.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/kernel.h>
10#include <linux/types.h>
11#include <linux/crypto.h>
12#include <linux/err.h>
13#include <crypto/aes.h>
14
15#include <net/mac80211.h>
16#include "key.h"
17#include "aes_gcm.h"
18
19void ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
20 u8 *data, size_t data_len, u8 *mic)
21{
22 struct scatterlist assoc, pt, ct[2];
23
24 char aead_req_data[sizeof(struct aead_request) +
25 crypto_aead_reqsize(tfm)]
26 __aligned(__alignof__(struct aead_request));
27 struct aead_request *aead_req = (void *)aead_req_data;
28
29 memset(aead_req, 0, sizeof(aead_req_data));
30
31 sg_init_one(&pt, data, data_len);
32 sg_init_one(&assoc, &aad[2], be16_to_cpup((__be16 *)aad));
33 sg_init_table(ct, 2);
34 sg_set_buf(&ct[0], data, data_len);
35 sg_set_buf(&ct[1], mic, IEEE80211_GCMP_MIC_LEN);
36
37 aead_request_set_tfm(aead_req, tfm);
38 aead_request_set_assoc(aead_req, &assoc, assoc.length);
39 aead_request_set_crypt(aead_req, &pt, ct, data_len, j_0);
40
41 crypto_aead_encrypt(aead_req);
42}
43
44int ieee80211_aes_gcm_decrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
45 u8 *data, size_t data_len, u8 *mic)
46{
47 struct scatterlist assoc, pt, ct[2];
48 char aead_req_data[sizeof(struct aead_request) +
49 crypto_aead_reqsize(tfm)]
50 __aligned(__alignof__(struct aead_request));
51 struct aead_request *aead_req = (void *)aead_req_data;
52
53 if (data_len == 0)
54 return -EINVAL;
55
56 memset(aead_req, 0, sizeof(aead_req_data));
57
58 sg_init_one(&pt, data, data_len);
59 sg_init_one(&assoc, &aad[2], be16_to_cpup((__be16 *)aad));
60 sg_init_table(ct, 2);
61 sg_set_buf(&ct[0], data, data_len);
62 sg_set_buf(&ct[1], mic, IEEE80211_GCMP_MIC_LEN);
63
64 aead_request_set_tfm(aead_req, tfm);
65 aead_request_set_assoc(aead_req, &assoc, assoc.length);
66 aead_request_set_crypt(aead_req, ct, &pt,
67 data_len + IEEE80211_GCMP_MIC_LEN, j_0);
68
69 return crypto_aead_decrypt(aead_req);
70}
71
72struct crypto_aead *ieee80211_aes_gcm_key_setup_encrypt(const u8 key[],
73 size_t key_len)
74{
75 struct crypto_aead *tfm;
76 int err;
77
78 tfm = crypto_alloc_aead("gcm(aes)", 0, CRYPTO_ALG_ASYNC);
79 if (IS_ERR(tfm))
80 return tfm;
81
82 err = crypto_aead_setkey(tfm, key, key_len);
83 if (!err)
84 err = crypto_aead_setauthsize(tfm, IEEE80211_GCMP_MIC_LEN);
85 if (!err)
86 return tfm;
87
88 crypto_free_aead(tfm);
89 return ERR_PTR(err);
90}
91
92void ieee80211_aes_gcm_key_free(struct crypto_aead *tfm)
93{
94 crypto_free_aead(tfm);
95}
diff --git a/net/mac80211/aes_gcm.h b/net/mac80211/aes_gcm.h
new file mode 100644
index 000000000000..1347fda6b76a
--- /dev/null
+++ b/net/mac80211/aes_gcm.h
@@ -0,0 +1,22 @@
1/*
2 * Copyright 2014-2015, Qualcomm Atheros, Inc.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#ifndef AES_GCM_H
10#define AES_GCM_H
11
12#include <linux/crypto.h>
13
14void ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
15 u8 *data, size_t data_len, u8 *mic);
16int ieee80211_aes_gcm_decrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
17 u8 *data, size_t data_len, u8 *mic);
18struct crypto_aead *ieee80211_aes_gcm_key_setup_encrypt(const u8 key[],
19 size_t key_len);
20void ieee80211_aes_gcm_key_free(struct crypto_aead *tfm);
21
22#endif /* AES_GCM_H */
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index a777114d663b..1c1d061cff56 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -164,6 +164,7 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
164 case WLAN_CIPHER_SUITE_CCMP: 164 case WLAN_CIPHER_SUITE_CCMP:
165 case WLAN_CIPHER_SUITE_AES_CMAC: 165 case WLAN_CIPHER_SUITE_AES_CMAC:
166 case WLAN_CIPHER_SUITE_GCMP: 166 case WLAN_CIPHER_SUITE_GCMP:
167 case WLAN_CIPHER_SUITE_GCMP_256:
167 break; 168 break;
168 default: 169 default:
169 cs = ieee80211_cs_get(local, params->cipher, sdata->vif.type); 170 cs = ieee80211_cs_get(local, params->cipher, sdata->vif.type);
@@ -369,6 +370,18 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
369 params.seq = seq; 370 params.seq = seq;
370 params.seq_len = 6; 371 params.seq_len = 6;
371 break; 372 break;
373 case WLAN_CIPHER_SUITE_GCMP:
374 case WLAN_CIPHER_SUITE_GCMP_256:
375 pn64 = atomic64_read(&key->u.gcmp.tx_pn);
376 seq[0] = pn64;
377 seq[1] = pn64 >> 8;
378 seq[2] = pn64 >> 16;
379 seq[3] = pn64 >> 24;
380 seq[4] = pn64 >> 32;
381 seq[5] = pn64 >> 40;
382 params.seq = seq;
383 params.seq_len = 6;
384 break;
372 } 385 }
373 386
374 params.key = key->conf.key; 387 params.key = key->conf.key;
diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c
index 5523b94c7c90..0e223e602296 100644
--- a/net/mac80211/debugfs_key.c
+++ b/net/mac80211/debugfs_key.c
@@ -105,6 +105,13 @@ static ssize_t key_tx_spec_read(struct file *file, char __user *userbuf,
105 (u8)(pn >> 40), (u8)(pn >> 32), (u8)(pn >> 24), 105 (u8)(pn >> 40), (u8)(pn >> 32), (u8)(pn >> 24),
106 (u8)(pn >> 16), (u8)(pn >> 8), (u8)pn); 106 (u8)(pn >> 16), (u8)(pn >> 8), (u8)pn);
107 break; 107 break;
108 case WLAN_CIPHER_SUITE_GCMP:
109 case WLAN_CIPHER_SUITE_GCMP_256:
110 pn = atomic64_read(&key->u.gcmp.tx_pn);
111 len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n",
112 (u8)(pn >> 40), (u8)(pn >> 32), (u8)(pn >> 24),
113 (u8)(pn >> 16), (u8)(pn >> 8), (u8)pn);
114 break;
108 default: 115 default:
109 return 0; 116 return 0;
110 } 117 }
@@ -151,6 +158,17 @@ static ssize_t key_rx_spec_read(struct file *file, char __user *userbuf,
151 rpn[3], rpn[4], rpn[5]); 158 rpn[3], rpn[4], rpn[5]);
152 len = p - buf; 159 len = p - buf;
153 break; 160 break;
161 case WLAN_CIPHER_SUITE_GCMP:
162 case WLAN_CIPHER_SUITE_GCMP_256:
163 for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++) {
164 rpn = key->u.gcmp.rx_pn[i];
165 p += scnprintf(p, sizeof(buf)+buf-p,
166 "%02x%02x%02x%02x%02x%02x\n",
167 rpn[0], rpn[1], rpn[2],
168 rpn[3], rpn[4], rpn[5]);
169 }
170 len = p - buf;
171 break;
154 default: 172 default:
155 return 0; 173 return 0;
156 } 174 }
@@ -173,6 +191,10 @@ static ssize_t key_replays_read(struct file *file, char __user *userbuf,
173 len = scnprintf(buf, sizeof(buf), "%u\n", 191 len = scnprintf(buf, sizeof(buf), "%u\n",
174 key->u.aes_cmac.replays); 192 key->u.aes_cmac.replays);
175 break; 193 break;
194 case WLAN_CIPHER_SUITE_GCMP:
195 case WLAN_CIPHER_SUITE_GCMP_256:
196 len = scnprintf(buf, sizeof(buf), "%u\n", key->u.gcmp.replays);
197 break;
176 default: 198 default:
177 return 0; 199 return 0;
178 } 200 }
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index 5167c53aa15f..cbee2f5180ce 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -24,6 +24,7 @@
24#include "debugfs_key.h" 24#include "debugfs_key.h"
25#include "aes_ccm.h" 25#include "aes_ccm.h"
26#include "aes_cmac.h" 26#include "aes_cmac.h"
27#include "aes_gcm.h"
27 28
28 29
29/** 30/**
@@ -163,6 +164,8 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
163 case WLAN_CIPHER_SUITE_TKIP: 164 case WLAN_CIPHER_SUITE_TKIP:
164 case WLAN_CIPHER_SUITE_CCMP: 165 case WLAN_CIPHER_SUITE_CCMP:
165 case WLAN_CIPHER_SUITE_AES_CMAC: 166 case WLAN_CIPHER_SUITE_AES_CMAC:
167 case WLAN_CIPHER_SUITE_GCMP:
168 case WLAN_CIPHER_SUITE_GCMP_256:
166 /* all of these we can do in software - if driver can */ 169 /* all of these we can do in software - if driver can */
167 if (ret == 1) 170 if (ret == 1)
168 return 0; 171 return 0;
@@ -412,6 +415,25 @@ ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
412 return ERR_PTR(err); 415 return ERR_PTR(err);
413 } 416 }
414 break; 417 break;
418 case WLAN_CIPHER_SUITE_GCMP:
419 case WLAN_CIPHER_SUITE_GCMP_256:
420 key->conf.iv_len = IEEE80211_GCMP_HDR_LEN;
421 key->conf.icv_len = IEEE80211_GCMP_MIC_LEN;
422 for (i = 0; seq && i < IEEE80211_NUM_TIDS + 1; i++)
423 for (j = 0; j < IEEE80211_GCMP_PN_LEN; j++)
424 key->u.gcmp.rx_pn[i][j] =
425 seq[IEEE80211_GCMP_PN_LEN - j - 1];
426 /* Initialize AES key state here as an optimization so that
427 * it does not need to be initialized for every packet.
428 */
429 key->u.gcmp.tfm = ieee80211_aes_gcm_key_setup_encrypt(key_data,
430 key_len);
431 if (IS_ERR(key->u.gcmp.tfm)) {
432 err = PTR_ERR(key->u.gcmp.tfm);
433 kfree(key);
434 return ERR_PTR(err);
435 }
436 break;
415 default: 437 default:
416 if (cs) { 438 if (cs) {
417 size_t len = (seq_len > MAX_PN_LEN) ? 439 size_t len = (seq_len > MAX_PN_LEN) ?
@@ -433,10 +455,18 @@ ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
433 455
434static void ieee80211_key_free_common(struct ieee80211_key *key) 456static void ieee80211_key_free_common(struct ieee80211_key *key)
435{ 457{
436 if (key->conf.cipher == WLAN_CIPHER_SUITE_CCMP) 458 switch (key->conf.cipher) {
459 case WLAN_CIPHER_SUITE_CCMP:
437 ieee80211_aes_key_free(key->u.ccmp.tfm); 460 ieee80211_aes_key_free(key->u.ccmp.tfm);
438 if (key->conf.cipher == WLAN_CIPHER_SUITE_AES_CMAC) 461 break;
462 case WLAN_CIPHER_SUITE_AES_CMAC:
439 ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm); 463 ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm);
464 break;
465 case WLAN_CIPHER_SUITE_GCMP:
466 case WLAN_CIPHER_SUITE_GCMP_256:
467 ieee80211_aes_gcm_key_free(key->u.gcmp.tfm);
468 break;
469 }
440 kzfree(key); 470 kzfree(key);
441} 471}
442 472
@@ -760,6 +790,16 @@ void ieee80211_get_key_tx_seq(struct ieee80211_key_conf *keyconf,
760 seq->ccmp.pn[1] = pn64 >> 32; 790 seq->ccmp.pn[1] = pn64 >> 32;
761 seq->ccmp.pn[0] = pn64 >> 40; 791 seq->ccmp.pn[0] = pn64 >> 40;
762 break; 792 break;
793 case WLAN_CIPHER_SUITE_GCMP:
794 case WLAN_CIPHER_SUITE_GCMP_256:
795 pn64 = atomic64_read(&key->u.gcmp.tx_pn);
796 seq->gcmp.pn[5] = pn64;
797 seq->gcmp.pn[4] = pn64 >> 8;
798 seq->gcmp.pn[3] = pn64 >> 16;
799 seq->gcmp.pn[2] = pn64 >> 24;
800 seq->gcmp.pn[1] = pn64 >> 32;
801 seq->gcmp.pn[0] = pn64 >> 40;
802 break;
763 default: 803 default:
764 WARN_ON(1); 804 WARN_ON(1);
765 } 805 }
@@ -796,6 +836,16 @@ void ieee80211_get_key_rx_seq(struct ieee80211_key_conf *keyconf,
796 pn = key->u.aes_cmac.rx_pn; 836 pn = key->u.aes_cmac.rx_pn;
797 memcpy(seq->aes_cmac.pn, pn, IEEE80211_CMAC_PN_LEN); 837 memcpy(seq->aes_cmac.pn, pn, IEEE80211_CMAC_PN_LEN);
798 break; 838 break;
839 case WLAN_CIPHER_SUITE_GCMP:
840 case WLAN_CIPHER_SUITE_GCMP_256:
841 if (WARN_ON(tid < -1 || tid >= IEEE80211_NUM_TIDS))
842 return;
843 if (tid < 0)
844 pn = key->u.gcmp.rx_pn[IEEE80211_NUM_TIDS];
845 else
846 pn = key->u.gcmp.rx_pn[tid];
847 memcpy(seq->gcmp.pn, pn, IEEE80211_GCMP_PN_LEN);
848 break;
799 } 849 }
800} 850}
801EXPORT_SYMBOL(ieee80211_get_key_rx_seq); 851EXPORT_SYMBOL(ieee80211_get_key_rx_seq);
@@ -831,6 +881,16 @@ void ieee80211_set_key_tx_seq(struct ieee80211_key_conf *keyconf,
831 ((u64)seq->aes_cmac.pn[0] << 40); 881 ((u64)seq->aes_cmac.pn[0] << 40);
832 atomic64_set(&key->u.aes_cmac.tx_pn, pn64); 882 atomic64_set(&key->u.aes_cmac.tx_pn, pn64);
833 break; 883 break;
884 case WLAN_CIPHER_SUITE_GCMP:
885 case WLAN_CIPHER_SUITE_GCMP_256:
886 pn64 = (u64)seq->gcmp.pn[5] |
887 ((u64)seq->gcmp.pn[4] << 8) |
888 ((u64)seq->gcmp.pn[3] << 16) |
889 ((u64)seq->gcmp.pn[2] << 24) |
890 ((u64)seq->gcmp.pn[1] << 32) |
891 ((u64)seq->gcmp.pn[0] << 40);
892 atomic64_set(&key->u.gcmp.tx_pn, pn64);
893 break;
834 default: 894 default:
835 WARN_ON(1); 895 WARN_ON(1);
836 break; 896 break;
@@ -868,6 +928,16 @@ void ieee80211_set_key_rx_seq(struct ieee80211_key_conf *keyconf,
868 pn = key->u.aes_cmac.rx_pn; 928 pn = key->u.aes_cmac.rx_pn;
869 memcpy(pn, seq->aes_cmac.pn, IEEE80211_CMAC_PN_LEN); 929 memcpy(pn, seq->aes_cmac.pn, IEEE80211_CMAC_PN_LEN);
870 break; 930 break;
931 case WLAN_CIPHER_SUITE_GCMP:
932 case WLAN_CIPHER_SUITE_GCMP_256:
933 if (WARN_ON(tid < -1 || tid >= IEEE80211_NUM_TIDS))
934 return;
935 if (tid < 0)
936 pn = key->u.gcmp.rx_pn[IEEE80211_NUM_TIDS];
937 else
938 pn = key->u.gcmp.rx_pn[tid];
939 memcpy(pn, seq->gcmp.pn, IEEE80211_GCMP_PN_LEN);
940 break;
871 default: 941 default:
872 WARN_ON(1); 942 WARN_ON(1);
873 break; 943 break;
diff --git a/net/mac80211/key.h b/net/mac80211/key.h
index 19db68663d75..27580da851c8 100644
--- a/net/mac80211/key.h
+++ b/net/mac80211/key.h
@@ -95,6 +95,17 @@ struct ieee80211_key {
95 u32 icverrors; /* dot11RSNAStatsCMACICVErrors */ 95 u32 icverrors; /* dot11RSNAStatsCMACICVErrors */
96 } aes_cmac; 96 } aes_cmac;
97 struct { 97 struct {
98 atomic64_t tx_pn;
99 /* Last received packet number. The first
100 * IEEE80211_NUM_TIDS counters are used with Data
101 * frames and the last counter is used with Robust
102 * Management frames.
103 */
104 u8 rx_pn[IEEE80211_NUM_TIDS + 1][IEEE80211_GCMP_PN_LEN];
105 struct crypto_aead *tfm;
106 u32 replays; /* dot11RSNAStatsGCMPReplays */
107 } gcmp;
108 struct {
98 /* generic cipher scheme */ 109 /* generic cipher scheme */
99 u8 rx_pn[IEEE80211_NUM_TIDS + 1][MAX_PN_LEN]; 110 u8 rx_pn[IEEE80211_NUM_TIDS + 1][MAX_PN_LEN];
100 } gen; 111 } gen;
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index ea6b82ac4f0b..7223b4e16752 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -666,6 +666,8 @@ 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_GCMP,
670 WLAN_CIPHER_SUITE_GCMP_256,
669 671
670 /* keep last -- depends on hw flags! */ 672 /* keep last -- depends on hw flags! */
671 WLAN_CIPHER_SUITE_AES_CMAC 673 WLAN_CIPHER_SUITE_AES_CMAC
@@ -724,9 +726,10 @@ static int ieee80211_init_cipher_suites(struct ieee80211_local *local)
724 /* Driver specifies cipher schemes only (but not cipher suites 726 /* Driver specifies cipher schemes only (but not cipher suites
725 * including the schemes) 727 * including the schemes)
726 * 728 *
727 * We start counting ciphers defined by schemes, TKIP and CCMP 729 * We start counting ciphers defined by schemes, TKIP, CCMP,
730 * GCMP, and GCMP-256
728 */ 731 */
729 n_suites = local->hw.n_cipher_schemes + 2; 732 n_suites = local->hw.n_cipher_schemes + 4;
730 733
731 /* check if we have WEP40 and WEP104 */ 734 /* check if we have WEP40 and WEP104 */
732 if (have_wep) 735 if (have_wep)
@@ -742,6 +745,8 @@ static int ieee80211_init_cipher_suites(struct ieee80211_local *local)
742 745
743 suites[w++] = WLAN_CIPHER_SUITE_CCMP; 746 suites[w++] = WLAN_CIPHER_SUITE_CCMP;
744 suites[w++] = WLAN_CIPHER_SUITE_TKIP; 747 suites[w++] = WLAN_CIPHER_SUITE_TKIP;
748 suites[w++] = WLAN_CIPHER_SUITE_GCMP;
749 suites[w++] = WLAN_CIPHER_SUITE_GCMP_256;
745 750
746 if (have_wep) { 751 if (have_wep) {
747 suites[w++] = WLAN_CIPHER_SUITE_WEP40; 752 suites[w++] = WLAN_CIPHER_SUITE_WEP40;
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index ed516ae80a3b..a11d2518c365 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1655,6 +1655,10 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
1655 case WLAN_CIPHER_SUITE_AES_CMAC: 1655 case WLAN_CIPHER_SUITE_AES_CMAC:
1656 result = ieee80211_crypto_aes_cmac_decrypt(rx); 1656 result = ieee80211_crypto_aes_cmac_decrypt(rx);
1657 break; 1657 break;
1658 case WLAN_CIPHER_SUITE_GCMP:
1659 case WLAN_CIPHER_SUITE_GCMP_256:
1660 result = ieee80211_crypto_gcmp_decrypt(rx);
1661 break;
1658 default: 1662 default:
1659 result = ieee80211_crypto_hw_decrypt(rx); 1663 result = ieee80211_crypto_hw_decrypt(rx);
1660 } 1664 }
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 02ed6f60629a..e4c6fbc4bf7a 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -626,6 +626,8 @@ 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_GCMP:
630 case WLAN_CIPHER_SUITE_GCMP_256:
629 if (!ieee80211_is_data_present(hdr->frame_control) && 631 if (!ieee80211_is_data_present(hdr->frame_control) &&
630 !ieee80211_use_mfp(hdr->frame_control, tx->sta, 632 !ieee80211_use_mfp(hdr->frame_control, tx->sta,
631 tx->skb)) 633 tx->skb))
@@ -1014,6 +1016,9 @@ ieee80211_tx_h_encrypt(struct ieee80211_tx_data *tx)
1014 return ieee80211_crypto_ccmp_encrypt(tx); 1016 return ieee80211_crypto_ccmp_encrypt(tx);
1015 case WLAN_CIPHER_SUITE_AES_CMAC: 1017 case WLAN_CIPHER_SUITE_AES_CMAC:
1016 return ieee80211_crypto_aes_cmac_encrypt(tx); 1018 return ieee80211_crypto_aes_cmac_encrypt(tx);
1019 case WLAN_CIPHER_SUITE_GCMP:
1020 case WLAN_CIPHER_SUITE_GCMP_256:
1021 return ieee80211_crypto_gcmp_encrypt(tx);
1017 default: 1022 default:
1018 return ieee80211_crypto_hw_encrypt(tx); 1023 return ieee80211_crypto_hw_encrypt(tx);
1019 } 1024 }
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c
index 12398fde02e8..96b65c240109 100644
--- a/net/mac80211/wpa.c
+++ b/net/mac80211/wpa.c
@@ -22,6 +22,7 @@
22#include "tkip.h" 22#include "tkip.h"
23#include "aes_ccm.h" 23#include "aes_ccm.h"
24#include "aes_cmac.h" 24#include "aes_cmac.h"
25#include "aes_gcm.h"
25#include "wpa.h" 26#include "wpa.h"
26 27
27ieee80211_tx_result 28ieee80211_tx_result
@@ -546,6 +547,229 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx)
546 return RX_CONTINUE; 547 return RX_CONTINUE;
547} 548}
548 549
550static void gcmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *j_0, u8 *aad)
551{
552 __le16 mask_fc;
553 u8 qos_tid;
554 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
555
556 memcpy(j_0, hdr->addr2, ETH_ALEN);
557 memcpy(&j_0[ETH_ALEN], pn, IEEE80211_GCMP_PN_LEN);
558 j_0[13] = 0;
559 j_0[14] = 0;
560 j_0[AES_BLOCK_SIZE - 1] = 0x01;
561
562 /* AAD (extra authenticate-only data) / masked 802.11 header
563 * FC | A1 | A2 | A3 | SC | [A4] | [QC]
564 */
565 put_unaligned_be16(ieee80211_hdrlen(hdr->frame_control) - 2, &aad[0]);
566 /* Mask FC: zero subtype b4 b5 b6 (if not mgmt)
567 * Retry, PwrMgt, MoreData; set Protected
568 */
569 mask_fc = hdr->frame_control;
570 mask_fc &= ~cpu_to_le16(IEEE80211_FCTL_RETRY |
571 IEEE80211_FCTL_PM | IEEE80211_FCTL_MOREDATA);
572 if (!ieee80211_is_mgmt(hdr->frame_control))
573 mask_fc &= ~cpu_to_le16(0x0070);
574 mask_fc |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
575
576 put_unaligned(mask_fc, (__le16 *)&aad[2]);
577 memcpy(&aad[4], &hdr->addr1, 3 * ETH_ALEN);
578
579 /* Mask Seq#, leave Frag# */
580 aad[22] = *((u8 *)&hdr->seq_ctrl) & 0x0f;
581 aad[23] = 0;
582
583 if (ieee80211_is_data_qos(hdr->frame_control))
584 qos_tid = *ieee80211_get_qos_ctl(hdr) &
585 IEEE80211_QOS_CTL_TID_MASK;
586 else
587 qos_tid = 0;
588
589 if (ieee80211_has_a4(hdr->frame_control)) {
590 memcpy(&aad[24], hdr->addr4, ETH_ALEN);
591 aad[30] = qos_tid;
592 aad[31] = 0;
593 } else {
594 memset(&aad[24], 0, ETH_ALEN + IEEE80211_QOS_CTL_LEN);
595 aad[24] = qos_tid;
596 }
597}
598
599static inline void gcmp_pn2hdr(u8 *hdr, const u8 *pn, int key_id)
600{
601 hdr[0] = pn[5];
602 hdr[1] = pn[4];
603 hdr[2] = 0;
604 hdr[3] = 0x20 | (key_id << 6);
605 hdr[4] = pn[3];
606 hdr[5] = pn[2];
607 hdr[6] = pn[1];
608 hdr[7] = pn[0];
609}
610
611static inline void gcmp_hdr2pn(u8 *pn, const u8 *hdr)
612{
613 pn[0] = hdr[7];
614 pn[1] = hdr[6];
615 pn[2] = hdr[5];
616 pn[3] = hdr[4];
617 pn[4] = hdr[1];
618 pn[5] = hdr[0];
619}
620
621static int gcmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
622{
623 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
624 struct ieee80211_key *key = tx->key;
625 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
626 int hdrlen, len, tail;
627 u8 *pos;
628 u8 pn[6];
629 u64 pn64;
630 u8 aad[2 * AES_BLOCK_SIZE];
631 u8 j_0[AES_BLOCK_SIZE];
632
633 if (info->control.hw_key &&
634 !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV) &&
635 !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE) &&
636 !((info->control.hw_key->flags &
637 IEEE80211_KEY_FLAG_GENERATE_IV_MGMT) &&
638 ieee80211_is_mgmt(hdr->frame_control))) {
639 /* hwaccel has no need for preallocated room for GCMP
640 * header or MIC fields
641 */
642 return 0;
643 }
644
645 hdrlen = ieee80211_hdrlen(hdr->frame_control);
646 len = skb->len - hdrlen;
647
648 if (info->control.hw_key)
649 tail = 0;
650 else
651 tail = IEEE80211_GCMP_MIC_LEN;
652
653 if (WARN_ON(skb_tailroom(skb) < tail ||
654 skb_headroom(skb) < IEEE80211_GCMP_HDR_LEN))
655 return -1;
656
657 pos = skb_push(skb, IEEE80211_GCMP_HDR_LEN);
658 memmove(pos, pos + IEEE80211_GCMP_HDR_LEN, hdrlen);
659 skb_set_network_header(skb, skb_network_offset(skb) +
660 IEEE80211_GCMP_HDR_LEN);
661
662 /* the HW only needs room for the IV, but not the actual IV */
663 if (info->control.hw_key &&
664 (info->control.hw_key->flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE))
665 return 0;
666
667 hdr = (struct ieee80211_hdr *)pos;
668 pos += hdrlen;
669
670 pn64 = atomic64_inc_return(&key->u.gcmp.tx_pn);
671
672 pn[5] = pn64;
673 pn[4] = pn64 >> 8;
674 pn[3] = pn64 >> 16;
675 pn[2] = pn64 >> 24;
676 pn[1] = pn64 >> 32;
677 pn[0] = pn64 >> 40;
678
679 gcmp_pn2hdr(pos, pn, key->conf.keyidx);
680
681 /* hwaccel - with software GCMP header */
682 if (info->control.hw_key)
683 return 0;
684
685 pos += IEEE80211_GCMP_HDR_LEN;
686 gcmp_special_blocks(skb, pn, j_0, aad);
687 ieee80211_aes_gcm_encrypt(key->u.gcmp.tfm, j_0, aad, pos, len,
688 skb_put(skb, IEEE80211_GCMP_MIC_LEN));
689
690 return 0;
691}
692
693ieee80211_tx_result
694ieee80211_crypto_gcmp_encrypt(struct ieee80211_tx_data *tx)
695{
696 struct sk_buff *skb;
697
698 ieee80211_tx_set_protected(tx);
699
700 skb_queue_walk(&tx->skbs, skb) {
701 if (gcmp_encrypt_skb(tx, skb) < 0)
702 return TX_DROP;
703 }
704
705 return TX_CONTINUE;
706}
707
708ieee80211_rx_result
709ieee80211_crypto_gcmp_decrypt(struct ieee80211_rx_data *rx)
710{
711 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
712 int hdrlen;
713 struct ieee80211_key *key = rx->key;
714 struct sk_buff *skb = rx->skb;
715 struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
716 u8 pn[IEEE80211_GCMP_PN_LEN];
717 int data_len;
718 int queue;
719
720 hdrlen = ieee80211_hdrlen(hdr->frame_control);
721
722 if (!ieee80211_is_data(hdr->frame_control) &&
723 !ieee80211_is_robust_mgmt_frame(skb))
724 return RX_CONTINUE;
725
726 data_len = skb->len - hdrlen - IEEE80211_GCMP_HDR_LEN -
727 IEEE80211_GCMP_MIC_LEN;
728 if (!rx->sta || data_len < 0)
729 return RX_DROP_UNUSABLE;
730
731 if (status->flag & RX_FLAG_DECRYPTED) {
732 if (!pskb_may_pull(rx->skb, hdrlen + IEEE80211_GCMP_HDR_LEN))
733 return RX_DROP_UNUSABLE;
734 } else {
735 if (skb_linearize(rx->skb))
736 return RX_DROP_UNUSABLE;
737 }
738
739 gcmp_hdr2pn(pn, skb->data + hdrlen);
740
741 queue = rx->security_idx;
742
743 if (memcmp(pn, key->u.gcmp.rx_pn[queue], IEEE80211_GCMP_PN_LEN) <= 0) {
744 key->u.gcmp.replays++;
745 return RX_DROP_UNUSABLE;
746 }
747
748 if (!(status->flag & RX_FLAG_DECRYPTED)) {
749 u8 aad[2 * AES_BLOCK_SIZE];
750 u8 j_0[AES_BLOCK_SIZE];
751 /* hardware didn't decrypt/verify MIC */
752 gcmp_special_blocks(skb, pn, j_0, aad);
753
754 if (ieee80211_aes_gcm_decrypt(
755 key->u.gcmp.tfm, j_0, aad,
756 skb->data + hdrlen + IEEE80211_GCMP_HDR_LEN,
757 data_len,
758 skb->data + skb->len - IEEE80211_GCMP_MIC_LEN))
759 return RX_DROP_UNUSABLE;
760 }
761
762 memcpy(key->u.gcmp.rx_pn[queue], pn, IEEE80211_GCMP_PN_LEN);
763
764 /* Remove GCMP header and MIC */
765 if (pskb_trim(skb, skb->len - IEEE80211_GCMP_MIC_LEN))
766 return RX_DROP_UNUSABLE;
767 memmove(skb->data + IEEE80211_GCMP_HDR_LEN, skb->data, hdrlen);
768 skb_pull(skb, IEEE80211_GCMP_HDR_LEN);
769
770 return RX_CONTINUE;
771}
772
549static ieee80211_tx_result 773static ieee80211_tx_result
550ieee80211_crypto_cs_encrypt(struct ieee80211_tx_data *tx, 774ieee80211_crypto_cs_encrypt(struct ieee80211_tx_data *tx,
551 struct sk_buff *skb) 775 struct sk_buff *skb)
diff --git a/net/mac80211/wpa.h b/net/mac80211/wpa.h
index 62e5a12dfe0a..ea955f278351 100644
--- a/net/mac80211/wpa.h
+++ b/net/mac80211/wpa.h
@@ -37,4 +37,9 @@ ieee80211_crypto_hw_encrypt(struct ieee80211_tx_data *tx);
37ieee80211_rx_result 37ieee80211_rx_result
38ieee80211_crypto_hw_decrypt(struct ieee80211_rx_data *rx); 38ieee80211_crypto_hw_decrypt(struct ieee80211_rx_data *rx);
39 39
40ieee80211_tx_result
41ieee80211_crypto_gcmp_encrypt(struct ieee80211_tx_data *tx);
42ieee80211_rx_result
43ieee80211_crypto_gcmp_decrypt(struct ieee80211_rx_data *rx);
44
40#endif /* WPA_H */ 45#endif /* WPA_H */