1 --- a/net/mac80211/wpa.c
2 +++ b/net/mac80211/wpa.c
3 @@ -301,15 +301,22 @@ ieee80211_crypto_tkip_decrypt(struct iee
7 -static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *b_0, u8 *aad)
8 +static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *scratch,
12 int a4_included, mgmt;
16 + u16 data_len, len_a;
18 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
20 + memset(scratch, 0, 6 * AES_BLOCK_SIZE);
22 + b_0 = scratch + 3 * AES_BLOCK_SIZE;
23 + aad = scratch + 4 * AES_BLOCK_SIZE;
26 * Mask FC: zero subtype b4 b5 b6 (if not mgmt)
27 * Retry, PwrMgt, MoreData; set Protected
28 @@ -331,21 +338,20 @@ static void ccmp_special_blocks(struct s
32 - /* In CCM, the initial vectors (IV) used for CTR mode encryption and CBC
33 - * mode authentication are not allowed to collide, yet both are derived
34 - * from this vector b_0. We only set L := 1 here to indicate that the
35 - * data size can be represented in (L+1) bytes. The CCM layer will take
36 - * care of storing the data length in the top (L+1) bytes and setting
37 - * and clearing the other bits as is required to derive the two IVs.
40 + data_len = skb->len - hdrlen - IEEE80211_CCMP_HDR_LEN;
42 + data_len -= IEEE80211_CCMP_MIC_LEN;
44 + /* First block, b_0 */
45 + b_0[0] = 0x59; /* flags: Adata: 1, M: 011, L: 001 */
46 /* Nonce: Nonce Flags | A2 | PN
47 * Nonce Flags: Priority (b0..b3) | Management (b4) | Reserved (b5..b7)
49 b_0[1] = qos_tid | (mgmt << 4);
50 memcpy(&b_0[2], hdr->addr2, ETH_ALEN);
51 memcpy(&b_0[8], pn, IEEE80211_CCMP_PN_LEN);
53 + put_unaligned_be16(data_len, &b_0[14]);
55 /* AAD (extra authenticate-only data) / masked 802.11 header
56 * FC | A1 | A2 | A3 | SC | [A4] | [QC] */
57 @@ -401,8 +407,7 @@ static int ccmp_encrypt_skb(struct ieee8
61 - u8 aad[2 * AES_BLOCK_SIZE];
62 - u8 b_0[AES_BLOCK_SIZE];
63 + u8 scratch[6 * AES_BLOCK_SIZE];
65 if (info->control.hw_key &&
66 !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV) &&
67 @@ -455,9 +460,9 @@ static int ccmp_encrypt_skb(struct ieee8
70 pos += IEEE80211_CCMP_HDR_LEN;
71 - ccmp_special_blocks(skb, pn, b_0, aad);
72 - ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, b_0, aad, pos, len,
73 - skb_put(skb, IEEE80211_CCMP_MIC_LEN));
74 + ccmp_special_blocks(skb, pn, scratch, 0);
75 + ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, scratch, pos, len,
76 + pos, skb_put(skb, IEEE80211_CCMP_MIC_LEN));
80 @@ -520,16 +525,16 @@ ieee80211_crypto_ccmp_decrypt(struct iee
83 if (!(status->flag & RX_FLAG_DECRYPTED)) {
84 - u8 aad[2 * AES_BLOCK_SIZE];
85 - u8 b_0[AES_BLOCK_SIZE];
86 + u8 scratch[6 * AES_BLOCK_SIZE];
87 /* hardware didn't decrypt/verify MIC */
88 - ccmp_special_blocks(skb, pn, b_0, aad);
89 + ccmp_special_blocks(skb, pn, scratch, 1);
91 if (ieee80211_aes_ccm_decrypt(
92 - key->u.ccmp.tfm, b_0, aad,
93 + key->u.ccmp.tfm, scratch,
94 skb->data + hdrlen + IEEE80211_CCMP_HDR_LEN,
96 - skb->data + skb->len - IEEE80211_CCMP_MIC_LEN))
97 + skb->data + skb->len - IEEE80211_CCMP_MIC_LEN,
98 + skb->data + hdrlen + IEEE80211_CCMP_HDR_LEN))
99 return RX_DROP_UNUSABLE;
102 --- a/net/mac80211/Kconfig
103 +++ b/net/mac80211/Kconfig
104 @@ -5,7 +5,6 @@ config MAC80211
106 depends on CRYPTO_ARC4
107 depends on CRYPTO_AES
108 - depends on CRYPTO_CCM
110 select BACKPORT_AVERAGE
112 --- a/net/mac80211/aes_ccm.c
113 +++ b/net/mac80211/aes_ccm.c
115 * Copyright 2003-2004, Instant802 Networks, Inc.
116 * Copyright 2005-2006, Devicescape Software, Inc.
118 - * Rewrite: Copyright (C) 2013 Linaro Ltd <ard.biesheuvel@linaro.org>
120 * This program is free software; you can redistribute it and/or modify
121 * it under the terms of the GNU General Public License version 2 as
122 * published by the Free Software Foundation.
127 -void ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
128 - u8 *data, size_t data_len, u8 *mic)
129 +static void aes_ccm_prepare(struct crypto_cipher *tfm, u8 *scratch, u8 *a)
131 - struct scatterlist assoc, pt, ct[2];
133 - struct aead_request req;
134 - u8 priv[crypto_aead_reqsize(tfm)];
137 - memset(&aead_req, 0, sizeof(aead_req));
139 - sg_init_one(&pt, data, data_len);
140 - sg_init_one(&assoc, &aad[2], be16_to_cpup((__be16 *)aad));
141 - sg_init_table(ct, 2);
142 - sg_set_buf(&ct[0], data, data_len);
143 - sg_set_buf(&ct[1], mic, IEEE80211_CCMP_MIC_LEN);
145 - aead_request_set_tfm(&aead_req.req, tfm);
146 - aead_request_set_assoc(&aead_req.req, &assoc, assoc.length);
147 - aead_request_set_crypt(&aead_req.req, &pt, ct, data_len, b_0);
149 + u8 *b_0, *aad, *b, *s_0;
151 - crypto_aead_encrypt(&aead_req.req);
152 + b_0 = scratch + 3 * AES_BLOCK_SIZE;
153 + aad = scratch + 4 * AES_BLOCK_SIZE;
155 + s_0 = scratch + AES_BLOCK_SIZE;
157 + crypto_cipher_encrypt_one(tfm, b, b_0);
159 + /* Extra Authenticate-only data (always two AES blocks) */
160 + for (i = 0; i < AES_BLOCK_SIZE; i++)
162 + crypto_cipher_encrypt_one(tfm, b, aad);
164 + aad += AES_BLOCK_SIZE;
166 + for (i = 0; i < AES_BLOCK_SIZE; i++)
168 + crypto_cipher_encrypt_one(tfm, a, aad);
170 + /* Mask out bits from auth-only-b_0 */
173 + /* S_0 is used to encrypt T (= MIC) */
176 + crypto_cipher_encrypt_one(tfm, s_0, b_0);
179 -int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
180 - u8 *data, size_t data_len, u8 *mic)
182 +void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *scratch,
183 + u8 *data, size_t data_len,
184 + u8 *cdata, u8 *mic)
186 - struct scatterlist assoc, pt, ct[2];
188 - struct aead_request req;
189 - u8 priv[crypto_aead_reqsize(tfm)];
192 - memset(&aead_req, 0, sizeof(aead_req));
194 - sg_init_one(&pt, data, data_len);
195 - sg_init_one(&assoc, &aad[2], be16_to_cpup((__be16 *)aad));
196 - sg_init_table(ct, 2);
197 - sg_set_buf(&ct[0], data, data_len);
198 - sg_set_buf(&ct[1], mic, IEEE80211_CCMP_MIC_LEN);
200 - aead_request_set_tfm(&aead_req.req, tfm);
201 - aead_request_set_assoc(&aead_req.req, &assoc, assoc.length);
202 - aead_request_set_crypt(&aead_req.req, ct, &pt,
203 - data_len + IEEE80211_CCMP_MIC_LEN, b_0);
204 + int i, j, last_len, num_blocks;
205 + u8 *pos, *cpos, *b, *s_0, *e, *b_0;
208 + s_0 = scratch + AES_BLOCK_SIZE;
209 + e = scratch + 2 * AES_BLOCK_SIZE;
210 + b_0 = scratch + 3 * AES_BLOCK_SIZE;
212 + num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_SIZE);
213 + last_len = data_len % AES_BLOCK_SIZE;
214 + aes_ccm_prepare(tfm, scratch, b);
216 + /* Process payload blocks */
219 + for (j = 1; j <= num_blocks; j++) {
220 + int blen = (j == num_blocks && last_len) ?
221 + last_len : AES_BLOCK_SIZE;
223 + /* Authentication followed by encryption */
224 + for (i = 0; i < blen; i++)
226 + crypto_cipher_encrypt_one(tfm, b, b);
228 + b_0[14] = (j >> 8) & 0xff;
229 + b_0[15] = j & 0xff;
230 + crypto_cipher_encrypt_one(tfm, e, b_0);
231 + for (i = 0; i < blen; i++)
232 + *cpos++ = *pos++ ^ e[i];
235 - return crypto_aead_decrypt(&aead_req.req);
236 + for (i = 0; i < IEEE80211_CCMP_MIC_LEN; i++)
237 + mic[i] = b[i] ^ s_0[i];
240 -struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[])
242 +int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *scratch,
243 + u8 *cdata, size_t data_len, u8 *mic, u8 *data)
245 - struct crypto_aead *tfm;
247 + int i, j, last_len, num_blocks;
248 + u8 *pos, *cpos, *b, *s_0, *a, *b_0;
250 - tfm = crypto_alloc_aead("ccm(aes)", 0, CRYPTO_ALG_ASYNC);
254 - err = crypto_aead_setkey(tfm, key, WLAN_KEY_LEN_CCMP);
256 - err = crypto_aead_setauthsize(tfm, IEEE80211_CCMP_MIC_LEN);
260 + s_0 = scratch + AES_BLOCK_SIZE;
261 + a = scratch + 2 * AES_BLOCK_SIZE;
262 + b_0 = scratch + 3 * AES_BLOCK_SIZE;
264 + num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_SIZE);
265 + last_len = data_len % AES_BLOCK_SIZE;
266 + aes_ccm_prepare(tfm, scratch, a);
268 + /* Process payload blocks */
271 + for (j = 1; j <= num_blocks; j++) {
272 + int blen = (j == num_blocks && last_len) ?
273 + last_len : AES_BLOCK_SIZE;
275 + /* Decryption followed by authentication */
276 + b_0[14] = (j >> 8) & 0xff;
277 + b_0[15] = j & 0xff;
278 + crypto_cipher_encrypt_one(tfm, b, b_0);
279 + for (i = 0; i < blen; i++) {
280 + *pos = *cpos++ ^ b[i];
283 + crypto_cipher_encrypt_one(tfm, a, a);
286 + for (i = 0; i < IEEE80211_CCMP_MIC_LEN; i++) {
287 + if ((mic[i] ^ s_0[i]) != a[i])
291 - crypto_free_aead(tfm);
292 - return ERR_PTR(err);
296 -void ieee80211_aes_key_free(struct crypto_aead *tfm)
298 +struct crypto_cipher *ieee80211_aes_key_setup_encrypt(const u8 key[])
300 + struct crypto_cipher *tfm;
302 + tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
304 + crypto_cipher_setkey(tfm, key, WLAN_KEY_LEN_CCMP);
310 +void ieee80211_aes_key_free(struct crypto_cipher *tfm)
312 - crypto_free_aead(tfm);
313 + crypto_free_cipher(tfm);
315 --- a/net/mac80211/aes_ccm.h
316 +++ b/net/mac80211/aes_ccm.h
319 #include <linux/crypto.h>
321 -struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[]);
322 -void ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
323 - u8 *data, size_t data_len, u8 *mic);
324 -int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
325 - u8 *data, size_t data_len, u8 *mic);
326 -void ieee80211_aes_key_free(struct crypto_aead *tfm);
327 +struct crypto_cipher *ieee80211_aes_key_setup_encrypt(const u8 key[]);
328 +void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *scratch,
329 + u8 *data, size_t data_len,
330 + u8 *cdata, u8 *mic);
331 +int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *scratch,
332 + u8 *cdata, size_t data_len,
333 + u8 *mic, u8 *data);
334 +void ieee80211_aes_key_free(struct crypto_cipher *tfm);
336 #endif /* AES_CCM_H */
337 --- a/net/mac80211/key.h
338 +++ b/net/mac80211/key.h
339 @@ -84,7 +84,7 @@ struct ieee80211_key {
342 u8 rx_pn[IEEE80211_NUM_TIDS + 1][IEEE80211_CCMP_PN_LEN];
343 - struct crypto_aead *tfm;
344 + struct crypto_cipher *tfm;
345 u32 replays; /* dot11RSNAStatsCCMPReplays */