Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0-only
2 : : /*
3 : : * Copyright 2002-2004, Instant802 Networks, Inc.
4 : : * Copyright 2008, Jouni Malinen <j@w1.fi>
5 : : * Copyright (C) 2016-2017 Intel Deutschland GmbH
6 : : */
7 : :
8 : : #include <linux/netdevice.h>
9 : : #include <linux/types.h>
10 : : #include <linux/skbuff.h>
11 : : #include <linux/compiler.h>
12 : : #include <linux/ieee80211.h>
13 : : #include <linux/gfp.h>
14 : : #include <asm/unaligned.h>
15 : : #include <net/mac80211.h>
16 : : #include <crypto/aes.h>
17 : : #include <crypto/algapi.h>
18 : :
19 : : #include "ieee80211_i.h"
20 : : #include "michael.h"
21 : : #include "tkip.h"
22 : : #include "aes_ccm.h"
23 : : #include "aes_cmac.h"
24 : : #include "aes_gmac.h"
25 : : #include "aes_gcm.h"
26 : : #include "wpa.h"
27 : :
28 : : ieee80211_tx_result
29 : 0 : ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx)
30 : : {
31 : 0 : u8 *data, *key, *mic;
32 : 0 : size_t data_len;
33 : 0 : unsigned int hdrlen;
34 : 0 : struct ieee80211_hdr *hdr;
35 : 0 : struct sk_buff *skb = tx->skb;
36 [ # # ]: 0 : struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
37 : 0 : int tail;
38 : :
39 : 0 : hdr = (struct ieee80211_hdr *)skb->data;
40 [ # # # # ]: 0 : if (!tx->key || tx->key->conf.cipher != WLAN_CIPHER_SUITE_TKIP ||
41 [ # # # # ]: 0 : skb->len < 24 || !ieee80211_is_data_present(hdr->frame_control))
42 : : return TX_CONTINUE;
43 : :
44 : 0 : hdrlen = ieee80211_hdrlen(hdr->frame_control);
45 [ # # ]: 0 : if (skb->len < hdrlen)
46 : : return TX_DROP;
47 : :
48 : 0 : data = skb->data + hdrlen;
49 : 0 : data_len = skb->len - hdrlen;
50 : :
51 [ # # ]: 0 : if (unlikely(info->flags & IEEE80211_TX_INTFL_TKIP_MIC_FAILURE)) {
52 : : /* Need to use software crypto for the test */
53 : 0 : info->control.hw_key = NULL;
54 : : }
55 : :
56 [ # # ]: 0 : if (info->control.hw_key &&
57 [ # # # # ]: 0 : (info->flags & IEEE80211_TX_CTL_DONTFRAG ||
58 : 0 : ieee80211_hw_check(&tx->local->hw, SUPPORTS_TX_FRAG)) &&
59 [ # # ]: 0 : !(tx->key->conf.flags & (IEEE80211_KEY_FLAG_GENERATE_MMIC |
60 : : IEEE80211_KEY_FLAG_PUT_MIC_SPACE))) {
61 : : /* hwaccel - with no need for SW-generated MMIC or MIC space */
62 : : return TX_CONTINUE;
63 : : }
64 : :
65 : 0 : tail = MICHAEL_MIC_LEN;
66 [ # # ]: 0 : if (!info->control.hw_key)
67 : 0 : tail += IEEE80211_TKIP_ICV_LEN;
68 : :
69 [ # # # # : 0 : if (WARN(skb_tailroom(skb) < tail ||
# # # # #
# ]
70 : : skb_headroom(skb) < IEEE80211_TKIP_IV_LEN,
71 : : "mmic: not enough head/tail (%d/%d,%d/%d)\n",
72 : : skb_headroom(skb), IEEE80211_TKIP_IV_LEN,
73 : : skb_tailroom(skb), tail))
74 : : return TX_DROP;
75 : :
76 : 0 : mic = skb_put(skb, MICHAEL_MIC_LEN);
77 : :
78 [ # # ]: 0 : if (tx->key->conf.flags & IEEE80211_KEY_FLAG_PUT_MIC_SPACE) {
79 : : /* Zeroed MIC can help with debug */
80 : 0 : memset(mic, 0, MICHAEL_MIC_LEN);
81 : 0 : return TX_CONTINUE;
82 : : }
83 : :
84 : 0 : key = &tx->key->conf.key[NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY];
85 : 0 : michael_mic(key, hdr, data, data_len, mic);
86 [ # # ]: 0 : if (unlikely(info->flags & IEEE80211_TX_INTFL_TKIP_MIC_FAILURE))
87 : 0 : mic[0]++;
88 : :
89 : : return TX_CONTINUE;
90 : : }
91 : :
92 : :
93 : : ieee80211_rx_result
94 : 0 : ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx)
95 : : {
96 : 0 : u8 *data, *key = NULL;
97 : 0 : size_t data_len;
98 : 0 : unsigned int hdrlen;
99 : 0 : u8 mic[MICHAEL_MIC_LEN];
100 : 0 : struct sk_buff *skb = rx->skb;
101 [ # # ]: 0 : struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
102 : 0 : struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
103 : :
104 : : /*
105 : : * it makes no sense to check for MIC errors on anything other
106 : : * than data frames.
107 : : */
108 [ # # ]: 0 : if (!ieee80211_is_data_present(hdr->frame_control))
109 : : return RX_CONTINUE;
110 : :
111 : : /*
112 : : * No way to verify the MIC if the hardware stripped it or
113 : : * the IV with the key index. In this case we have solely rely
114 : : * on the driver to set RX_FLAG_MMIC_ERROR in the event of a
115 : : * MIC failure report.
116 : : */
117 [ # # ]: 0 : if (status->flag & (RX_FLAG_MMIC_STRIPPED | RX_FLAG_IV_STRIPPED)) {
118 [ # # ]: 0 : if (status->flag & RX_FLAG_MMIC_ERROR)
119 : 0 : goto mic_fail_no_key;
120 : :
121 [ # # # # ]: 0 : if (!(status->flag & RX_FLAG_IV_STRIPPED) && rx->key &&
122 [ # # ]: 0 : rx->key->conf.cipher == WLAN_CIPHER_SUITE_TKIP)
123 : 0 : goto update_iv;
124 : :
125 : : return RX_CONTINUE;
126 : : }
127 : :
128 : : /*
129 : : * Some hardware seems to generate Michael MIC failure reports; even
130 : : * though, the frame was not encrypted with TKIP and therefore has no
131 : : * MIC. Ignore the flag them to avoid triggering countermeasures.
132 : : */
133 [ # # # # ]: 0 : if (!rx->key || rx->key->conf.cipher != WLAN_CIPHER_SUITE_TKIP ||
134 [ # # ]: 0 : !(status->flag & RX_FLAG_DECRYPTED))
135 : : return RX_CONTINUE;
136 : :
137 [ # # # # ]: 0 : if (rx->sdata->vif.type == NL80211_IFTYPE_AP && rx->key->conf.keyidx) {
138 : : /*
139 : : * APs with pairwise keys should never receive Michael MIC
140 : : * errors for non-zero keyidx because these are reserved for
141 : : * group keys and only the AP is sending real multicast
142 : : * frames in the BSS.
143 : : */
144 : : return RX_DROP_UNUSABLE;
145 : : }
146 : :
147 [ # # ]: 0 : if (status->flag & RX_FLAG_MMIC_ERROR)
148 : 0 : goto mic_fail;
149 : :
150 : 0 : hdrlen = ieee80211_hdrlen(hdr->frame_control);
151 [ # # ]: 0 : if (skb->len < hdrlen + MICHAEL_MIC_LEN)
152 : : return RX_DROP_UNUSABLE;
153 : :
154 [ # # ]: 0 : if (skb_linearize(rx->skb))
155 : : return RX_DROP_UNUSABLE;
156 : 0 : hdr = (void *)skb->data;
157 : :
158 : 0 : data = skb->data + hdrlen;
159 : 0 : data_len = skb->len - hdrlen - MICHAEL_MIC_LEN;
160 : 0 : key = &rx->key->conf.key[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY];
161 : 0 : michael_mic(key, hdr, data, data_len, mic);
162 [ # # ]: 0 : if (crypto_memneq(mic, data + data_len, MICHAEL_MIC_LEN))
163 : 0 : goto mic_fail;
164 : :
165 : : /* remove Michael MIC from payload */
166 : 0 : skb_trim(skb, skb->len - MICHAEL_MIC_LEN);
167 : :
168 : 0 : update_iv:
169 : : /* update IV in key information to be able to detect replays */
170 : 0 : rx->key->u.tkip.rx[rx->security_idx].iv32 = rx->tkip_iv32;
171 : 0 : rx->key->u.tkip.rx[rx->security_idx].iv16 = rx->tkip_iv16;
172 : :
173 : 0 : return RX_CONTINUE;
174 : :
175 : 0 : mic_fail:
176 : 0 : rx->key->u.tkip.mic_failures++;
177 : :
178 : 0 : mic_fail_no_key:
179 : : /*
180 : : * In some cases the key can be unset - e.g. a multicast packet, in
181 : : * a driver that supports HW encryption. Send up the key idx only if
182 : : * the key is set.
183 : : */
184 : 0 : cfg80211_michael_mic_failure(rx->sdata->dev, hdr->addr2,
185 : : is_multicast_ether_addr(hdr->addr1) ?
186 : 0 : NL80211_KEYTYPE_GROUP :
187 : : NL80211_KEYTYPE_PAIRWISE,
188 [ # # ]: 0 : rx->key ? rx->key->conf.keyidx : -1,
189 : : NULL, GFP_ATOMIC);
190 : 0 : return RX_DROP_UNUSABLE;
191 : : }
192 : :
193 : : static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
194 : : {
195 : : struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
196 : : struct ieee80211_key *key = tx->key;
197 : : struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
198 : : unsigned int hdrlen;
199 : : int len, tail;
200 : : u64 pn;
201 : : u8 *pos;
202 : :
203 : : if (info->control.hw_key &&
204 : : !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV) &&
205 : : !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE)) {
206 : : /* hwaccel - with no need for software-generated IV */
207 : : return 0;
208 : : }
209 : :
210 : : hdrlen = ieee80211_hdrlen(hdr->frame_control);
211 : : len = skb->len - hdrlen;
212 : :
213 : : if (info->control.hw_key)
214 : : tail = 0;
215 : : else
216 : : tail = IEEE80211_TKIP_ICV_LEN;
217 : :
218 : : if (WARN_ON(skb_tailroom(skb) < tail ||
219 : : skb_headroom(skb) < IEEE80211_TKIP_IV_LEN))
220 : : return -1;
221 : :
222 : : pos = skb_push(skb, IEEE80211_TKIP_IV_LEN);
223 : : memmove(pos, pos + IEEE80211_TKIP_IV_LEN, hdrlen);
224 : : pos += hdrlen;
225 : :
226 : : /* the HW only needs room for the IV, but not the actual IV */
227 : : if (info->control.hw_key &&
228 : : (info->control.hw_key->flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE))
229 : : return 0;
230 : :
231 : : /* Increase IV for the frame */
232 : : pn = atomic64_inc_return(&key->conf.tx_pn);
233 : : pos = ieee80211_tkip_add_iv(pos, &key->conf, pn);
234 : :
235 : : /* hwaccel - with software IV */
236 : : if (info->control.hw_key)
237 : : return 0;
238 : :
239 : : /* Add room for ICV */
240 : : skb_put(skb, IEEE80211_TKIP_ICV_LEN);
241 : :
242 : : return ieee80211_tkip_encrypt_data(&tx->local->wep_tx_ctx,
243 : : key, skb, pos, len);
244 : : }
245 : :
246 : :
247 : : ieee80211_tx_result
248 : 0 : ieee80211_crypto_tkip_encrypt(struct ieee80211_tx_data *tx)
249 : : {
250 : 0 : struct sk_buff *skb;
251 : :
252 : 0 : ieee80211_tx_set_protected(tx);
253 : :
254 [ # # ]: 0 : skb_queue_walk(&tx->skbs, skb) {
255 [ # # ]: 0 : if (tkip_encrypt_skb(tx, skb) < 0)
256 : : return TX_DROP;
257 : : }
258 : :
259 : : return TX_CONTINUE;
260 : : }
261 : :
262 : :
263 : : ieee80211_rx_result
264 : 0 : ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx)
265 : : {
266 : 0 : struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data;
267 : 0 : int hdrlen, res, hwaccel = 0;
268 : 0 : struct ieee80211_key *key = rx->key;
269 : 0 : struct sk_buff *skb = rx->skb;
270 [ # # ]: 0 : struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
271 : :
272 : 0 : hdrlen = ieee80211_hdrlen(hdr->frame_control);
273 : :
274 [ # # ]: 0 : if (!ieee80211_is_data(hdr->frame_control))
275 : : return RX_CONTINUE;
276 : :
277 [ # # # # ]: 0 : if (!rx->sta || skb->len - hdrlen < 12)
278 : : return RX_DROP_UNUSABLE;
279 : :
280 : : /* it may be possible to optimize this a bit more */
281 [ # # ]: 0 : if (skb_linearize(rx->skb))
282 : : return RX_DROP_UNUSABLE;
283 : 0 : hdr = (void *)skb->data;
284 : :
285 : : /*
286 : : * Let TKIP code verify IV, but skip decryption.
287 : : * In the case where hardware checks the IV as well,
288 : : * we don't even get here, see ieee80211_rx_h_decrypt()
289 : : */
290 [ # # ]: 0 : if (status->flag & RX_FLAG_DECRYPTED)
291 : 0 : hwaccel = 1;
292 : :
293 : 0 : res = ieee80211_tkip_decrypt_data(&rx->local->wep_rx_ctx,
294 : 0 : key, skb->data + hdrlen,
295 : 0 : skb->len - hdrlen, rx->sta->sta.addr,
296 : 0 : hdr->addr1, hwaccel, rx->security_idx,
297 : : &rx->tkip_iv32,
298 : : &rx->tkip_iv16);
299 [ # # ]: 0 : if (res != TKIP_DECRYPT_OK)
300 : : return RX_DROP_UNUSABLE;
301 : :
302 : : /* Trim ICV */
303 [ # # ]: 0 : if (!(status->flag & RX_FLAG_ICV_STRIPPED))
304 : 0 : skb_trim(skb, skb->len - IEEE80211_TKIP_ICV_LEN);
305 : :
306 : : /* Remove IV */
307 : 0 : memmove(skb->data + IEEE80211_TKIP_IV_LEN, skb->data, hdrlen);
308 : 0 : skb_pull(skb, IEEE80211_TKIP_IV_LEN);
309 : :
310 : 0 : return RX_CONTINUE;
311 : : }
312 : :
313 : :
314 : : static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *b_0, u8 *aad)
315 : : {
316 : : __le16 mask_fc;
317 : : int a4_included, mgmt;
318 : : u8 qos_tid;
319 : : u16 len_a;
320 : : unsigned int hdrlen;
321 : : struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
322 : :
323 : : /*
324 : : * Mask FC: zero subtype b4 b5 b6 (if not mgmt)
325 : : * Retry, PwrMgt, MoreData; set Protected
326 : : */
327 : : mgmt = ieee80211_is_mgmt(hdr->frame_control);
328 : : mask_fc = hdr->frame_control;
329 : : mask_fc &= ~cpu_to_le16(IEEE80211_FCTL_RETRY |
330 : : IEEE80211_FCTL_PM | IEEE80211_FCTL_MOREDATA);
331 : : if (!mgmt)
332 : : mask_fc &= ~cpu_to_le16(0x0070);
333 : : mask_fc |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
334 : :
335 : : hdrlen = ieee80211_hdrlen(hdr->frame_control);
336 : : len_a = hdrlen - 2;
337 : : a4_included = ieee80211_has_a4(hdr->frame_control);
338 : :
339 : : if (ieee80211_is_data_qos(hdr->frame_control))
340 : : qos_tid = ieee80211_get_tid(hdr);
341 : : else
342 : : qos_tid = 0;
343 : :
344 : : /* In CCM, the initial vectors (IV) used for CTR mode encryption and CBC
345 : : * mode authentication are not allowed to collide, yet both are derived
346 : : * from this vector b_0. We only set L := 1 here to indicate that the
347 : : * data size can be represented in (L+1) bytes. The CCM layer will take
348 : : * care of storing the data length in the top (L+1) bytes and setting
349 : : * and clearing the other bits as is required to derive the two IVs.
350 : : */
351 : : b_0[0] = 0x1;
352 : :
353 : : /* Nonce: Nonce Flags | A2 | PN
354 : : * Nonce Flags: Priority (b0..b3) | Management (b4) | Reserved (b5..b7)
355 : : */
356 : : b_0[1] = qos_tid | (mgmt << 4);
357 : : memcpy(&b_0[2], hdr->addr2, ETH_ALEN);
358 : : memcpy(&b_0[8], pn, IEEE80211_CCMP_PN_LEN);
359 : :
360 : : /* AAD (extra authenticate-only data) / masked 802.11 header
361 : : * FC | A1 | A2 | A3 | SC | [A4] | [QC] */
362 : : put_unaligned_be16(len_a, &aad[0]);
363 : : put_unaligned(mask_fc, (__le16 *)&aad[2]);
364 : : memcpy(&aad[4], &hdr->addr1, 3 * ETH_ALEN);
365 : :
366 : : /* Mask Seq#, leave Frag# */
367 : : aad[22] = *((u8 *) &hdr->seq_ctrl) & 0x0f;
368 : : aad[23] = 0;
369 : :
370 : : if (a4_included) {
371 : : memcpy(&aad[24], hdr->addr4, ETH_ALEN);
372 : : aad[30] = qos_tid;
373 : : aad[31] = 0;
374 : : } else {
375 : : memset(&aad[24], 0, ETH_ALEN + IEEE80211_QOS_CTL_LEN);
376 : : aad[24] = qos_tid;
377 : : }
378 : : }
379 : :
380 : :
381 : : static inline void ccmp_pn2hdr(u8 *hdr, u8 *pn, int key_id)
382 : : {
383 : : hdr[0] = pn[5];
384 : : hdr[1] = pn[4];
385 : : hdr[2] = 0;
386 : : hdr[3] = 0x20 | (key_id << 6);
387 : : hdr[4] = pn[3];
388 : : hdr[5] = pn[2];
389 : : hdr[6] = pn[1];
390 : : hdr[7] = pn[0];
391 : : }
392 : :
393 : :
394 : 0 : static inline void ccmp_hdr2pn(u8 *pn, u8 *hdr)
395 : : {
396 : 0 : pn[0] = hdr[7];
397 : 0 : pn[1] = hdr[6];
398 : 0 : pn[2] = hdr[5];
399 : 0 : pn[3] = hdr[4];
400 : 0 : pn[4] = hdr[1];
401 : 0 : pn[5] = hdr[0];
402 : : }
403 : :
404 : :
405 : : static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb,
406 : : unsigned int mic_len)
407 : : {
408 : : struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
409 : : struct ieee80211_key *key = tx->key;
410 : : struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
411 : : int hdrlen, len, tail;
412 : : u8 *pos;
413 : : u8 pn[6];
414 : : u64 pn64;
415 : : u8 aad[CCM_AAD_LEN];
416 : : u8 b_0[AES_BLOCK_SIZE];
417 : :
418 : : if (info->control.hw_key &&
419 : : !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV) &&
420 : : !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE) &&
421 : : !((info->control.hw_key->flags &
422 : : IEEE80211_KEY_FLAG_GENERATE_IV_MGMT) &&
423 : : ieee80211_is_mgmt(hdr->frame_control))) {
424 : : /*
425 : : * hwaccel has no need for preallocated room for CCMP
426 : : * header or MIC fields
427 : : */
428 : : return 0;
429 : : }
430 : :
431 : : hdrlen = ieee80211_hdrlen(hdr->frame_control);
432 : : len = skb->len - hdrlen;
433 : :
434 : : if (info->control.hw_key)
435 : : tail = 0;
436 : : else
437 : : tail = mic_len;
438 : :
439 : : if (WARN_ON(skb_tailroom(skb) < tail ||
440 : : skb_headroom(skb) < IEEE80211_CCMP_HDR_LEN))
441 : : return -1;
442 : :
443 : : pos = skb_push(skb, IEEE80211_CCMP_HDR_LEN);
444 : : memmove(pos, pos + IEEE80211_CCMP_HDR_LEN, hdrlen);
445 : :
446 : : /* the HW only needs room for the IV, but not the actual IV */
447 : : if (info->control.hw_key &&
448 : : (info->control.hw_key->flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE))
449 : : return 0;
450 : :
451 : : hdr = (struct ieee80211_hdr *) pos;
452 : : pos += hdrlen;
453 : :
454 : : pn64 = atomic64_inc_return(&key->conf.tx_pn);
455 : :
456 : : pn[5] = pn64;
457 : : pn[4] = pn64 >> 8;
458 : : pn[3] = pn64 >> 16;
459 : : pn[2] = pn64 >> 24;
460 : : pn[1] = pn64 >> 32;
461 : : pn[0] = pn64 >> 40;
462 : :
463 : : ccmp_pn2hdr(pos, pn, key->conf.keyidx);
464 : :
465 : : /* hwaccel - with software CCMP header */
466 : : if (info->control.hw_key)
467 : : return 0;
468 : :
469 : : pos += IEEE80211_CCMP_HDR_LEN;
470 : : ccmp_special_blocks(skb, pn, b_0, aad);
471 : : return ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, b_0, aad, pos, len,
472 : : skb_put(skb, mic_len));
473 : : }
474 : :
475 : :
476 : : ieee80211_tx_result
477 : 0 : ieee80211_crypto_ccmp_encrypt(struct ieee80211_tx_data *tx,
478 : : unsigned int mic_len)
479 : : {
480 : 0 : struct sk_buff *skb;
481 : :
482 : 0 : ieee80211_tx_set_protected(tx);
483 : :
484 [ # # ]: 0 : skb_queue_walk(&tx->skbs, skb) {
485 [ # # ]: 0 : if (ccmp_encrypt_skb(tx, skb, mic_len) < 0)
486 : : return TX_DROP;
487 : : }
488 : :
489 : : return TX_CONTINUE;
490 : : }
491 : :
492 : :
493 : : ieee80211_rx_result
494 : 0 : ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx,
495 : : unsigned int mic_len)
496 : : {
497 : 0 : struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
498 : 0 : int hdrlen;
499 : 0 : struct ieee80211_key *key = rx->key;
500 : 0 : struct sk_buff *skb = rx->skb;
501 [ # # ]: 0 : struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
502 : 0 : u8 pn[IEEE80211_CCMP_PN_LEN];
503 : 0 : int data_len;
504 : 0 : int queue;
505 : :
506 : 0 : hdrlen = ieee80211_hdrlen(hdr->frame_control);
507 : :
508 [ # # # # ]: 0 : if (!ieee80211_is_data(hdr->frame_control) &&
509 [ # # ]: 0 : !ieee80211_is_robust_mgmt_frame(skb))
510 : : return RX_CONTINUE;
511 : :
512 [ # # ]: 0 : if (status->flag & RX_FLAG_DECRYPTED) {
513 [ # # ]: 0 : if (!pskb_may_pull(rx->skb, hdrlen + IEEE80211_CCMP_HDR_LEN))
514 : : return RX_DROP_UNUSABLE;
515 [ # # ]: 0 : if (status->flag & RX_FLAG_MIC_STRIPPED)
516 : 0 : mic_len = 0;
517 : : } else {
518 [ # # ]: 0 : if (skb_linearize(rx->skb))
519 : : return RX_DROP_UNUSABLE;
520 : : }
521 : :
522 : 0 : data_len = skb->len - hdrlen - IEEE80211_CCMP_HDR_LEN - mic_len;
523 [ # # # # ]: 0 : if (!rx->sta || data_len < 0)
524 : : return RX_DROP_UNUSABLE;
525 : :
526 [ # # ]: 0 : if (!(status->flag & RX_FLAG_PN_VALIDATED)) {
527 : 0 : int res;
528 : :
529 : 0 : ccmp_hdr2pn(pn, skb->data + hdrlen);
530 : :
531 : 0 : queue = rx->security_idx;
532 : :
533 : 0 : res = memcmp(pn, key->u.ccmp.rx_pn[queue],
534 : : IEEE80211_CCMP_PN_LEN);
535 [ # # # # ]: 0 : if (res < 0 ||
536 [ # # ]: 0 : (!res && !(status->flag & RX_FLAG_ALLOW_SAME_PN))) {
537 : 0 : key->u.ccmp.replays++;
538 : 0 : return RX_DROP_UNUSABLE;
539 : : }
540 : :
541 [ # # ]: 0 : if (!(status->flag & RX_FLAG_DECRYPTED)) {
542 : 0 : u8 aad[2 * AES_BLOCK_SIZE];
543 : 0 : u8 b_0[AES_BLOCK_SIZE];
544 : : /* hardware didn't decrypt/verify MIC */
545 : 0 : ccmp_special_blocks(skb, pn, b_0, aad);
546 : :
547 [ # # ]: 0 : if (ieee80211_aes_ccm_decrypt(
548 : : key->u.ccmp.tfm, b_0, aad,
549 : 0 : skb->data + hdrlen + IEEE80211_CCMP_HDR_LEN,
550 : : data_len,
551 : 0 : skb->data + skb->len - mic_len))
552 : 0 : return RX_DROP_UNUSABLE;
553 : : }
554 : :
555 : 0 : memcpy(key->u.ccmp.rx_pn[queue], pn, IEEE80211_CCMP_PN_LEN);
556 : : }
557 : :
558 : : /* Remove CCMP header and MIC */
559 [ # # ]: 0 : if (pskb_trim(skb, skb->len - mic_len))
560 : : return RX_DROP_UNUSABLE;
561 : 0 : memmove(skb->data + IEEE80211_CCMP_HDR_LEN, skb->data, hdrlen);
562 : 0 : skb_pull(skb, IEEE80211_CCMP_HDR_LEN);
563 : :
564 : 0 : return RX_CONTINUE;
565 : : }
566 : :
567 : : static void gcmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *j_0, u8 *aad)
568 : : {
569 : : __le16 mask_fc;
570 : : u8 qos_tid;
571 : : struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
572 : :
573 : : memcpy(j_0, hdr->addr2, ETH_ALEN);
574 : : memcpy(&j_0[ETH_ALEN], pn, IEEE80211_GCMP_PN_LEN);
575 : : j_0[13] = 0;
576 : : j_0[14] = 0;
577 : : j_0[AES_BLOCK_SIZE - 1] = 0x01;
578 : :
579 : : /* AAD (extra authenticate-only data) / masked 802.11 header
580 : : * FC | A1 | A2 | A3 | SC | [A4] | [QC]
581 : : */
582 : : put_unaligned_be16(ieee80211_hdrlen(hdr->frame_control) - 2, &aad[0]);
583 : : /* Mask FC: zero subtype b4 b5 b6 (if not mgmt)
584 : : * Retry, PwrMgt, MoreData; set Protected
585 : : */
586 : : mask_fc = hdr->frame_control;
587 : : mask_fc &= ~cpu_to_le16(IEEE80211_FCTL_RETRY |
588 : : IEEE80211_FCTL_PM | IEEE80211_FCTL_MOREDATA);
589 : : if (!ieee80211_is_mgmt(hdr->frame_control))
590 : : mask_fc &= ~cpu_to_le16(0x0070);
591 : : mask_fc |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
592 : :
593 : : put_unaligned(mask_fc, (__le16 *)&aad[2]);
594 : : memcpy(&aad[4], &hdr->addr1, 3 * ETH_ALEN);
595 : :
596 : : /* Mask Seq#, leave Frag# */
597 : : aad[22] = *((u8 *)&hdr->seq_ctrl) & 0x0f;
598 : : aad[23] = 0;
599 : :
600 : : if (ieee80211_is_data_qos(hdr->frame_control))
601 : : qos_tid = ieee80211_get_tid(hdr);
602 : : else
603 : : qos_tid = 0;
604 : :
605 : : if (ieee80211_has_a4(hdr->frame_control)) {
606 : : memcpy(&aad[24], hdr->addr4, ETH_ALEN);
607 : : aad[30] = qos_tid;
608 : : aad[31] = 0;
609 : : } else {
610 : : memset(&aad[24], 0, ETH_ALEN + IEEE80211_QOS_CTL_LEN);
611 : : aad[24] = qos_tid;
612 : : }
613 : : }
614 : :
615 : : static inline void gcmp_pn2hdr(u8 *hdr, const u8 *pn, int key_id)
616 : : {
617 : : hdr[0] = pn[5];
618 : : hdr[1] = pn[4];
619 : : hdr[2] = 0;
620 : : hdr[3] = 0x20 | (key_id << 6);
621 : : hdr[4] = pn[3];
622 : : hdr[5] = pn[2];
623 : : hdr[6] = pn[1];
624 : : hdr[7] = pn[0];
625 : : }
626 : :
627 : 0 : static inline void gcmp_hdr2pn(u8 *pn, const u8 *hdr)
628 : : {
629 : 0 : pn[0] = hdr[7];
630 : 0 : pn[1] = hdr[6];
631 : 0 : pn[2] = hdr[5];
632 : 0 : pn[3] = hdr[4];
633 : 0 : pn[4] = hdr[1];
634 : 0 : pn[5] = hdr[0];
635 : : }
636 : :
637 : : static int gcmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
638 : : {
639 : : struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
640 : : struct ieee80211_key *key = tx->key;
641 : : struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
642 : : int hdrlen, len, tail;
643 : : u8 *pos;
644 : : u8 pn[6];
645 : : u64 pn64;
646 : : u8 aad[GCM_AAD_LEN];
647 : : u8 j_0[AES_BLOCK_SIZE];
648 : :
649 : : if (info->control.hw_key &&
650 : : !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV) &&
651 : : !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE) &&
652 : : !((info->control.hw_key->flags &
653 : : IEEE80211_KEY_FLAG_GENERATE_IV_MGMT) &&
654 : : ieee80211_is_mgmt(hdr->frame_control))) {
655 : : /* hwaccel has no need for preallocated room for GCMP
656 : : * header or MIC fields
657 : : */
658 : : return 0;
659 : : }
660 : :
661 : : hdrlen = ieee80211_hdrlen(hdr->frame_control);
662 : : len = skb->len - hdrlen;
663 : :
664 : : if (info->control.hw_key)
665 : : tail = 0;
666 : : else
667 : : tail = IEEE80211_GCMP_MIC_LEN;
668 : :
669 : : if (WARN_ON(skb_tailroom(skb) < tail ||
670 : : skb_headroom(skb) < IEEE80211_GCMP_HDR_LEN))
671 : : return -1;
672 : :
673 : : pos = skb_push(skb, IEEE80211_GCMP_HDR_LEN);
674 : : memmove(pos, pos + IEEE80211_GCMP_HDR_LEN, hdrlen);
675 : : skb_set_network_header(skb, skb_network_offset(skb) +
676 : : IEEE80211_GCMP_HDR_LEN);
677 : :
678 : : /* the HW only needs room for the IV, but not the actual IV */
679 : : if (info->control.hw_key &&
680 : : (info->control.hw_key->flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE))
681 : : return 0;
682 : :
683 : : hdr = (struct ieee80211_hdr *)pos;
684 : : pos += hdrlen;
685 : :
686 : : pn64 = atomic64_inc_return(&key->conf.tx_pn);
687 : :
688 : : pn[5] = pn64;
689 : : pn[4] = pn64 >> 8;
690 : : pn[3] = pn64 >> 16;
691 : : pn[2] = pn64 >> 24;
692 : : pn[1] = pn64 >> 32;
693 : : pn[0] = pn64 >> 40;
694 : :
695 : : gcmp_pn2hdr(pos, pn, key->conf.keyidx);
696 : :
697 : : /* hwaccel - with software GCMP header */
698 : : if (info->control.hw_key)
699 : : return 0;
700 : :
701 : : pos += IEEE80211_GCMP_HDR_LEN;
702 : : gcmp_special_blocks(skb, pn, j_0, aad);
703 : : return ieee80211_aes_gcm_encrypt(key->u.gcmp.tfm, j_0, aad, pos, len,
704 : : skb_put(skb, IEEE80211_GCMP_MIC_LEN));
705 : : }
706 : :
707 : : ieee80211_tx_result
708 : 0 : ieee80211_crypto_gcmp_encrypt(struct ieee80211_tx_data *tx)
709 : : {
710 : 0 : struct sk_buff *skb;
711 : :
712 : 0 : ieee80211_tx_set_protected(tx);
713 : :
714 [ # # ]: 0 : skb_queue_walk(&tx->skbs, skb) {
715 [ # # ]: 0 : if (gcmp_encrypt_skb(tx, skb) < 0)
716 : : return TX_DROP;
717 : : }
718 : :
719 : : return TX_CONTINUE;
720 : : }
721 : :
722 : : ieee80211_rx_result
723 : 0 : ieee80211_crypto_gcmp_decrypt(struct ieee80211_rx_data *rx)
724 : : {
725 : 0 : struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
726 : 0 : int hdrlen;
727 : 0 : struct ieee80211_key *key = rx->key;
728 : 0 : struct sk_buff *skb = rx->skb;
729 [ # # ]: 0 : struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
730 : 0 : u8 pn[IEEE80211_GCMP_PN_LEN];
731 : 0 : int data_len, queue, mic_len = IEEE80211_GCMP_MIC_LEN;
732 : :
733 : 0 : hdrlen = ieee80211_hdrlen(hdr->frame_control);
734 : :
735 [ # # # # ]: 0 : if (!ieee80211_is_data(hdr->frame_control) &&
736 [ # # ]: 0 : !ieee80211_is_robust_mgmt_frame(skb))
737 : : return RX_CONTINUE;
738 : :
739 [ # # ]: 0 : if (status->flag & RX_FLAG_DECRYPTED) {
740 [ # # ]: 0 : if (!pskb_may_pull(rx->skb, hdrlen + IEEE80211_GCMP_HDR_LEN))
741 : : return RX_DROP_UNUSABLE;
742 [ # # ]: 0 : if (status->flag & RX_FLAG_MIC_STRIPPED)
743 : 0 : mic_len = 0;
744 : : } else {
745 [ # # ]: 0 : if (skb_linearize(rx->skb))
746 : : return RX_DROP_UNUSABLE;
747 : : }
748 : :
749 : 0 : data_len = skb->len - hdrlen - IEEE80211_GCMP_HDR_LEN - mic_len;
750 [ # # # # ]: 0 : if (!rx->sta || data_len < 0)
751 : : return RX_DROP_UNUSABLE;
752 : :
753 [ # # ]: 0 : if (!(status->flag & RX_FLAG_PN_VALIDATED)) {
754 : 0 : int res;
755 : :
756 : 0 : gcmp_hdr2pn(pn, skb->data + hdrlen);
757 : :
758 : 0 : queue = rx->security_idx;
759 : :
760 : 0 : res = memcmp(pn, key->u.gcmp.rx_pn[queue],
761 : : IEEE80211_GCMP_PN_LEN);
762 [ # # # # ]: 0 : if (res < 0 ||
763 [ # # ]: 0 : (!res && !(status->flag & RX_FLAG_ALLOW_SAME_PN))) {
764 : 0 : key->u.gcmp.replays++;
765 : 0 : return RX_DROP_UNUSABLE;
766 : : }
767 : :
768 [ # # ]: 0 : if (!(status->flag & RX_FLAG_DECRYPTED)) {
769 : 0 : u8 aad[2 * AES_BLOCK_SIZE];
770 : 0 : u8 j_0[AES_BLOCK_SIZE];
771 : : /* hardware didn't decrypt/verify MIC */
772 : 0 : gcmp_special_blocks(skb, pn, j_0, aad);
773 : :
774 [ # # ]: 0 : if (ieee80211_aes_gcm_decrypt(
775 : : key->u.gcmp.tfm, j_0, aad,
776 : 0 : skb->data + hdrlen + IEEE80211_GCMP_HDR_LEN,
777 : : data_len,
778 : 0 : skb->data + skb->len -
779 : : IEEE80211_GCMP_MIC_LEN))
780 : 0 : return RX_DROP_UNUSABLE;
781 : : }
782 : :
783 : 0 : memcpy(key->u.gcmp.rx_pn[queue], pn, IEEE80211_GCMP_PN_LEN);
784 : : }
785 : :
786 : : /* Remove GCMP header and MIC */
787 [ # # ]: 0 : if (pskb_trim(skb, skb->len - mic_len))
788 : : return RX_DROP_UNUSABLE;
789 : 0 : memmove(skb->data + IEEE80211_GCMP_HDR_LEN, skb->data, hdrlen);
790 : 0 : skb_pull(skb, IEEE80211_GCMP_HDR_LEN);
791 : :
792 : 0 : return RX_CONTINUE;
793 : : }
794 : :
795 : : static ieee80211_tx_result
796 : : ieee80211_crypto_cs_encrypt(struct ieee80211_tx_data *tx,
797 : : struct sk_buff *skb)
798 : : {
799 : : struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
800 : : struct ieee80211_key *key = tx->key;
801 : : struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
802 : : int hdrlen;
803 : : u8 *pos, iv_len = key->conf.iv_len;
804 : :
805 : : if (info->control.hw_key &&
806 : : !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE)) {
807 : : /* hwaccel has no need for preallocated head room */
808 : : return TX_CONTINUE;
809 : : }
810 : :
811 : : if (unlikely(skb_headroom(skb) < iv_len &&
812 : : pskb_expand_head(skb, iv_len, 0, GFP_ATOMIC)))
813 : : return TX_DROP;
814 : :
815 : : hdrlen = ieee80211_hdrlen(hdr->frame_control);
816 : :
817 : : pos = skb_push(skb, iv_len);
818 : : memmove(pos, pos + iv_len, hdrlen);
819 : :
820 : : return TX_CONTINUE;
821 : : }
822 : :
823 : 0 : static inline int ieee80211_crypto_cs_pn_compare(u8 *pn1, u8 *pn2, int len)
824 : : {
825 : 0 : int i;
826 : :
827 : : /* pn is little endian */
828 [ # # ]: 0 : for (i = len - 1; i >= 0; i--) {
829 [ # # ]: 0 : if (pn1[i] < pn2[i])
830 : : return -1;
831 [ # # ]: 0 : else if (pn1[i] > pn2[i])
832 : : return 1;
833 : : }
834 : :
835 : : return 0;
836 : : }
837 : :
838 : : static ieee80211_rx_result
839 : 0 : ieee80211_crypto_cs_decrypt(struct ieee80211_rx_data *rx)
840 : : {
841 : 0 : struct ieee80211_key *key = rx->key;
842 : 0 : struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
843 : 0 : const struct ieee80211_cipher_scheme *cs = NULL;
844 : 0 : int hdrlen = ieee80211_hdrlen(hdr->frame_control);
845 [ # # ]: 0 : struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
846 : 0 : int data_len;
847 : 0 : u8 *rx_pn;
848 : 0 : u8 *skb_pn;
849 : 0 : u8 qos_tid;
850 : :
851 [ # # # # ]: 0 : if (!rx->sta || !rx->sta->cipher_scheme ||
852 [ # # ]: 0 : !(status->flag & RX_FLAG_DECRYPTED))
853 : : return RX_DROP_UNUSABLE;
854 : :
855 [ # # ]: 0 : if (!ieee80211_is_data(hdr->frame_control))
856 : : return RX_CONTINUE;
857 : :
858 : 0 : cs = rx->sta->cipher_scheme;
859 : :
860 : 0 : data_len = rx->skb->len - hdrlen - cs->hdr_len;
861 : :
862 [ # # ]: 0 : if (data_len < 0)
863 : : return RX_DROP_UNUSABLE;
864 : :
865 [ # # ]: 0 : if (ieee80211_is_data_qos(hdr->frame_control))
866 [ # # ]: 0 : qos_tid = ieee80211_get_tid(hdr);
867 : : else
868 : : qos_tid = 0;
869 : :
870 [ # # ]: 0 : if (skb_linearize(rx->skb))
871 : : return RX_DROP_UNUSABLE;
872 : :
873 : 0 : hdr = (struct ieee80211_hdr *)rx->skb->data;
874 : :
875 : 0 : rx_pn = key->u.gen.rx_pn[qos_tid];
876 : 0 : skb_pn = rx->skb->data + hdrlen + cs->pn_off;
877 : :
878 [ # # ]: 0 : if (ieee80211_crypto_cs_pn_compare(skb_pn, rx_pn, cs->pn_len) <= 0)
879 : : return RX_DROP_UNUSABLE;
880 : :
881 : 0 : memcpy(rx_pn, skb_pn, cs->pn_len);
882 : :
883 : : /* remove security header and MIC */
884 [ # # ]: 0 : if (pskb_trim(rx->skb, rx->skb->len - cs->mic_len))
885 : : return RX_DROP_UNUSABLE;
886 : :
887 : 0 : memmove(rx->skb->data + cs->hdr_len, rx->skb->data, hdrlen);
888 : 0 : skb_pull(rx->skb, cs->hdr_len);
889 : :
890 : 0 : return RX_CONTINUE;
891 : : }
892 : :
893 : 0 : static void bip_aad(struct sk_buff *skb, u8 *aad)
894 : : {
895 : 0 : __le16 mask_fc;
896 : 0 : struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
897 : :
898 : : /* BIP AAD: FC(masked) || A1 || A2 || A3 */
899 : :
900 : : /* FC type/subtype */
901 : : /* Mask FC Retry, PwrMgt, MoreData flags to zero */
902 : 0 : mask_fc = hdr->frame_control;
903 : 0 : mask_fc &= ~cpu_to_le16(IEEE80211_FCTL_RETRY | IEEE80211_FCTL_PM |
904 : : IEEE80211_FCTL_MOREDATA);
905 : 0 : put_unaligned(mask_fc, (__le16 *) &aad[0]);
906 : : /* A1 || A2 || A3 */
907 : 0 : memcpy(aad + 2, &hdr->addr1, 3 * ETH_ALEN);
908 : : }
909 : :
910 : :
911 : 0 : static inline void bip_ipn_set64(u8 *d, u64 pn)
912 : : {
913 : 0 : *d++ = pn;
914 : 0 : *d++ = pn >> 8;
915 : 0 : *d++ = pn >> 16;
916 : 0 : *d++ = pn >> 24;
917 : 0 : *d++ = pn >> 32;
918 : 0 : *d = pn >> 40;
919 : : }
920 : :
921 : 0 : static inline void bip_ipn_swap(u8 *d, const u8 *s)
922 : : {
923 : 0 : *d++ = s[5];
924 : 0 : *d++ = s[4];
925 : 0 : *d++ = s[3];
926 : 0 : *d++ = s[2];
927 : 0 : *d++ = s[1];
928 : 0 : *d = s[0];
929 : : }
930 : :
931 : :
932 : : ieee80211_tx_result
933 : 0 : ieee80211_crypto_aes_cmac_encrypt(struct ieee80211_tx_data *tx)
934 : : {
935 : 0 : struct sk_buff *skb;
936 : 0 : struct ieee80211_tx_info *info;
937 : 0 : struct ieee80211_key *key = tx->key;
938 : 0 : struct ieee80211_mmie *mmie;
939 : 0 : u8 aad[20];
940 : 0 : u64 pn64;
941 : :
942 [ # # # # ]: 0 : if (WARN_ON(skb_queue_len(&tx->skbs) != 1))
943 : : return TX_DROP;
944 : :
945 [ # # ]: 0 : skb = skb_peek(&tx->skbs);
946 : :
947 [ # # ]: 0 : info = IEEE80211_SKB_CB(skb);
948 : :
949 [ # # ]: 0 : if (info->control.hw_key &&
950 [ # # ]: 0 : !(key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIE))
951 : : return TX_CONTINUE;
952 : :
953 [ # # # # : 0 : if (WARN_ON(skb_tailroom(skb) < sizeof(*mmie)))
# # ]
954 : : return TX_DROP;
955 : :
956 : 0 : mmie = skb_put(skb, sizeof(*mmie));
957 : 0 : mmie->element_id = WLAN_EID_MMIE;
958 : 0 : mmie->length = sizeof(*mmie) - 2;
959 : 0 : mmie->key_id = cpu_to_le16(key->conf.keyidx);
960 : :
961 : : /* PN = PN + 1 */
962 : 0 : pn64 = atomic64_inc_return(&key->conf.tx_pn);
963 : :
964 : 0 : bip_ipn_set64(mmie->sequence_number, pn64);
965 : :
966 [ # # ]: 0 : if (info->control.hw_key)
967 : : return TX_CONTINUE;
968 : :
969 : 0 : bip_aad(skb, aad);
970 : :
971 : : /*
972 : : * MIC = AES-128-CMAC(IGTK, AAD || Management Frame Body || MMIE, 64)
973 : : */
974 : 0 : ieee80211_aes_cmac(key->u.aes_cmac.tfm, aad,
975 : 0 : skb->data + 24, skb->len - 24, mmie->mic);
976 : :
977 : 0 : return TX_CONTINUE;
978 : : }
979 : :
980 : : ieee80211_tx_result
981 : 0 : ieee80211_crypto_aes_cmac_256_encrypt(struct ieee80211_tx_data *tx)
982 : : {
983 : 0 : struct sk_buff *skb;
984 : 0 : struct ieee80211_tx_info *info;
985 : 0 : struct ieee80211_key *key = tx->key;
986 : 0 : struct ieee80211_mmie_16 *mmie;
987 : 0 : u8 aad[20];
988 : 0 : u64 pn64;
989 : :
990 [ # # # # ]: 0 : if (WARN_ON(skb_queue_len(&tx->skbs) != 1))
991 : : return TX_DROP;
992 : :
993 [ # # ]: 0 : skb = skb_peek(&tx->skbs);
994 : :
995 [ # # ]: 0 : info = IEEE80211_SKB_CB(skb);
996 : :
997 [ # # ]: 0 : if (info->control.hw_key)
998 : : return TX_CONTINUE;
999 : :
1000 [ # # # # : 0 : if (WARN_ON(skb_tailroom(skb) < sizeof(*mmie)))
# # ]
1001 : : return TX_DROP;
1002 : :
1003 : 0 : mmie = skb_put(skb, sizeof(*mmie));
1004 : 0 : mmie->element_id = WLAN_EID_MMIE;
1005 : 0 : mmie->length = sizeof(*mmie) - 2;
1006 : 0 : mmie->key_id = cpu_to_le16(key->conf.keyidx);
1007 : :
1008 : : /* PN = PN + 1 */
1009 : 0 : pn64 = atomic64_inc_return(&key->conf.tx_pn);
1010 : :
1011 : 0 : bip_ipn_set64(mmie->sequence_number, pn64);
1012 : :
1013 : 0 : bip_aad(skb, aad);
1014 : :
1015 : : /* MIC = AES-256-CMAC(IGTK, AAD || Management Frame Body || MMIE, 128)
1016 : : */
1017 : 0 : ieee80211_aes_cmac_256(key->u.aes_cmac.tfm, aad,
1018 : 0 : skb->data + 24, skb->len - 24, mmie->mic);
1019 : :
1020 : 0 : return TX_CONTINUE;
1021 : : }
1022 : :
1023 : : ieee80211_rx_result
1024 : 0 : ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx)
1025 : : {
1026 : 0 : struct sk_buff *skb = rx->skb;
1027 [ # # ]: 0 : struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
1028 : 0 : struct ieee80211_key *key = rx->key;
1029 : 0 : struct ieee80211_mmie *mmie;
1030 : 0 : u8 aad[20], mic[8], ipn[6];
1031 : 0 : struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
1032 : :
1033 [ # # ]: 0 : if (!ieee80211_is_mgmt(hdr->frame_control))
1034 : : return RX_CONTINUE;
1035 : :
1036 : : /* management frames are already linear */
1037 : :
1038 [ # # ]: 0 : if (skb->len < 24 + sizeof(*mmie))
1039 : : return RX_DROP_UNUSABLE;
1040 : :
1041 : 0 : mmie = (struct ieee80211_mmie *)
1042 : 0 : (skb->data + skb->len - sizeof(*mmie));
1043 [ # # ]: 0 : if (mmie->element_id != WLAN_EID_MMIE ||
1044 [ # # ]: 0 : mmie->length != sizeof(*mmie) - 2)
1045 : : return RX_DROP_UNUSABLE; /* Invalid MMIE */
1046 : :
1047 : 0 : bip_ipn_swap(ipn, mmie->sequence_number);
1048 : :
1049 [ # # ]: 0 : if (memcmp(ipn, key->u.aes_cmac.rx_pn, 6) <= 0) {
1050 : 0 : key->u.aes_cmac.replays++;
1051 : 0 : return RX_DROP_UNUSABLE;
1052 : : }
1053 : :
1054 [ # # ]: 0 : if (!(status->flag & RX_FLAG_DECRYPTED)) {
1055 : : /* hardware didn't decrypt/verify MIC */
1056 : 0 : bip_aad(skb, aad);
1057 : 0 : ieee80211_aes_cmac(key->u.aes_cmac.tfm, aad,
1058 : 0 : skb->data + 24, skb->len - 24, mic);
1059 [ # # ]: 0 : if (crypto_memneq(mic, mmie->mic, sizeof(mmie->mic))) {
1060 : 0 : key->u.aes_cmac.icverrors++;
1061 : 0 : return RX_DROP_UNUSABLE;
1062 : : }
1063 : : }
1064 : :
1065 : 0 : memcpy(key->u.aes_cmac.rx_pn, ipn, 6);
1066 : :
1067 : : /* Remove MMIE */
1068 : 0 : skb_trim(skb, skb->len - sizeof(*mmie));
1069 : :
1070 : 0 : return RX_CONTINUE;
1071 : : }
1072 : :
1073 : : ieee80211_rx_result
1074 : 0 : ieee80211_crypto_aes_cmac_256_decrypt(struct ieee80211_rx_data *rx)
1075 : : {
1076 : 0 : struct sk_buff *skb = rx->skb;
1077 [ # # ]: 0 : struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
1078 : 0 : struct ieee80211_key *key = rx->key;
1079 : 0 : struct ieee80211_mmie_16 *mmie;
1080 : 0 : u8 aad[20], mic[16], ipn[6];
1081 : 0 : struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
1082 : :
1083 [ # # ]: 0 : if (!ieee80211_is_mgmt(hdr->frame_control))
1084 : : return RX_CONTINUE;
1085 : :
1086 : : /* management frames are already linear */
1087 : :
1088 [ # # ]: 0 : if (skb->len < 24 + sizeof(*mmie))
1089 : : return RX_DROP_UNUSABLE;
1090 : :
1091 : 0 : mmie = (struct ieee80211_mmie_16 *)
1092 : 0 : (skb->data + skb->len - sizeof(*mmie));
1093 [ # # ]: 0 : if (mmie->element_id != WLAN_EID_MMIE ||
1094 [ # # ]: 0 : mmie->length != sizeof(*mmie) - 2)
1095 : : return RX_DROP_UNUSABLE; /* Invalid MMIE */
1096 : :
1097 : 0 : bip_ipn_swap(ipn, mmie->sequence_number);
1098 : :
1099 [ # # ]: 0 : if (memcmp(ipn, key->u.aes_cmac.rx_pn, 6) <= 0) {
1100 : 0 : key->u.aes_cmac.replays++;
1101 : 0 : return RX_DROP_UNUSABLE;
1102 : : }
1103 : :
1104 [ # # ]: 0 : if (!(status->flag & RX_FLAG_DECRYPTED)) {
1105 : : /* hardware didn't decrypt/verify MIC */
1106 : 0 : bip_aad(skb, aad);
1107 : 0 : ieee80211_aes_cmac_256(key->u.aes_cmac.tfm, aad,
1108 : 0 : skb->data + 24, skb->len - 24, mic);
1109 [ # # ]: 0 : if (crypto_memneq(mic, mmie->mic, sizeof(mmie->mic))) {
1110 : 0 : key->u.aes_cmac.icverrors++;
1111 : 0 : return RX_DROP_UNUSABLE;
1112 : : }
1113 : : }
1114 : :
1115 : 0 : memcpy(key->u.aes_cmac.rx_pn, ipn, 6);
1116 : :
1117 : : /* Remove MMIE */
1118 : 0 : skb_trim(skb, skb->len - sizeof(*mmie));
1119 : :
1120 : 0 : return RX_CONTINUE;
1121 : : }
1122 : :
1123 : : ieee80211_tx_result
1124 : 0 : ieee80211_crypto_aes_gmac_encrypt(struct ieee80211_tx_data *tx)
1125 : : {
1126 : 0 : struct sk_buff *skb;
1127 : 0 : struct ieee80211_tx_info *info;
1128 : 0 : struct ieee80211_key *key = tx->key;
1129 : 0 : struct ieee80211_mmie_16 *mmie;
1130 : 0 : struct ieee80211_hdr *hdr;
1131 : 0 : u8 aad[GMAC_AAD_LEN];
1132 : 0 : u64 pn64;
1133 : 0 : u8 nonce[GMAC_NONCE_LEN];
1134 : :
1135 [ # # # # ]: 0 : if (WARN_ON(skb_queue_len(&tx->skbs) != 1))
1136 : : return TX_DROP;
1137 : :
1138 [ # # ]: 0 : skb = skb_peek(&tx->skbs);
1139 : :
1140 [ # # ]: 0 : info = IEEE80211_SKB_CB(skb);
1141 : :
1142 [ # # ]: 0 : if (info->control.hw_key)
1143 : : return TX_CONTINUE;
1144 : :
1145 [ # # # # : 0 : if (WARN_ON(skb_tailroom(skb) < sizeof(*mmie)))
# # ]
1146 : : return TX_DROP;
1147 : :
1148 : 0 : mmie = skb_put(skb, sizeof(*mmie));
1149 : 0 : mmie->element_id = WLAN_EID_MMIE;
1150 : 0 : mmie->length = sizeof(*mmie) - 2;
1151 : 0 : mmie->key_id = cpu_to_le16(key->conf.keyidx);
1152 : :
1153 : : /* PN = PN + 1 */
1154 : 0 : pn64 = atomic64_inc_return(&key->conf.tx_pn);
1155 : :
1156 : 0 : bip_ipn_set64(mmie->sequence_number, pn64);
1157 : :
1158 : 0 : bip_aad(skb, aad);
1159 : :
1160 : 0 : hdr = (struct ieee80211_hdr *)skb->data;
1161 : 0 : memcpy(nonce, hdr->addr2, ETH_ALEN);
1162 : 0 : bip_ipn_swap(nonce + ETH_ALEN, mmie->sequence_number);
1163 : :
1164 : : /* MIC = AES-GMAC(IGTK, AAD || Management Frame Body || MMIE, 128) */
1165 [ # # ]: 0 : if (ieee80211_aes_gmac(key->u.aes_gmac.tfm, aad, nonce,
1166 : 0 : skb->data + 24, skb->len - 24, mmie->mic) < 0)
1167 : 0 : return TX_DROP;
1168 : :
1169 : : return TX_CONTINUE;
1170 : : }
1171 : :
1172 : : ieee80211_rx_result
1173 : 0 : ieee80211_crypto_aes_gmac_decrypt(struct ieee80211_rx_data *rx)
1174 : : {
1175 : 0 : struct sk_buff *skb = rx->skb;
1176 [ # # ]: 0 : struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
1177 : 0 : struct ieee80211_key *key = rx->key;
1178 : 0 : struct ieee80211_mmie_16 *mmie;
1179 : 0 : u8 aad[GMAC_AAD_LEN], *mic, ipn[6], nonce[GMAC_NONCE_LEN];
1180 : 0 : struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
1181 : :
1182 [ # # ]: 0 : if (!ieee80211_is_mgmt(hdr->frame_control))
1183 : : return RX_CONTINUE;
1184 : :
1185 : : /* management frames are already linear */
1186 : :
1187 [ # # ]: 0 : if (skb->len < 24 + sizeof(*mmie))
1188 : : return RX_DROP_UNUSABLE;
1189 : :
1190 : 0 : mmie = (struct ieee80211_mmie_16 *)
1191 : 0 : (skb->data + skb->len - sizeof(*mmie));
1192 [ # # ]: 0 : if (mmie->element_id != WLAN_EID_MMIE ||
1193 [ # # ]: 0 : mmie->length != sizeof(*mmie) - 2)
1194 : : return RX_DROP_UNUSABLE; /* Invalid MMIE */
1195 : :
1196 : 0 : bip_ipn_swap(ipn, mmie->sequence_number);
1197 : :
1198 [ # # ]: 0 : if (memcmp(ipn, key->u.aes_gmac.rx_pn, 6) <= 0) {
1199 : 0 : key->u.aes_gmac.replays++;
1200 : 0 : return RX_DROP_UNUSABLE;
1201 : : }
1202 : :
1203 [ # # ]: 0 : if (!(status->flag & RX_FLAG_DECRYPTED)) {
1204 : : /* hardware didn't decrypt/verify MIC */
1205 : 0 : bip_aad(skb, aad);
1206 : :
1207 : 0 : memcpy(nonce, hdr->addr2, ETH_ALEN);
1208 : 0 : memcpy(nonce + ETH_ALEN, ipn, 6);
1209 : :
1210 : 0 : mic = kmalloc(GMAC_MIC_LEN, GFP_ATOMIC);
1211 [ # # ]: 0 : if (!mic)
1212 : : return RX_DROP_UNUSABLE;
1213 [ # # ]: 0 : if (ieee80211_aes_gmac(key->u.aes_gmac.tfm, aad, nonce,
1214 : 0 : skb->data + 24, skb->len - 24,
1215 [ # # ]: 0 : mic) < 0 ||
1216 : 0 : crypto_memneq(mic, mmie->mic, sizeof(mmie->mic))) {
1217 : 0 : key->u.aes_gmac.icverrors++;
1218 : 0 : kfree(mic);
1219 : 0 : return RX_DROP_UNUSABLE;
1220 : : }
1221 : 0 : kfree(mic);
1222 : : }
1223 : :
1224 : 0 : memcpy(key->u.aes_gmac.rx_pn, ipn, 6);
1225 : :
1226 : : /* Remove MMIE */
1227 : 0 : skb_trim(skb, skb->len - sizeof(*mmie));
1228 : :
1229 : 0 : return RX_CONTINUE;
1230 : : }
1231 : :
1232 : : ieee80211_tx_result
1233 : 0 : ieee80211_crypto_hw_encrypt(struct ieee80211_tx_data *tx)
1234 : : {
1235 : 0 : struct sk_buff *skb;
1236 : 0 : struct ieee80211_tx_info *info = NULL;
1237 : 0 : ieee80211_tx_result res;
1238 : :
1239 [ # # ]: 0 : skb_queue_walk(&tx->skbs, skb) {
1240 [ # # ]: 0 : info = IEEE80211_SKB_CB(skb);
1241 : :
1242 : : /* handle hw-only algorithm */
1243 [ # # ]: 0 : if (!info->control.hw_key)
1244 : : return TX_DROP;
1245 : :
1246 [ # # ]: 0 : if (tx->key->flags & KEY_FLAG_CIPHER_SCHEME) {
1247 : 0 : res = ieee80211_crypto_cs_encrypt(tx, skb);
1248 [ # # ]: 0 : if (res != TX_CONTINUE)
1249 : 0 : return res;
1250 : : }
1251 : : }
1252 : :
1253 : 0 : ieee80211_tx_set_protected(tx);
1254 : :
1255 : 0 : return TX_CONTINUE;
1256 : : }
1257 : :
1258 : : ieee80211_rx_result
1259 : 0 : ieee80211_crypto_hw_decrypt(struct ieee80211_rx_data *rx)
1260 : : {
1261 [ # # # # ]: 0 : if (rx->sta && rx->sta->cipher_scheme)
1262 : 0 : return ieee80211_crypto_cs_decrypt(rx);
1263 : :
1264 : : return RX_DROP_UNUSABLE;
1265 : : }
|