wpa.c 15.1 KB
Newer Older
1 2
/*
 * Copyright 2002-2004, Instant802 Networks, Inc.
3
 * Copyright 2008, Jouni Malinen <j@w1.fi>
4 5 6 7 8 9 10 11 12 13
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/netdevice.h>
#include <linux/types.h>
#include <linux/skbuff.h>
#include <linux/compiler.h>
14
#include <linux/ieee80211.h>
15
#include <linux/gfp.h>
16
#include <asm/unaligned.h>
17
#include <net/mac80211.h>
J
Johannes Berg 已提交
18

19 20 21 22
#include "ieee80211_i.h"
#include "michael.h"
#include "tkip.h"
#include "aes_ccm.h"
23
#include "aes_cmac.h"
24 25
#include "wpa.h"

26
ieee80211_tx_result
27
ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx)
28
{
29
	u8 *data, *key, *mic;
30
	size_t data_len;
31 32
	unsigned int hdrlen;
	struct ieee80211_hdr *hdr;
33
	struct sk_buff *skb = tx->skb;
34
	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
35
	int tail;
36

37
	hdr = (struct ieee80211_hdr *)skb->data;
38 39
	if (!tx->key || tx->key->conf.cipher != WLAN_CIPHER_SUITE_TKIP ||
	    skb->len < 24 || !ieee80211_is_data_present(hdr->frame_control))
40
		return TX_CONTINUE;
41

42 43
	hdrlen = ieee80211_hdrlen(hdr->frame_control);
	if (skb->len < hdrlen)
44
		return TX_DROP;
45

46 47 48
	data = skb->data + hdrlen;
	data_len = skb->len - hdrlen;

49 50 51 52 53
	if (unlikely(info->flags & IEEE80211_TX_INTFL_TKIP_MIC_FAILURE)) {
		/* Need to use software crypto for the test */
		info->control.hw_key = NULL;
	}

54
	if (info->control.hw_key &&
55
	    !(tx->flags & IEEE80211_TX_FRAGMENTED) &&
56 57
	    !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC)) {
		/* hwaccel - with no need for SW-generated MMIC */
58
		return TX_CONTINUE;
59 60
	}

61
	tail = MICHAEL_MIC_LEN;
62
	if (!info->control.hw_key)
63 64 65 66 67
		tail += TKIP_ICV_LEN;

	if (WARN_ON(skb_tailroom(skb) < tail ||
		    skb_headroom(skb) < TKIP_IV_LEN))
		return TX_DROP;
68

69
	key = &tx->key->conf.key[NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY];
70
	mic = skb_put(skb, MICHAEL_MIC_LEN);
71
	michael_mic(key, hdr, data, data_len, mic);
72 73
	if (unlikely(info->flags & IEEE80211_TX_INTFL_TKIP_MIC_FAILURE))
		mic[0]++;
74

75
	return TX_CONTINUE;
76 77 78
}


79
ieee80211_rx_result
80
ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx)
81
{
82
	u8 *data, *key = NULL;
83
	size_t data_len;
84
	unsigned int hdrlen;
85 86
	u8 mic[MICHAEL_MIC_LEN];
	struct sk_buff *skb = rx->skb;
J
Johannes Berg 已提交
87 88
	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
89

90 91 92 93 94
	/*
	 * it makes no sense to check for MIC errors on anything other
	 * than data frames.
	 */
	if (!ieee80211_is_data_present(hdr->frame_control))
95
		return RX_CONTINUE;
96

97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
	/*
	 * No way to verify the MIC if the hardware stripped it or
	 * the IV with the key index. In this case we have solely rely
	 * on the driver to set RX_FLAG_MMIC_ERROR in the event of a
	 * MIC failure report.
	 */
	if (status->flag & (RX_FLAG_MMIC_STRIPPED | RX_FLAG_IV_STRIPPED)) {
		if (status->flag & RX_FLAG_MMIC_ERROR)
			goto mic_fail;

		if (!(status->flag & RX_FLAG_IV_STRIPPED))
			goto update_iv;

		return RX_CONTINUE;
	}

	/*
	 * Some hardware seems to generate Michael MIC failure reports; even
	 * though, the frame was not encrypted with TKIP and therefore has no
	 * MIC. Ignore the flag them to avoid triggering countermeasures.
	 */
118
	if (!rx->key || rx->key->conf.cipher != WLAN_CIPHER_SUITE_TKIP ||
119
	    !(status->flag & RX_FLAG_DECRYPTED))
120
		return RX_CONTINUE;
121

122 123 124 125 126 127 128 129 130 131 132 133 134
	if (rx->sdata->vif.type == NL80211_IFTYPE_AP && rx->key->conf.keyidx) {
		/*
		 * APs with pairwise keys should never receive Michael MIC
		 * errors for non-zero keyidx because these are reserved for
		 * group keys and only the AP is sending real multicast
		 * frames in the BSS. (
		 */
		return RX_DROP_UNUSABLE;
	}

	if (status->flag & RX_FLAG_MMIC_ERROR)
		goto mic_fail;

135 136
	hdrlen = ieee80211_hdrlen(hdr->frame_control);
	if (skb->len < hdrlen + MICHAEL_MIC_LEN)
J
Johannes Berg 已提交
137
		return RX_DROP_UNUSABLE;
138

139 140
	data = skb->data + hdrlen;
	data_len = skb->len - hdrlen - MICHAEL_MIC_LEN;
141
	key = &rx->key->conf.key[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY];
142
	michael_mic(key, hdr, data, data_len, mic);
143 144
	if (memcmp(mic, data + data_len, MICHAEL_MIC_LEN) != 0)
		goto mic_fail;
145 146 147 148

	/* remove Michael MIC from payload */
	skb_trim(skb, skb->len - MICHAEL_MIC_LEN);

149
update_iv:
150
	/* update IV in key information to be able to detect replays */
151 152
	rx->key->u.tkip.rx[rx->queue].iv32 = rx->tkip_iv32;
	rx->key->u.tkip.rx[rx->queue].iv16 = rx->tkip_iv16;
153

154
	return RX_CONTINUE;
155 156 157 158 159

mic_fail:
	mac80211_ev_michael_mic_failure(rx->sdata, rx->key->conf.keyidx,
					(void *) skb->data, NULL, GFP_ATOMIC);
	return RX_DROP_UNUSABLE;
160 161 162
}


163
static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
164 165 166
{
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
	struct ieee80211_key *key = tx->key;
167
	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
168 169
	unsigned int hdrlen;
	int len, tail;
170 171
	u8 *pos;

172 173 174
	if (info->control.hw_key &&
	    !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV)) {
		/* hwaccel - with no need for software-generated IV */
175
		return 0;
176 177
	}

178
	hdrlen = ieee80211_hdrlen(hdr->frame_control);
179 180
	len = skb->len - hdrlen;

181
	if (info->control.hw_key)
182
		tail = 0;
J
Johannes Berg 已提交
183
	else
184 185 186 187 188
		tail = TKIP_ICV_LEN;

	if (WARN_ON(skb_tailroom(skb) < tail ||
		    skb_headroom(skb) < TKIP_IV_LEN))
		return -1;
189 190 191 192 193 194

	pos = skb_push(skb, TKIP_IV_LEN);
	memmove(pos, pos + TKIP_IV_LEN, hdrlen);
	pos += hdrlen;

	/* Increase IV for the frame */
195 196 197
	key->u.tkip.tx.iv16++;
	if (key->u.tkip.tx.iv16 == 0)
		key->u.tkip.tx.iv32++;
198

199
	pos = ieee80211_tkip_add_iv(pos, key, key->u.tkip.tx.iv16);
200

201 202
	/* hwaccel - with software IV */
	if (info->control.hw_key)
203 204 205 206 207 208
		return 0;

	/* Add room for ICV */
	skb_put(skb, TKIP_ICV_LEN);

	hdr = (struct ieee80211_hdr *) skb->data;
209 210
	return ieee80211_tkip_encrypt_data(tx->local->wep_tx_tfm,
					   key, pos, len, hdr->addr2);
211 212 213
}


214
ieee80211_tx_result
215
ieee80211_crypto_tkip_encrypt(struct ieee80211_tx_data *tx)
216 217 218
{
	struct sk_buff *skb = tx->skb;

219
	ieee80211_tx_set_protected(tx);
220

J
Johannes Berg 已提交
221 222 223 224
	do {
		if (tkip_encrypt_skb(tx, skb) < 0)
			return TX_DROP;
	} while ((skb = skb->next));
225

226
	return TX_CONTINUE;
227 228 229
}


230
ieee80211_rx_result
231
ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx)
232 233
{
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data;
234
	int hdrlen, res, hwaccel = 0;
235 236
	struct ieee80211_key *key = rx->key;
	struct sk_buff *skb = rx->skb;
J
Johannes Berg 已提交
237
	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
238

239
	hdrlen = ieee80211_hdrlen(hdr->frame_control);
240

241
	if (!ieee80211_is_data(hdr->frame_control))
242
		return RX_CONTINUE;
243 244

	if (!rx->sta || skb->len - hdrlen < 12)
J
Johannes Berg 已提交
245
		return RX_DROP_UNUSABLE;
246

247 248 249 250 251 252
	/*
	 * Let TKIP code verify IV, but skip decryption.
	 * In the case where hardware checks the IV as well,
	 * we don't even get here, see ieee80211_rx_h_decrypt()
	 */
	if (status->flag & RX_FLAG_DECRYPTED)
253 254 255 256
		hwaccel = 1;

	res = ieee80211_tkip_decrypt_data(rx->local->wep_rx_tfm,
					  key, skb->data + hdrlen,
257
					  skb->len - hdrlen, rx->sta->sta.addr,
258
					  hdr->addr1, hwaccel, rx->queue,
259 260
					  &rx->tkip_iv32,
					  &rx->tkip_iv16);
261
	if (res != TKIP_DECRYPT_OK)
J
Johannes Berg 已提交
262
		return RX_DROP_UNUSABLE;
263 264 265 266 267 268 269 270

	/* Trim ICV */
	skb_trim(skb, skb->len - TKIP_ICV_LEN);

	/* Remove IV */
	memmove(skb->data + TKIP_IV_LEN, skb->data, hdrlen);
	skb_pull(skb, TKIP_IV_LEN);

271
	return RX_CONTINUE;
272 273 274
}


275
static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *scratch,
276 277
				int encrypted)
{
278
	__le16 mask_fc;
279
	int a4_included, mgmt;
280
	u8 qos_tid;
281
	u8 *b_0, *aad;
282 283 284
	u16 data_len, len_a;
	unsigned int hdrlen;
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
285

286 287 288
	b_0 = scratch + 3 * AES_BLOCK_LEN;
	aad = scratch + 4 * AES_BLOCK_LEN;

289
	/*
290
	 * Mask FC: zero subtype b4 b5 b6 (if not mgmt)
291 292
	 * Retry, PwrMgt, MoreData; set Protected
	 */
293
	mgmt = ieee80211_is_mgmt(hdr->frame_control);
294
	mask_fc = hdr->frame_control;
295
	mask_fc &= ~cpu_to_le16(IEEE80211_FCTL_RETRY |
296
				IEEE80211_FCTL_PM | IEEE80211_FCTL_MOREDATA);
297 298
	if (!mgmt)
		mask_fc &= ~cpu_to_le16(0x0070);
299 300 301 302 303
	mask_fc |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);

	hdrlen = ieee80211_hdrlen(hdr->frame_control);
	len_a = hdrlen - 2;
	a4_included = ieee80211_has_a4(hdr->frame_control);
304

305 306 307 308 309 310 311 312 313 314
	if (ieee80211_is_data_qos(hdr->frame_control))
		qos_tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK;
	else
		qos_tid = 0;

	data_len = skb->len - hdrlen - CCMP_HDR_LEN;
	if (encrypted)
		data_len -= CCMP_MIC_LEN;

	/* First block, b_0 */
315
	b_0[0] = 0x59; /* flags: Adata: 1, M: 011, L: 001 */
316 317 318 319
	/* Nonce: Nonce Flags | A2 | PN
	 * Nonce Flags: Priority (b0..b3) | Management (b4) | Reserved (b5..b7)
	 */
	b_0[1] = qos_tid | (mgmt << 4);
320
	memcpy(&b_0[2], hdr->addr2, ETH_ALEN);
321 322
	memcpy(&b_0[8], pn, CCMP_PN_LEN);
	/* l(m) */
323
	put_unaligned_be16(data_len, &b_0[14]);
324 325 326

	/* AAD (extra authenticate-only data) / masked 802.11 header
	 * FC | A1 | A2 | A3 | SC | [A4] | [QC] */
327 328
	put_unaligned_be16(len_a, &aad[0]);
	put_unaligned(mask_fc, (__le16 *)&aad[2]);
329
	memcpy(&aad[4], &hdr->addr1, 3 * ETH_ALEN);
330 331 332 333

	/* Mask Seq#, leave Frag# */
	aad[22] = *((u8 *) &hdr->seq_ctrl) & 0x0f;
	aad[23] = 0;
334

335
	if (a4_included) {
336
		memcpy(&aad[24], hdr->addr4, ETH_ALEN);
337
		aad[30] = qos_tid;
338
		aad[31] = 0;
339
	} else {
340
		memset(&aad[24], 0, ETH_ALEN + IEEE80211_QOS_CTL_LEN);
341
		aad[24] = qos_tid;
342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358
	}
}


static inline void ccmp_pn2hdr(u8 *hdr, u8 *pn, int key_id)
{
	hdr[0] = pn[5];
	hdr[1] = pn[4];
	hdr[2] = 0;
	hdr[3] = 0x20 | (key_id << 6);
	hdr[4] = pn[3];
	hdr[5] = pn[2];
	hdr[6] = pn[1];
	hdr[7] = pn[0];
}


J
Johannes Berg 已提交
359
static inline void ccmp_hdr2pn(u8 *pn, u8 *hdr)
360 361 362 363 364 365 366 367 368 369
{
	pn[0] = hdr[7];
	pn[1] = hdr[6];
	pn[2] = hdr[5];
	pn[3] = hdr[4];
	pn[4] = hdr[1];
	pn[5] = hdr[0];
}


370
static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
371 372 373
{
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
	struct ieee80211_key *key = tx->key;
374
	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
375
	int hdrlen, len, tail;
376
	u8 *pos, *pn;
377 378
	int i;

379 380 381 382 383 384
	if (info->control.hw_key &&
	    !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV)) {
		/*
		 * hwaccel has no need for preallocated room for CCMP
		 * header or MIC fields
		 */
385
		return 0;
386 387
	}

388
	hdrlen = ieee80211_hdrlen(hdr->frame_control);
389 390
	len = skb->len - hdrlen;

391
	if (info->control.hw_key)
392
		tail = 0;
J
Johannes Berg 已提交
393
	else
394 395 396 397 398
		tail = CCMP_MIC_LEN;

	if (WARN_ON(skb_tailroom(skb) < tail ||
		    skb_headroom(skb) < CCMP_HDR_LEN))
		return -1;
399 400 401 402 403 404 405 406 407 408 409 410 411 412 413

	pos = skb_push(skb, CCMP_HDR_LEN);
	memmove(pos, pos + CCMP_HDR_LEN, hdrlen);
	hdr = (struct ieee80211_hdr *) pos;
	pos += hdrlen;

	/* PN = PN + 1 */
	pn = key->u.ccmp.tx_pn;

	for (i = CCMP_PN_LEN - 1; i >= 0; i--) {
		pn[i]++;
		if (pn[i])
			break;
	}

414
	ccmp_pn2hdr(pos, pn, key->conf.keyidx);
415

416 417
	/* hwaccel - with software CCMP header */
	if (info->control.hw_key)
418 419 420
		return 0;

	pos += CCMP_HDR_LEN;
421 422
	ccmp_special_blocks(skb, pn, key->u.ccmp.tx_crypto_buf, 0);
	ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, key->u.ccmp.tx_crypto_buf, pos, len,
423 424 425 426 427 428
				  pos, skb_put(skb, CCMP_MIC_LEN));

	return 0;
}


429
ieee80211_tx_result
430
ieee80211_crypto_ccmp_encrypt(struct ieee80211_tx_data *tx)
431 432 433
{
	struct sk_buff *skb = tx->skb;

434
	ieee80211_tx_set_protected(tx);
435

J
Johannes Berg 已提交
436 437 438 439
	do {
		if (ccmp_encrypt_skb(tx, skb) < 0)
			return TX_DROP;
	} while ((skb = skb->next));
440

441
	return TX_CONTINUE;
442 443 444
}


445
ieee80211_rx_result
446
ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx)
447
{
448
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
449 450 451
	int hdrlen;
	struct ieee80211_key *key = rx->key;
	struct sk_buff *skb = rx->skb;
J
Johannes Berg 已提交
452
	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
453 454
	u8 pn[CCMP_PN_LEN];
	int data_len;
455
	int queue;
456

457
	hdrlen = ieee80211_hdrlen(hdr->frame_control);
458

459 460
	if (!ieee80211_is_data(hdr->frame_control) &&
	    !ieee80211_is_robust_mgmt_frame(hdr))
461
		return RX_CONTINUE;
462 463 464

	data_len = skb->len - hdrlen - CCMP_HDR_LEN - CCMP_MIC_LEN;
	if (!rx->sta || data_len < 0)
J
Johannes Berg 已提交
465
		return RX_DROP_UNUSABLE;
466

J
Johannes Berg 已提交
467
	ccmp_hdr2pn(pn, skb->data + hdrlen);
468

469 470 471 472
	queue = ieee80211_is_mgmt(hdr->frame_control) ?
		NUM_RX_DATA_QUEUES : rx->queue;

	if (memcmp(pn, key->u.ccmp.rx_pn[queue], CCMP_PN_LEN) <= 0) {
473
		key->u.ccmp.replays++;
J
Johannes Berg 已提交
474
		return RX_DROP_UNUSABLE;
475 476
	}

J
Johannes Berg 已提交
477
	if (!(status->flag & RX_FLAG_DECRYPTED)) {
478
		/* hardware didn't decrypt/verify MIC */
479
		ccmp_special_blocks(skb, pn, key->u.ccmp.rx_crypto_buf, 1);
480 481

		if (ieee80211_aes_ccm_decrypt(
482
			    key->u.ccmp.tfm, key->u.ccmp.rx_crypto_buf,
483 484
			    skb->data + hdrlen + CCMP_HDR_LEN, data_len,
			    skb->data + skb->len - CCMP_MIC_LEN,
J
Johannes Berg 已提交
485
			    skb->data + hdrlen + CCMP_HDR_LEN))
J
Johannes Berg 已提交
486
			return RX_DROP_UNUSABLE;
487 488
	}

489
	memcpy(key->u.ccmp.rx_pn[queue], pn, CCMP_PN_LEN);
490 491 492 493 494 495

	/* Remove CCMP header and MIC */
	skb_trim(skb, skb->len - CCMP_MIC_LEN);
	memmove(skb->data + CCMP_HDR_LEN, skb->data, hdrlen);
	skb_pull(skb, CCMP_HDR_LEN);

496
	return RX_CONTINUE;
497
}
498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533


static void bip_aad(struct sk_buff *skb, u8 *aad)
{
	/* BIP AAD: FC(masked) || A1 || A2 || A3 */

	/* FC type/subtype */
	aad[0] = skb->data[0];
	/* Mask FC Retry, PwrMgt, MoreData flags to zero */
	aad[1] = skb->data[1] & ~(BIT(4) | BIT(5) | BIT(6));
	/* A1 || A2 || A3 */
	memcpy(aad + 2, skb->data + 4, 3 * ETH_ALEN);
}


static inline void bip_ipn_swap(u8 *d, const u8 *s)
{
	*d++ = s[5];
	*d++ = s[4];
	*d++ = s[3];
	*d++ = s[2];
	*d++ = s[1];
	*d = s[0];
}


ieee80211_tx_result
ieee80211_crypto_aes_cmac_encrypt(struct ieee80211_tx_data *tx)
{
	struct sk_buff *skb = tx->skb;
	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
	struct ieee80211_key *key = tx->key;
	struct ieee80211_mmie *mmie;
	u8 *pn, aad[20];
	int i;

534
	if (info->control.hw_key)
535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570
		return 0;

	if (WARN_ON(skb_tailroom(skb) < sizeof(*mmie)))
		return TX_DROP;

	mmie = (struct ieee80211_mmie *) skb_put(skb, sizeof(*mmie));
	mmie->element_id = WLAN_EID_MMIE;
	mmie->length = sizeof(*mmie) - 2;
	mmie->key_id = cpu_to_le16(key->conf.keyidx);

	/* PN = PN + 1 */
	pn = key->u.aes_cmac.tx_pn;

	for (i = sizeof(key->u.aes_cmac.tx_pn) - 1; i >= 0; i--) {
		pn[i]++;
		if (pn[i])
			break;
	}
	bip_ipn_swap(mmie->sequence_number, pn);

	bip_aad(skb, aad);

	/*
	 * MIC = AES-128-CMAC(IGTK, AAD || Management Frame Body || MMIE, 64)
	 */
	ieee80211_aes_cmac(key->u.aes_cmac.tfm, key->u.aes_cmac.tx_crypto_buf,
			   aad, skb->data + 24, skb->len - 24, mmie->mic);

	return TX_CONTINUE;
}


ieee80211_rx_result
ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx)
{
	struct sk_buff *skb = rx->skb;
J
Johannes Berg 已提交
571
	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595
	struct ieee80211_key *key = rx->key;
	struct ieee80211_mmie *mmie;
	u8 aad[20], mic[8], ipn[6];
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;

	if (!ieee80211_is_mgmt(hdr->frame_control))
		return RX_CONTINUE;

	if (skb->len < 24 + sizeof(*mmie))
		return RX_DROP_UNUSABLE;

	mmie = (struct ieee80211_mmie *)
		(skb->data + skb->len - sizeof(*mmie));
	if (mmie->element_id != WLAN_EID_MMIE ||
	    mmie->length != sizeof(*mmie) - 2)
		return RX_DROP_UNUSABLE; /* Invalid MMIE */

	bip_ipn_swap(ipn, mmie->sequence_number);

	if (memcmp(ipn, key->u.aes_cmac.rx_pn, 6) <= 0) {
		key->u.aes_cmac.replays++;
		return RX_DROP_UNUSABLE;
	}

J
Johannes Berg 已提交
596
	if (!(status->flag & RX_FLAG_DECRYPTED)) {
597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614
		/* hardware didn't decrypt/verify MIC */
		bip_aad(skb, aad);
		ieee80211_aes_cmac(key->u.aes_cmac.tfm,
				   key->u.aes_cmac.rx_crypto_buf, aad,
				   skb->data + 24, skb->len - 24, mic);
		if (memcmp(mic, mmie->mic, sizeof(mmie->mic)) != 0) {
			key->u.aes_cmac.icverrors++;
			return RX_DROP_UNUSABLE;
		}
	}

	memcpy(key->u.aes_cmac.rx_pn, ipn, 6);

	/* Remove MMIE */
	skb_trim(skb, skb->len - sizeof(*mmie));

	return RX_CONTINUE;
}