summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJouni Malinen <jouni@qca.qualcomm.com>2015-01-24 12:52:09 -0500
committerJohannes Berg <johannes.berg@intel.com>2015-01-27 05:10:13 -0500
commit8ade538bf39b1ee53418528fdacd36b8e65621b9 (patch)
treef7bd85219ee6946b493252effe9a39918b309fb4 /net
parent56c52da2d554f081e8fce58ecbcf6a40c605b95b (diff)
mac80111: Add BIP-GMAC-128 and BIP-GMAC-256 ciphers
This allows mac80211 to configure BIP-GMAC-128 and BIP-GMAC-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> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/Makefile1
-rw-r--r--net/mac80211/aes_gmac.c84
-rw-r--r--net/mac80211/aes_gmac.h20
-rw-r--r--net/mac80211/cfg.c14
-rw-r--r--net/mac80211/debugfs_key.c26
-rw-r--r--net/mac80211/key.c60
-rw-r--r--net/mac80211/key.h7
-rw-r--r--net/mac80211/main.c12
-rw-r--r--net/mac80211/rx.c4
-rw-r--r--net/mac80211/tx.c5
-rw-r--r--net/mac80211/wpa.c105
-rw-r--r--net/mac80211/wpa.h4
12 files changed, 339 insertions, 3 deletions
diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile
index 0cbf93618433..3275f01881be 100644
--- a/net/mac80211/Makefile
+++ b/net/mac80211/Makefile
@@ -17,6 +17,7 @@ mac80211-y := \
17 aes_ccm.o \ 17 aes_ccm.o \
18 aes_gcm.o \ 18 aes_gcm.o \
19 aes_cmac.o \ 19 aes_cmac.o \
20 aes_gmac.o \
20 cfg.o \ 21 cfg.o \
21 ethtool.o \ 22 ethtool.o \
22 rx.o \ 23 rx.o \
diff --git a/net/mac80211/aes_gmac.c b/net/mac80211/aes_gmac.c
new file mode 100644
index 000000000000..1c72edcb0083
--- /dev/null
+++ b/net/mac80211/aes_gmac.c
@@ -0,0 +1,84 @@
1/*
2 * AES-GMAC for IEEE 802.11 BIP-GMAC-128 and BIP-GMAC-256
3 * Copyright 2015, Qualcomm Atheros, Inc.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 */
9
10#include <linux/kernel.h>
11#include <linux/types.h>
12#include <linux/crypto.h>
13#include <linux/err.h>
14#include <crypto/aes.h>
15
16#include <net/mac80211.h>
17#include "key.h"
18#include "aes_gmac.h"
19
20#define GMAC_MIC_LEN 16
21#define GMAC_NONCE_LEN 12
22#define AAD_LEN 20
23
24int ieee80211_aes_gmac(struct crypto_aead *tfm, const u8 *aad, u8 *nonce,
25 const u8 *data, size_t data_len, u8 *mic)
26{
27 struct scatterlist sg[3], ct[1];
28 char aead_req_data[sizeof(struct aead_request) +
29 crypto_aead_reqsize(tfm)]
30 __aligned(__alignof__(struct aead_request));
31 struct aead_request *aead_req = (void *)aead_req_data;
32 u8 zero[GMAC_MIC_LEN], iv[AES_BLOCK_SIZE];
33
34 if (data_len < GMAC_MIC_LEN)
35 return -EINVAL;
36
37 memset(aead_req, 0, sizeof(aead_req_data));
38
39 memset(zero, 0, GMAC_MIC_LEN);
40 sg_init_table(sg, 3);
41 sg_set_buf(&sg[0], aad, AAD_LEN);
42 sg_set_buf(&sg[1], data, data_len - GMAC_MIC_LEN);
43 sg_set_buf(&sg[2], zero, GMAC_MIC_LEN);
44
45 memcpy(iv, nonce, GMAC_NONCE_LEN);
46 memset(iv + GMAC_NONCE_LEN, 0, sizeof(iv) - GMAC_NONCE_LEN);
47 iv[AES_BLOCK_SIZE - 1] = 0x01;
48
49 sg_init_table(ct, 1);
50 sg_set_buf(&ct[0], mic, GMAC_MIC_LEN);
51
52 aead_request_set_tfm(aead_req, tfm);
53 aead_request_set_assoc(aead_req, sg, AAD_LEN + data_len);
54 aead_request_set_crypt(aead_req, NULL, ct, 0, iv);
55
56 crypto_aead_encrypt(aead_req);
57
58 return 0;
59}
60
61struct crypto_aead *ieee80211_aes_gmac_key_setup(const u8 key[],
62 size_t key_len)
63{
64 struct crypto_aead *tfm;
65 int err;
66
67 tfm = crypto_alloc_aead("gcm(aes)", 0, CRYPTO_ALG_ASYNC);
68 if (IS_ERR(tfm))
69 return tfm;
70
71 err = crypto_aead_setkey(tfm, key, key_len);
72 if (!err)
73 return tfm;
74 if (!err)
75 err = crypto_aead_setauthsize(tfm, GMAC_MIC_LEN);
76
77 crypto_free_aead(tfm);
78 return ERR_PTR(err);
79}
80
81void ieee80211_aes_gmac_key_free(struct crypto_aead *tfm)
82{
83 crypto_free_aead(tfm);
84}
diff --git a/net/mac80211/aes_gmac.h b/net/mac80211/aes_gmac.h
new file mode 100644
index 000000000000..d328204d73a8
--- /dev/null
+++ b/net/mac80211/aes_gmac.h
@@ -0,0 +1,20 @@
1/*
2 * Copyright 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_GMAC_H
10#define AES_GMAC_H
11
12#include <linux/crypto.h>
13
14struct crypto_aead *ieee80211_aes_gmac_key_setup(const u8 key[],
15 size_t key_len);
16int ieee80211_aes_gmac(struct crypto_aead *tfm, const u8 *aad, u8 *nonce,
17 const u8 *data, size_t data_len, u8 *mic);
18void ieee80211_aes_gmac_key_free(struct crypto_aead *tfm);
19
20#endif /* AES_GMAC_H */
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index b7e528bbecce..dd4ff36c557a 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -165,6 +165,8 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
165 case WLAN_CIPHER_SUITE_CCMP_256: 165 case WLAN_CIPHER_SUITE_CCMP_256:
166 case WLAN_CIPHER_SUITE_AES_CMAC: 166 case WLAN_CIPHER_SUITE_AES_CMAC:
167 case WLAN_CIPHER_SUITE_BIP_CMAC_256: 167 case WLAN_CIPHER_SUITE_BIP_CMAC_256:
168 case WLAN_CIPHER_SUITE_BIP_GMAC_128:
169 case WLAN_CIPHER_SUITE_BIP_GMAC_256:
168 case WLAN_CIPHER_SUITE_GCMP: 170 case WLAN_CIPHER_SUITE_GCMP:
169 case WLAN_CIPHER_SUITE_GCMP_256: 171 case WLAN_CIPHER_SUITE_GCMP_256:
170 break; 172 break;
@@ -374,6 +376,18 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
374 params.seq = seq; 376 params.seq = seq;
375 params.seq_len = 6; 377 params.seq_len = 6;
376 break; 378 break;
379 case WLAN_CIPHER_SUITE_BIP_GMAC_128:
380 case WLAN_CIPHER_SUITE_BIP_GMAC_256:
381 pn64 = atomic64_read(&key->u.aes_gmac.tx_pn);
382 seq[0] = pn64;
383 seq[1] = pn64 >> 8;
384 seq[2] = pn64 >> 16;
385 seq[3] = pn64 >> 24;
386 seq[4] = pn64 >> 32;
387 seq[5] = pn64 >> 40;
388 params.seq = seq;
389 params.seq_len = 6;
390 break;
377 case WLAN_CIPHER_SUITE_GCMP: 391 case WLAN_CIPHER_SUITE_GCMP:
378 case WLAN_CIPHER_SUITE_GCMP_256: 392 case WLAN_CIPHER_SUITE_GCMP_256:
379 pn64 = atomic64_read(&key->u.gcmp.tx_pn); 393 pn64 = atomic64_read(&key->u.gcmp.tx_pn);
diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c
index d1b60eb014a8..71ac1b5f4da5 100644
--- a/net/mac80211/debugfs_key.c
+++ b/net/mac80211/debugfs_key.c
@@ -107,6 +107,13 @@ static ssize_t key_tx_spec_read(struct file *file, char __user *userbuf,
107 (u8)(pn >> 40), (u8)(pn >> 32), (u8)(pn >> 24), 107 (u8)(pn >> 40), (u8)(pn >> 32), (u8)(pn >> 24),
108 (u8)(pn >> 16), (u8)(pn >> 8), (u8)pn); 108 (u8)(pn >> 16), (u8)(pn >> 8), (u8)pn);
109 break; 109 break;
110 case WLAN_CIPHER_SUITE_BIP_GMAC_128:
111 case WLAN_CIPHER_SUITE_BIP_GMAC_256:
112 pn = atomic64_read(&key->u.aes_gmac.tx_pn);
113 len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n",
114 (u8)(pn >> 40), (u8)(pn >> 32), (u8)(pn >> 24),
115 (u8)(pn >> 16), (u8)(pn >> 8), (u8)pn);
116 break;
110 case WLAN_CIPHER_SUITE_GCMP: 117 case WLAN_CIPHER_SUITE_GCMP:
111 case WLAN_CIPHER_SUITE_GCMP_256: 118 case WLAN_CIPHER_SUITE_GCMP_256:
112 pn = atomic64_read(&key->u.gcmp.tx_pn); 119 pn = atomic64_read(&key->u.gcmp.tx_pn);
@@ -162,6 +169,15 @@ static ssize_t key_rx_spec_read(struct file *file, char __user *userbuf,
162 rpn[3], rpn[4], rpn[5]); 169 rpn[3], rpn[4], rpn[5]);
163 len = p - buf; 170 len = p - buf;
164 break; 171 break;
172 case WLAN_CIPHER_SUITE_BIP_GMAC_128:
173 case WLAN_CIPHER_SUITE_BIP_GMAC_256:
174 rpn = key->u.aes_gmac.rx_pn;
175 p += scnprintf(p, sizeof(buf)+buf-p,
176 "%02x%02x%02x%02x%02x%02x\n",
177 rpn[0], rpn[1], rpn[2],
178 rpn[3], rpn[4], rpn[5]);
179 len = p - buf;
180 break;
165 case WLAN_CIPHER_SUITE_GCMP: 181 case WLAN_CIPHER_SUITE_GCMP:
166 case WLAN_CIPHER_SUITE_GCMP_256: 182 case WLAN_CIPHER_SUITE_GCMP_256:
167 for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++) { 183 for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++) {
@@ -197,6 +213,11 @@ static ssize_t key_replays_read(struct file *file, char __user *userbuf,
197 len = scnprintf(buf, sizeof(buf), "%u\n", 213 len = scnprintf(buf, sizeof(buf), "%u\n",
198 key->u.aes_cmac.replays); 214 key->u.aes_cmac.replays);
199 break; 215 break;
216 case WLAN_CIPHER_SUITE_BIP_GMAC_128:
217 case WLAN_CIPHER_SUITE_BIP_GMAC_256:
218 len = scnprintf(buf, sizeof(buf), "%u\n",
219 key->u.aes_gmac.replays);
220 break;
200 case WLAN_CIPHER_SUITE_GCMP: 221 case WLAN_CIPHER_SUITE_GCMP:
201 case WLAN_CIPHER_SUITE_GCMP_256: 222 case WLAN_CIPHER_SUITE_GCMP_256:
202 len = scnprintf(buf, sizeof(buf), "%u\n", key->u.gcmp.replays); 223 len = scnprintf(buf, sizeof(buf), "%u\n", key->u.gcmp.replays);
@@ -221,6 +242,11 @@ static ssize_t key_icverrors_read(struct file *file, char __user *userbuf,
221 len = scnprintf(buf, sizeof(buf), "%u\n", 242 len = scnprintf(buf, sizeof(buf), "%u\n",
222 key->u.aes_cmac.icverrors); 243 key->u.aes_cmac.icverrors);
223 break; 244 break;
245 case WLAN_CIPHER_SUITE_BIP_GMAC_128:
246 case WLAN_CIPHER_SUITE_BIP_GMAC_256:
247 len = scnprintf(buf, sizeof(buf), "%u\n",
248 key->u.aes_gmac.icverrors);
249 break;
224 default: 250 default:
225 return 0; 251 return 0;
226 } 252 }
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index 7ceea9d9fcd2..0825d76edcfc 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_gmac.h"
27#include "aes_gcm.h" 28#include "aes_gcm.h"
28 29
29 30
@@ -166,6 +167,8 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
166 case WLAN_CIPHER_SUITE_CCMP_256: 167 case WLAN_CIPHER_SUITE_CCMP_256:
167 case WLAN_CIPHER_SUITE_AES_CMAC: 168 case WLAN_CIPHER_SUITE_AES_CMAC:
168 case WLAN_CIPHER_SUITE_BIP_CMAC_256: 169 case WLAN_CIPHER_SUITE_BIP_CMAC_256:
170 case WLAN_CIPHER_SUITE_BIP_GMAC_128:
171 case WLAN_CIPHER_SUITE_BIP_GMAC_256:
169 case WLAN_CIPHER_SUITE_GCMP: 172 case WLAN_CIPHER_SUITE_GCMP:
170 case WLAN_CIPHER_SUITE_GCMP_256: 173 case WLAN_CIPHER_SUITE_GCMP_256:
171 /* all of these we can do in software - if driver can */ 174 /* all of these we can do in software - if driver can */
@@ -440,6 +443,25 @@ ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
440 return ERR_PTR(err); 443 return ERR_PTR(err);
441 } 444 }
442 break; 445 break;
446 case WLAN_CIPHER_SUITE_BIP_GMAC_128:
447 case WLAN_CIPHER_SUITE_BIP_GMAC_256:
448 key->conf.iv_len = 0;
449 key->conf.icv_len = sizeof(struct ieee80211_mmie_16);
450 if (seq)
451 for (j = 0; j < IEEE80211_GMAC_PN_LEN; j++)
452 key->u.aes_gmac.rx_pn[j] =
453 seq[IEEE80211_GMAC_PN_LEN - j - 1];
454 /* Initialize AES key state here as an optimization so that
455 * it does not need to be initialized for every packet.
456 */
457 key->u.aes_gmac.tfm =
458 ieee80211_aes_gmac_key_setup(key_data, key_len);
459 if (IS_ERR(key->u.aes_gmac.tfm)) {
460 err = PTR_ERR(key->u.aes_gmac.tfm);
461 kfree(key);
462 return ERR_PTR(err);
463 }
464 break;
443 case WLAN_CIPHER_SUITE_GCMP: 465 case WLAN_CIPHER_SUITE_GCMP:
444 case WLAN_CIPHER_SUITE_GCMP_256: 466 case WLAN_CIPHER_SUITE_GCMP_256:
445 key->conf.iv_len = IEEE80211_GCMP_HDR_LEN; 467 key->conf.iv_len = IEEE80211_GCMP_HDR_LEN;
@@ -489,6 +511,10 @@ static void ieee80211_key_free_common(struct ieee80211_key *key)
489 case WLAN_CIPHER_SUITE_BIP_CMAC_256: 511 case WLAN_CIPHER_SUITE_BIP_CMAC_256:
490 ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm); 512 ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm);
491 break; 513 break;
514 case WLAN_CIPHER_SUITE_BIP_GMAC_128:
515 case WLAN_CIPHER_SUITE_BIP_GMAC_256:
516 ieee80211_aes_gmac_key_free(key->u.aes_gmac.tfm);
517 break;
492 case WLAN_CIPHER_SUITE_GCMP: 518 case WLAN_CIPHER_SUITE_GCMP:
493 case WLAN_CIPHER_SUITE_GCMP_256: 519 case WLAN_CIPHER_SUITE_GCMP_256:
494 ieee80211_aes_gcm_key_free(key->u.gcmp.tfm); 520 ieee80211_aes_gcm_key_free(key->u.gcmp.tfm);
@@ -819,6 +845,16 @@ void ieee80211_get_key_tx_seq(struct ieee80211_key_conf *keyconf,
819 seq->ccmp.pn[1] = pn64 >> 32; 845 seq->ccmp.pn[1] = pn64 >> 32;
820 seq->ccmp.pn[0] = pn64 >> 40; 846 seq->ccmp.pn[0] = pn64 >> 40;
821 break; 847 break;
848 case WLAN_CIPHER_SUITE_BIP_GMAC_128:
849 case WLAN_CIPHER_SUITE_BIP_GMAC_256:
850 pn64 = atomic64_read(&key->u.aes_gmac.tx_pn);
851 seq->ccmp.pn[5] = pn64;
852 seq->ccmp.pn[4] = pn64 >> 8;
853 seq->ccmp.pn[3] = pn64 >> 16;
854 seq->ccmp.pn[2] = pn64 >> 24;
855 seq->ccmp.pn[1] = pn64 >> 32;
856 seq->ccmp.pn[0] = pn64 >> 40;
857 break;
822 case WLAN_CIPHER_SUITE_GCMP: 858 case WLAN_CIPHER_SUITE_GCMP:
823 case WLAN_CIPHER_SUITE_GCMP_256: 859 case WLAN_CIPHER_SUITE_GCMP_256:
824 pn64 = atomic64_read(&key->u.gcmp.tx_pn); 860 pn64 = atomic64_read(&key->u.gcmp.tx_pn);
@@ -867,6 +903,13 @@ void ieee80211_get_key_rx_seq(struct ieee80211_key_conf *keyconf,
867 pn = key->u.aes_cmac.rx_pn; 903 pn = key->u.aes_cmac.rx_pn;
868 memcpy(seq->aes_cmac.pn, pn, IEEE80211_CMAC_PN_LEN); 904 memcpy(seq->aes_cmac.pn, pn, IEEE80211_CMAC_PN_LEN);
869 break; 905 break;
906 case WLAN_CIPHER_SUITE_BIP_GMAC_128:
907 case WLAN_CIPHER_SUITE_BIP_GMAC_256:
908 if (WARN_ON(tid != 0))
909 return;
910 pn = key->u.aes_gmac.rx_pn;
911 memcpy(seq->aes_gmac.pn, pn, IEEE80211_GMAC_PN_LEN);
912 break;
870 case WLAN_CIPHER_SUITE_GCMP: 913 case WLAN_CIPHER_SUITE_GCMP:
871 case WLAN_CIPHER_SUITE_GCMP_256: 914 case WLAN_CIPHER_SUITE_GCMP_256:
872 if (WARN_ON(tid < -1 || tid >= IEEE80211_NUM_TIDS)) 915 if (WARN_ON(tid < -1 || tid >= IEEE80211_NUM_TIDS))
@@ -914,6 +957,16 @@ void ieee80211_set_key_tx_seq(struct ieee80211_key_conf *keyconf,
914 ((u64)seq->aes_cmac.pn[0] << 40); 957 ((u64)seq->aes_cmac.pn[0] << 40);
915 atomic64_set(&key->u.aes_cmac.tx_pn, pn64); 958 atomic64_set(&key->u.aes_cmac.tx_pn, pn64);
916 break; 959 break;
960 case WLAN_CIPHER_SUITE_BIP_GMAC_128:
961 case WLAN_CIPHER_SUITE_BIP_GMAC_256:
962 pn64 = (u64)seq->aes_gmac.pn[5] |
963 ((u64)seq->aes_gmac.pn[4] << 8) |
964 ((u64)seq->aes_gmac.pn[3] << 16) |
965 ((u64)seq->aes_gmac.pn[2] << 24) |
966 ((u64)seq->aes_gmac.pn[1] << 32) |
967 ((u64)seq->aes_gmac.pn[0] << 40);
968 atomic64_set(&key->u.aes_gmac.tx_pn, pn64);
969 break;
917 case WLAN_CIPHER_SUITE_GCMP: 970 case WLAN_CIPHER_SUITE_GCMP:
918 case WLAN_CIPHER_SUITE_GCMP_256: 971 case WLAN_CIPHER_SUITE_GCMP_256:
919 pn64 = (u64)seq->gcmp.pn[5] | 972 pn64 = (u64)seq->gcmp.pn[5] |
@@ -963,6 +1016,13 @@ void ieee80211_set_key_rx_seq(struct ieee80211_key_conf *keyconf,
963 pn = key->u.aes_cmac.rx_pn; 1016 pn = key->u.aes_cmac.rx_pn;
964 memcpy(pn, seq->aes_cmac.pn, IEEE80211_CMAC_PN_LEN); 1017 memcpy(pn, seq->aes_cmac.pn, IEEE80211_CMAC_PN_LEN);
965 break; 1018 break;
1019 case WLAN_CIPHER_SUITE_BIP_GMAC_128:
1020 case WLAN_CIPHER_SUITE_BIP_GMAC_256:
1021 if (WARN_ON(tid != 0))
1022 return;
1023 pn = key->u.aes_gmac.rx_pn;
1024 memcpy(pn, seq->aes_gmac.pn, IEEE80211_GMAC_PN_LEN);
1025 break;
966 case WLAN_CIPHER_SUITE_GCMP: 1026 case WLAN_CIPHER_SUITE_GCMP:
967 case WLAN_CIPHER_SUITE_GCMP_256: 1027 case WLAN_CIPHER_SUITE_GCMP_256:
968 if (WARN_ON(tid < -1 || tid >= IEEE80211_NUM_TIDS)) 1028 if (WARN_ON(tid < -1 || tid >= IEEE80211_NUM_TIDS))
diff --git a/net/mac80211/key.h b/net/mac80211/key.h
index 27580da851c8..d57a9915494f 100644
--- a/net/mac80211/key.h
+++ b/net/mac80211/key.h
@@ -96,6 +96,13 @@ struct ieee80211_key {
96 } aes_cmac; 96 } aes_cmac;
97 struct { 97 struct {
98 atomic64_t tx_pn; 98 atomic64_t tx_pn;
99 u8 rx_pn[IEEE80211_GMAC_PN_LEN];
100 struct crypto_aead *tfm;
101 u32 replays; /* dot11RSNAStatsCMACReplays */
102 u32 icverrors; /* dot11RSNAStatsCMACICVErrors */
103 } aes_gmac;
104 struct {
105 atomic64_t tx_pn;
99 /* Last received packet number. The first 106 /* Last received packet number. The first
100 * IEEE80211_NUM_TIDS counters are used with Data 107 * IEEE80211_NUM_TIDS counters are used with Data
101 * frames and the last counter is used with Robust 108 * frames and the last counter is used with Robust
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 053a17c5023a..5e09d354c5a5 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -673,6 +673,8 @@ static int ieee80211_init_cipher_suites(struct ieee80211_local *local)
673 /* keep last -- depends on hw flags! */ 673 /* keep last -- depends on hw flags! */
674 WLAN_CIPHER_SUITE_AES_CMAC, 674 WLAN_CIPHER_SUITE_AES_CMAC,
675 WLAN_CIPHER_SUITE_BIP_CMAC_256, 675 WLAN_CIPHER_SUITE_BIP_CMAC_256,
676 WLAN_CIPHER_SUITE_BIP_GMAC_128,
677 WLAN_CIPHER_SUITE_BIP_GMAC_256,
676 }; 678 };
677 679
678 if (local->hw.flags & IEEE80211_HW_SW_CRYPTO_CONTROL || 680 if (local->hw.flags & IEEE80211_HW_SW_CRYPTO_CONTROL ||
@@ -711,7 +713,7 @@ static int ieee80211_init_cipher_suites(struct ieee80211_local *local)
711 local->hw.wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); 713 local->hw.wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
712 714
713 if (!have_mfp) 715 if (!have_mfp)
714 local->hw.wiphy->n_cipher_suites -= 2; 716 local->hw.wiphy->n_cipher_suites -= 4;
715 717
716 if (!have_wep) { 718 if (!have_wep) {
717 local->hw.wiphy->cipher_suites += 2; 719 local->hw.wiphy->cipher_suites += 2;
@@ -737,9 +739,11 @@ static int ieee80211_init_cipher_suites(struct ieee80211_local *local)
737 if (have_wep) 739 if (have_wep)
738 n_suites += 2; 740 n_suites += 2;
739 741
740 /* check if we have AES_CMAC, BIP-CMAC-256 */ 742 /* check if we have AES_CMAC, BIP-CMAC-256, BIP-GMAC-128,
743 * BIP-GMAC-256
744 */
741 if (have_mfp) 745 if (have_mfp)
742 n_suites += 2; 746 n_suites += 4;
743 747
744 suites = kmalloc(sizeof(u32) * n_suites, GFP_KERNEL); 748 suites = kmalloc(sizeof(u32) * n_suites, GFP_KERNEL);
745 if (!suites) 749 if (!suites)
@@ -759,6 +763,8 @@ static int ieee80211_init_cipher_suites(struct ieee80211_local *local)
759 if (have_mfp) { 763 if (have_mfp) {
760 suites[w++] = WLAN_CIPHER_SUITE_AES_CMAC; 764 suites[w++] = WLAN_CIPHER_SUITE_AES_CMAC;
761 suites[w++] = WLAN_CIPHER_SUITE_BIP_CMAC_256; 765 suites[w++] = WLAN_CIPHER_SUITE_BIP_CMAC_256;
766 suites[w++] = WLAN_CIPHER_SUITE_BIP_GMAC_128;
767 suites[w++] = WLAN_CIPHER_SUITE_BIP_GMAC_256;
762 } 768 }
763 769
764 for (r = 0; r < local->hw.n_cipher_schemes; r++) 770 for (r = 0; r < local->hw.n_cipher_schemes; r++)
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 93ebc9525478..ed38d8302659 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1671,6 +1671,10 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
1671 case WLAN_CIPHER_SUITE_BIP_CMAC_256: 1671 case WLAN_CIPHER_SUITE_BIP_CMAC_256:
1672 result = ieee80211_crypto_aes_cmac_256_decrypt(rx); 1672 result = ieee80211_crypto_aes_cmac_256_decrypt(rx);
1673 break; 1673 break;
1674 case WLAN_CIPHER_SUITE_BIP_GMAC_128:
1675 case WLAN_CIPHER_SUITE_BIP_GMAC_256:
1676 result = ieee80211_crypto_aes_gmac_decrypt(rx);
1677 break;
1674 case WLAN_CIPHER_SUITE_GCMP: 1678 case WLAN_CIPHER_SUITE_GCMP:
1675 case WLAN_CIPHER_SUITE_GCMP_256: 1679 case WLAN_CIPHER_SUITE_GCMP_256:
1676 result = ieee80211_crypto_gcmp_decrypt(rx); 1680 result = ieee80211_crypto_gcmp_decrypt(rx);
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 909c27be1fdc..88a18ffe2975 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -640,6 +640,8 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
640 break; 640 break;
641 case WLAN_CIPHER_SUITE_AES_CMAC: 641 case WLAN_CIPHER_SUITE_AES_CMAC:
642 case WLAN_CIPHER_SUITE_BIP_CMAC_256: 642 case WLAN_CIPHER_SUITE_BIP_CMAC_256:
643 case WLAN_CIPHER_SUITE_BIP_GMAC_128:
644 case WLAN_CIPHER_SUITE_BIP_GMAC_256:
643 if (!ieee80211_is_mgmt(hdr->frame_control)) 645 if (!ieee80211_is_mgmt(hdr->frame_control))
644 tx->key = NULL; 646 tx->key = NULL;
645 break; 647 break;
@@ -1024,6 +1026,9 @@ ieee80211_tx_h_encrypt(struct ieee80211_tx_data *tx)
1024 return ieee80211_crypto_aes_cmac_encrypt(tx); 1026 return ieee80211_crypto_aes_cmac_encrypt(tx);
1025 case WLAN_CIPHER_SUITE_BIP_CMAC_256: 1027 case WLAN_CIPHER_SUITE_BIP_CMAC_256:
1026 return ieee80211_crypto_aes_cmac_256_encrypt(tx); 1028 return ieee80211_crypto_aes_cmac_256_encrypt(tx);
1029 case WLAN_CIPHER_SUITE_BIP_GMAC_128:
1030 case WLAN_CIPHER_SUITE_BIP_GMAC_256:
1031 return ieee80211_crypto_aes_gmac_encrypt(tx);
1027 case WLAN_CIPHER_SUITE_GCMP: 1032 case WLAN_CIPHER_SUITE_GCMP:
1028 case WLAN_CIPHER_SUITE_GCMP_256: 1033 case WLAN_CIPHER_SUITE_GCMP_256:
1029 return ieee80211_crypto_gcmp_encrypt(tx); 1034 return ieee80211_crypto_gcmp_encrypt(tx);
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c
index 549af118de9f..75de6fac40d1 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_gmac.h"
25#include "aes_gcm.h" 26#include "aes_gcm.h"
26#include "wpa.h" 27#include "wpa.h"
27 28
@@ -1099,6 +1100,110 @@ ieee80211_crypto_aes_cmac_256_decrypt(struct ieee80211_rx_data *rx)
1099} 1100}
1100 1101
1101ieee80211_tx_result 1102ieee80211_tx_result
1103ieee80211_crypto_aes_gmac_encrypt(struct ieee80211_tx_data *tx)
1104{
1105 struct sk_buff *skb;
1106 struct ieee80211_tx_info *info;
1107 struct ieee80211_key *key = tx->key;
1108 struct ieee80211_mmie_16 *mmie;
1109 struct ieee80211_hdr *hdr;
1110 u8 aad[20];
1111 u64 pn64;
1112 u8 nonce[12];
1113
1114 if (WARN_ON(skb_queue_len(&tx->skbs) != 1))
1115 return TX_DROP;
1116
1117 skb = skb_peek(&tx->skbs);
1118
1119 info = IEEE80211_SKB_CB(skb);
1120
1121 if (info->control.hw_key)
1122 return TX_CONTINUE;
1123
1124 if (WARN_ON(skb_tailroom(skb) < sizeof(*mmie)))
1125 return TX_DROP;
1126
1127 mmie = (struct ieee80211_mmie_16 *)skb_put(skb, sizeof(*mmie));
1128 mmie->element_id = WLAN_EID_MMIE;
1129 mmie->length = sizeof(*mmie) - 2;
1130 mmie->key_id = cpu_to_le16(key->conf.keyidx);
1131
1132 /* PN = PN + 1 */
1133 pn64 = atomic64_inc_return(&key->u.aes_gmac.tx_pn);
1134
1135 bip_ipn_set64(mmie->sequence_number, pn64);
1136
1137 bip_aad(skb, aad);
1138
1139 hdr = (struct ieee80211_hdr *)skb->data;
1140 memcpy(nonce, hdr->addr2, ETH_ALEN);
1141 bip_ipn_swap(nonce + ETH_ALEN, mmie->sequence_number);
1142
1143 /* MIC = AES-GMAC(IGTK, AAD || Management Frame Body || MMIE, 128) */
1144 if (ieee80211_aes_gmac(key->u.aes_gmac.tfm, aad, nonce,
1145 skb->data + 24, skb->len - 24, mmie->mic) < 0)
1146 return TX_DROP;
1147
1148 return TX_CONTINUE;
1149}
1150
1151ieee80211_rx_result
1152ieee80211_crypto_aes_gmac_decrypt(struct ieee80211_rx_data *rx)
1153{
1154 struct sk_buff *skb = rx->skb;
1155 struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
1156 struct ieee80211_key *key = rx->key;
1157 struct ieee80211_mmie_16 *mmie;
1158 u8 aad[20], mic[16], ipn[6], nonce[12];
1159 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
1160
1161 if (!ieee80211_is_mgmt(hdr->frame_control))
1162 return RX_CONTINUE;
1163
1164 /* management frames are already linear */
1165
1166 if (skb->len < 24 + sizeof(*mmie))
1167 return RX_DROP_UNUSABLE;
1168
1169 mmie = (struct ieee80211_mmie_16 *)
1170 (skb->data + skb->len - sizeof(*mmie));
1171 if (mmie->element_id != WLAN_EID_MMIE ||
1172 mmie->length != sizeof(*mmie) - 2)
1173 return RX_DROP_UNUSABLE; /* Invalid MMIE */
1174
1175 bip_ipn_swap(ipn, mmie->sequence_number);
1176
1177 if (memcmp(ipn, key->u.aes_gmac.rx_pn, 6) <= 0) {
1178 key->u.aes_gmac.replays++;
1179 return RX_DROP_UNUSABLE;
1180 }
1181
1182 if (!(status->flag & RX_FLAG_DECRYPTED)) {
1183 /* hardware didn't decrypt/verify MIC */
1184 bip_aad(skb, aad);
1185
1186 memcpy(nonce, hdr->addr2, ETH_ALEN);
1187 memcpy(nonce + ETH_ALEN, ipn, 6);
1188
1189 if (ieee80211_aes_gmac(key->u.aes_gmac.tfm, aad, nonce,
1190 skb->data + 24, skb->len - 24,
1191 mic) < 0 ||
1192 memcmp(mic, mmie->mic, sizeof(mmie->mic)) != 0) {
1193 key->u.aes_gmac.icverrors++;
1194 return RX_DROP_UNUSABLE;
1195 }
1196 }
1197
1198 memcpy(key->u.aes_gmac.rx_pn, ipn, 6);
1199
1200 /* Remove MMIE */
1201 skb_trim(skb, skb->len - sizeof(*mmie));
1202
1203 return RX_CONTINUE;
1204}
1205
1206ieee80211_tx_result
1102ieee80211_crypto_hw_encrypt(struct ieee80211_tx_data *tx) 1207ieee80211_crypto_hw_encrypt(struct ieee80211_tx_data *tx)
1103{ 1208{
1104 struct sk_buff *skb; 1209 struct sk_buff *skb;
diff --git a/net/mac80211/wpa.h b/net/mac80211/wpa.h
index 06b7f167a176..d98011ee8f55 100644
--- a/net/mac80211/wpa.h
+++ b/net/mac80211/wpa.h
@@ -39,6 +39,10 @@ ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx);
39ieee80211_rx_result 39ieee80211_rx_result
40ieee80211_crypto_aes_cmac_256_decrypt(struct ieee80211_rx_data *rx); 40ieee80211_crypto_aes_cmac_256_decrypt(struct ieee80211_rx_data *rx);
41ieee80211_tx_result 41ieee80211_tx_result
42ieee80211_crypto_aes_gmac_encrypt(struct ieee80211_tx_data *tx);
43ieee80211_rx_result
44ieee80211_crypto_aes_gmac_decrypt(struct ieee80211_rx_data *rx);
45ieee80211_tx_result
42ieee80211_crypto_hw_encrypt(struct ieee80211_tx_data *tx); 46ieee80211_crypto_hw_encrypt(struct ieee80211_tx_data *tx);
43ieee80211_rx_result 47ieee80211_rx_result
44ieee80211_crypto_hw_decrypt(struct ieee80211_rx_data *rx); 48ieee80211_crypto_hw_decrypt(struct ieee80211_rx_data *rx);