hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/net/wireless/lib80211_crypt_ccmp.c
....@@ -1,13 +1,9 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * lib80211 crypt: host-based CCMP encryption implementation for lib80211
34 *
45 * Copyright (c) 2003-2004, Jouni Malinen <j@w1.fi>
56 * Copyright (c) 2008, John W. Linville <linville@tuxdriver.com>
6
- *
7
- * This program is free software; you can redistribute it and/or modify
8
- * it under the terms of the GNU General Public License version 2 as
9
- * published by the Free Software Foundation. See README and COPYING for
10
- * more details.
117 */
128
139 #include <linux/kernel.h>
....@@ -26,6 +22,7 @@
2622 #include <linux/ieee80211.h>
2723
2824 #include <linux/crypto.h>
25
+#include <crypto/aead.h>
2926
3027 #include <net/lib80211.h>
3128
....@@ -52,19 +49,12 @@
5249
5350 int key_idx;
5451
55
- struct crypto_cipher *tfm;
52
+ struct crypto_aead *tfm;
5653
5754 /* scratch buffers for virt_to_page() (crypto API) */
58
- u8 tx_b0[AES_BLOCK_LEN], tx_b[AES_BLOCK_LEN],
59
- tx_e[AES_BLOCK_LEN], tx_s0[AES_BLOCK_LEN];
60
- u8 rx_b0[AES_BLOCK_LEN], rx_b[AES_BLOCK_LEN], rx_a[AES_BLOCK_LEN];
55
+ u8 tx_aad[2 * AES_BLOCK_LEN];
56
+ u8 rx_aad[2 * AES_BLOCK_LEN];
6157 };
62
-
63
-static inline void lib80211_ccmp_aes_encrypt(struct crypto_cipher *tfm,
64
- const u8 pt[16], u8 ct[16])
65
-{
66
- crypto_cipher_encrypt_one(tfm, ct, pt);
67
-}
6858
6959 static void *lib80211_ccmp_init(int key_idx)
7060 {
....@@ -75,7 +65,7 @@
7565 goto fail;
7666 priv->key_idx = key_idx;
7767
78
- priv->tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
68
+ priv->tfm = crypto_alloc_aead("ccm(aes)", 0, CRYPTO_ALG_ASYNC);
7969 if (IS_ERR(priv->tfm)) {
8070 priv->tfm = NULL;
8171 goto fail;
....@@ -86,7 +76,7 @@
8676 fail:
8777 if (priv) {
8878 if (priv->tfm)
89
- crypto_free_cipher(priv->tfm);
79
+ crypto_free_aead(priv->tfm);
9080 kfree(priv);
9181 }
9282
....@@ -97,25 +87,16 @@
9787 {
9888 struct lib80211_ccmp_data *_priv = priv;
9989 if (_priv && _priv->tfm)
100
- crypto_free_cipher(_priv->tfm);
90
+ crypto_free_aead(_priv->tfm);
10191 kfree(priv);
10292 }
10393
104
-static inline void xor_block(u8 * b, u8 * a, size_t len)
105
-{
106
- int i;
107
- for (i = 0; i < len; i++)
108
- b[i] ^= a[i];
109
-}
110
-
111
-static void ccmp_init_blocks(struct crypto_cipher *tfm,
112
- struct ieee80211_hdr *hdr,
113
- u8 * pn, size_t dlen, u8 * b0, u8 * auth, u8 * s0)
94
+static int ccmp_init_iv_and_aad(const struct ieee80211_hdr *hdr,
95
+ const u8 *pn, u8 *iv, u8 *aad)
11496 {
11597 u8 *pos, qc = 0;
11698 size_t aad_len;
11799 int a4_included, qc_included;
118
- u8 aad[2 * AES_BLOCK_LEN];
119100
120101 a4_included = ieee80211_has_a4(hdr->frame_control);
121102 qc_included = ieee80211_is_data_qos(hdr->frame_control);
....@@ -131,17 +112,19 @@
131112 aad_len += 2;
132113 }
133114
134
- /* CCM Initial Block:
135
- * Flag (Include authentication header, M=3 (8-octet MIC),
136
- * L=1 (2-octet Dlen))
137
- * Nonce: 0x00 | A2 | PN
138
- * Dlen */
139
- b0[0] = 0x59;
140
- b0[1] = qc;
141
- memcpy(b0 + 2, hdr->addr2, ETH_ALEN);
142
- memcpy(b0 + 8, pn, CCMP_PN_LEN);
143
- b0[14] = (dlen >> 8) & 0xff;
144
- b0[15] = dlen & 0xff;
115
+ /* In CCM, the initial vectors (IV) used for CTR mode encryption and CBC
116
+ * mode authentication are not allowed to collide, yet both are derived
117
+ * from the same vector. We only set L := 1 here to indicate that the
118
+ * data size can be represented in (L+1) bytes. The CCM layer will take
119
+ * care of storing the data length in the top (L+1) bytes and setting
120
+ * and clearing the other bits as is required to derive the two IVs.
121
+ */
122
+ iv[0] = 0x1;
123
+
124
+ /* Nonce: QC | A2 | PN */
125
+ iv[1] = qc;
126
+ memcpy(iv + 2, hdr->addr2, ETH_ALEN);
127
+ memcpy(iv + 8, pn, CCMP_PN_LEN);
145128
146129 /* AAD:
147130 * FC with bits 4..6 and 11..13 masked to zero; 14 is always one
....@@ -151,31 +134,20 @@
151134 * QC (if present)
152135 */
153136 pos = (u8 *) hdr;
154
- aad[0] = 0; /* aad_len >> 8 */
155
- aad[1] = aad_len & 0xff;
156
- aad[2] = pos[0] & 0x8f;
157
- aad[3] = pos[1] & 0xc7;
158
- memcpy(aad + 4, hdr->addr1, 3 * ETH_ALEN);
137
+ aad[0] = pos[0] & 0x8f;
138
+ aad[1] = pos[1] & 0xc7;
139
+ memcpy(aad + 2, hdr->addr1, 3 * ETH_ALEN);
159140 pos = (u8 *) & hdr->seq_ctrl;
160
- aad[22] = pos[0] & 0x0f;
161
- aad[23] = 0; /* all bits masked */
162
- memset(aad + 24, 0, 8);
141
+ aad[20] = pos[0] & 0x0f;
142
+ aad[21] = 0; /* all bits masked */
143
+ memset(aad + 22, 0, 8);
163144 if (a4_included)
164
- memcpy(aad + 24, hdr->addr4, ETH_ALEN);
145
+ memcpy(aad + 22, hdr->addr4, ETH_ALEN);
165146 if (qc_included) {
166
- aad[a4_included ? 30 : 24] = qc;
147
+ aad[a4_included ? 28 : 22] = qc;
167148 /* rest of QC masked */
168149 }
169
-
170
- /* Start with the first block and AAD */
171
- lib80211_ccmp_aes_encrypt(tfm, b0, auth);
172
- xor_block(auth, aad, AES_BLOCK_LEN);
173
- lib80211_ccmp_aes_encrypt(tfm, auth, auth);
174
- xor_block(auth, &aad[AES_BLOCK_LEN], AES_BLOCK_LEN);
175
- lib80211_ccmp_aes_encrypt(tfm, auth, auth);
176
- b0[0] &= 0x07;
177
- b0[14] = b0[15] = 0;
178
- lib80211_ccmp_aes_encrypt(tfm, b0, s0);
150
+ return aad_len;
179151 }
180152
181153 static int lib80211_ccmp_hdr(struct sk_buff *skb, int hdr_len,
....@@ -218,13 +190,13 @@
218190 static int lib80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
219191 {
220192 struct lib80211_ccmp_data *key = priv;
221
- int data_len, i, blocks, last, len;
222
- u8 *pos, *mic;
223193 struct ieee80211_hdr *hdr;
224
- u8 *b0 = key->tx_b0;
225
- u8 *b = key->tx_b;
226
- u8 *e = key->tx_e;
227
- u8 *s0 = key->tx_s0;
194
+ struct aead_request *req;
195
+ struct scatterlist sg[2];
196
+ u8 *aad = key->tx_aad;
197
+ u8 iv[AES_BLOCK_LEN];
198
+ int len, data_len, aad_len;
199
+ int ret;
228200
229201 if (skb_tailroom(skb) < CCMP_MIC_LEN || skb->len < hdr_len)
230202 return -1;
....@@ -234,31 +206,28 @@
234206 if (len < 0)
235207 return -1;
236208
237
- pos = skb->data + hdr_len + CCMP_HDR_LEN;
209
+ req = aead_request_alloc(key->tfm, GFP_ATOMIC);
210
+ if (!req)
211
+ return -ENOMEM;
212
+
238213 hdr = (struct ieee80211_hdr *)skb->data;
239
- ccmp_init_blocks(key->tfm, hdr, key->tx_pn, data_len, b0, b, s0);
214
+ aad_len = ccmp_init_iv_and_aad(hdr, key->tx_pn, iv, aad);
240215
241
- blocks = DIV_ROUND_UP(data_len, AES_BLOCK_LEN);
242
- last = data_len % AES_BLOCK_LEN;
216
+ skb_put(skb, CCMP_MIC_LEN);
243217
244
- for (i = 1; i <= blocks; i++) {
245
- len = (i == blocks && last) ? last : AES_BLOCK_LEN;
246
- /* Authentication */
247
- xor_block(b, pos, len);
248
- lib80211_ccmp_aes_encrypt(key->tfm, b, b);
249
- /* Encryption, with counter */
250
- b0[14] = (i >> 8) & 0xff;
251
- b0[15] = i & 0xff;
252
- lib80211_ccmp_aes_encrypt(key->tfm, b0, e);
253
- xor_block(pos, e, len);
254
- pos += len;
255
- }
218
+ sg_init_table(sg, 2);
219
+ sg_set_buf(&sg[0], aad, aad_len);
220
+ sg_set_buf(&sg[1], skb->data + hdr_len + CCMP_HDR_LEN,
221
+ data_len + CCMP_MIC_LEN);
256222
257
- mic = skb_put(skb, CCMP_MIC_LEN);
258
- for (i = 0; i < CCMP_MIC_LEN; i++)
259
- mic[i] = b[i] ^ s0[i];
223
+ aead_request_set_callback(req, 0, NULL, NULL);
224
+ aead_request_set_ad(req, aad_len);
225
+ aead_request_set_crypt(req, sg, sg, data_len, iv);
260226
261
- return 0;
227
+ ret = crypto_aead_encrypt(req);
228
+ aead_request_free(req);
229
+
230
+ return ret;
262231 }
263232
264233 /*
....@@ -287,13 +256,13 @@
287256 struct lib80211_ccmp_data *key = priv;
288257 u8 keyidx, *pos;
289258 struct ieee80211_hdr *hdr;
290
- u8 *b0 = key->rx_b0;
291
- u8 *b = key->rx_b;
292
- u8 *a = key->rx_a;
259
+ struct aead_request *req;
260
+ struct scatterlist sg[2];
261
+ u8 *aad = key->rx_aad;
262
+ u8 iv[AES_BLOCK_LEN];
293263 u8 pn[6];
294
- int i, blocks, last, len;
295
- size_t data_len = skb->len - hdr_len - CCMP_HDR_LEN - CCMP_MIC_LEN;
296
- u8 *mic = skb->data + skb->len - CCMP_MIC_LEN;
264
+ int aad_len, ret;
265
+ size_t data_len = skb->len - hdr_len - CCMP_HDR_LEN;
297266
298267 if (skb->len < hdr_len + CCMP_HDR_LEN + CCMP_MIC_LEN) {
299268 key->dot11RSNAStatsCCMPFormatErrors++;
....@@ -341,28 +310,26 @@
341310 return -4;
342311 }
343312
344
- ccmp_init_blocks(key->tfm, hdr, pn, data_len, b0, a, b);
345
- xor_block(mic, b, CCMP_MIC_LEN);
313
+ req = aead_request_alloc(key->tfm, GFP_ATOMIC);
314
+ if (!req)
315
+ return -ENOMEM;
346316
347
- blocks = DIV_ROUND_UP(data_len, AES_BLOCK_LEN);
348
- last = data_len % AES_BLOCK_LEN;
317
+ aad_len = ccmp_init_iv_and_aad(hdr, pn, iv, aad);
349318
350
- for (i = 1; i <= blocks; i++) {
351
- len = (i == blocks && last) ? last : AES_BLOCK_LEN;
352
- /* Decrypt, with counter */
353
- b0[14] = (i >> 8) & 0xff;
354
- b0[15] = i & 0xff;
355
- lib80211_ccmp_aes_encrypt(key->tfm, b0, b);
356
- xor_block(pos, b, len);
357
- /* Authentication */
358
- xor_block(a, pos, len);
359
- lib80211_ccmp_aes_encrypt(key->tfm, a, a);
360
- pos += len;
361
- }
319
+ sg_init_table(sg, 2);
320
+ sg_set_buf(&sg[0], aad, aad_len);
321
+ sg_set_buf(&sg[1], pos, data_len);
362322
363
- if (memcmp(mic, a, CCMP_MIC_LEN) != 0) {
364
- net_dbg_ratelimited("CCMP: decrypt failed: STA=%pM\n",
365
- hdr->addr2);
323
+ aead_request_set_callback(req, 0, NULL, NULL);
324
+ aead_request_set_ad(req, aad_len);
325
+ aead_request_set_crypt(req, sg, sg, data_len, iv);
326
+
327
+ ret = crypto_aead_decrypt(req);
328
+ aead_request_free(req);
329
+
330
+ if (ret) {
331
+ net_dbg_ratelimited("CCMP: decrypt failed: STA=%pM (%d)\n",
332
+ hdr->addr2, ret);
366333 key->dot11RSNAStatsCCMPDecryptErrors++;
367334 return -5;
368335 }
....@@ -381,7 +348,7 @@
381348 {
382349 struct lib80211_ccmp_data *data = priv;
383350 int keyidx;
384
- struct crypto_cipher *tfm = data->tfm;
351
+ struct crypto_aead *tfm = data->tfm;
385352
386353 keyidx = data->key_idx;
387354 memset(data, 0, sizeof(*data));
....@@ -398,7 +365,9 @@
398365 data->rx_pn[4] = seq[1];
399366 data->rx_pn[5] = seq[0];
400367 }
401
- crypto_cipher_setkey(data->tfm, data->key, CCMP_TK_LEN);
368
+ if (crypto_aead_setauthsize(data->tfm, CCMP_MIC_LEN) ||
369
+ crypto_aead_setkey(data->tfm, data->key, CCMP_TK_LEN))
370
+ return -1;
402371 } else if (len == 0)
403372 data->key_set = 0;
404373 else