wpa.c 13.0 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14
/*
 * Copyright 2002-2004, Instant802 Networks, Inc.
 *
 * 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/slab.h>
#include <linux/skbuff.h>
#include <linux/compiler.h>
#include <net/mac80211.h>
J
Johannes Berg 已提交
15

16 17 18 19 20 21 22 23 24 25 26
#include "ieee80211_i.h"
#include "michael.h"
#include "tkip.h"
#include "aes_ccm.h"
#include "wpa.h"

static int ieee80211_get_hdr_info(const struct sk_buff *skb, u8 **sa, u8 **da,
				  u8 *qos_tid, u8 **data, size_t *data_len)
{
	struct ieee80211_hdr *hdr;
	size_t hdrlen;
27
	__le16 fc;
28

29 30
	hdr = (struct ieee80211_hdr *)skb->data;
	fc = hdr->frame_control;
31

32 33 34 35
	hdrlen = ieee80211_hdrlen(fc);

	*sa = ieee80211_get_SA(hdr);
	*da = ieee80211_get_DA(hdr);
36 37 38 39

	*data = skb->data + hdrlen;
	*data_len = skb->len - hdrlen;

40 41 42
	if (ieee80211_is_data_qos(fc))
		*qos_tid = (*ieee80211_get_qos_ctl(hdr) & 0x0f) | 0x80;
	else
43 44 45 46 47 48
		*qos_tid = 0;

	return skb->len < hdrlen ? -1 : 0;
}


49
ieee80211_tx_result
50
ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx)
51
{
52
	u8 *data, *sa, *da, *key, *mic, qos_tid, key_offset;
53 54 55 56 57
	size_t data_len;
	u16 fc;
	struct sk_buff *skb = tx->skb;
	int authenticator;
	int wpa_test = 0;
58
	int tail;
59 60 61

	fc = tx->fc;

62
	if (!tx->key || tx->key->conf.alg != ALG_TKIP || skb->len < 24 ||
63
	    !WLAN_FC_DATA_PRESENT(fc))
64
		return TX_CONTINUE;
65 66

	if (ieee80211_get_hdr_info(skb, &sa, &da, &qos_tid, &data, &data_len))
67
		return TX_DROP;
68

J
Johannes Berg 已提交
69
	if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) &&
70
	    !(tx->flags & IEEE80211_TX_FRAGMENTED) &&
71
	    !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) &&
72 73 74
	    !wpa_test) {
		/* hwaccel - with no need for preallocated room for Michael MIC
		 */
75
		return TX_CONTINUE;
76 77
	}

78 79 80 81 82 83 84
	tail = MICHAEL_MIC_LEN;
	if (!(tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE))
		tail += TKIP_ICV_LEN;

	if (WARN_ON(skb_tailroom(skb) < tail ||
		    skb_headroom(skb) < TKIP_IV_LEN))
		return TX_DROP;
85 86 87 88 89 90

#if 0
	authenticator = fc & IEEE80211_FCTL_FROMDS; /* FIX */
#else
	authenticator = 1;
#endif
91 92 93 94 95 96
	/* At this point we know we're using ALG_TKIP. To get the MIC key
	 * we now will rely on the offset from the ieee80211_key_conf::key */
	key_offset = authenticator ?
		NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY :
		NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY;
	key = &tx->key->conf.key[key_offset];
97 98 99
	mic = skb_put(skb, MICHAEL_MIC_LEN);
	michael_mic(key, da, sa, qos_tid & 0x0f, data, data_len, mic);

100
	return TX_CONTINUE;
101 102 103
}


104
ieee80211_rx_result
105
ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx)
106
{
107
	u8 *data, *sa, *da, *key = NULL, qos_tid, key_offset;
108 109 110 111 112
	size_t data_len;
	u16 fc;
	u8 mic[MICHAEL_MIC_LEN];
	struct sk_buff *skb = rx->skb;
	int authenticator = 1, wpa_test = 0;
113
	DECLARE_MAC_BUF(mac);
114 115 116

	fc = rx->fc;

117 118 119
	/*
	 * No way to verify the MIC if the hardware stripped it
	 */
120
	if (rx->status->flag & RX_FLAG_MMIC_STRIPPED)
121
		return RX_CONTINUE;
122

123
	if (!rx->key || rx->key->conf.alg != ALG_TKIP ||
124
	    !(rx->fc & IEEE80211_FCTL_PROTECTED) || !WLAN_FC_DATA_PRESENT(fc))
125
		return RX_CONTINUE;
126 127 128

	if (ieee80211_get_hdr_info(skb, &sa, &da, &qos_tid, &data, &data_len)
	    || data_len < MICHAEL_MIC_LEN)
J
Johannes Berg 已提交
129
		return RX_DROP_UNUSABLE;
130 131 132 133 134 135 136 137

	data_len -= MICHAEL_MIC_LEN;

#if 0
	authenticator = fc & IEEE80211_FCTL_TODS; /* FIX */
#else
	authenticator = 1;
#endif
138 139 140 141 142 143
	/* At this point we know we're using ALG_TKIP. To get the MIC key
	 * we now will rely on the offset from the ieee80211_key_conf::key */
	key_offset = authenticator ?
		NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY :
		NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY;
	key = &rx->key->conf.key[key_offset];
144 145
	michael_mic(key, da, sa, qos_tid & 0x0f, data, data_len, mic);
	if (memcmp(mic, data + data_len, MICHAEL_MIC_LEN) != 0 || wpa_test) {
146
		if (!(rx->flags & IEEE80211_RX_RA_MATCH))
J
Johannes Berg 已提交
147
			return RX_DROP_UNUSABLE;
148

149
		mac80211_ev_michael_mic_failure(rx->dev, rx->key->conf.keyidx,
J
Johannes Berg 已提交
150
						(void *) skb->data);
J
Johannes Berg 已提交
151
		return RX_DROP_UNUSABLE;
152 153 154 155 156
	}

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

157
	/* update IV in key information to be able to detect replays */
158 159
	rx->key->u.tkip.rx[rx->queue].iv32 = rx->tkip_iv32;
	rx->key->u.tkip.rx[rx->queue].iv16 = rx->tkip_iv16;
160

161
	return RX_CONTINUE;
162 163 164
}


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

174 175 176 177 178 179 180
	info->control.icv_len = TKIP_ICV_LEN;
	info->control.iv_len = TKIP_IV_LEN;

	if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) &&
	    !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) {
		/* hwaccel - with no need for preallocated room for IV/ICV */
		info->control.hw_key = &tx->key->conf;
181
		return 0;
182 183
	}

184
	hdrlen = ieee80211_hdrlen(hdr->frame_control);
185 186
	len = skb->len - hdrlen;

J
Johannes Berg 已提交
187
	if (tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)
188
		tail = 0;
J
Johannes Berg 已提交
189
	else
190 191 192 193 194
		tail = TKIP_ICV_LEN;

	if (WARN_ON(skb_tailroom(skb) < tail ||
		    skb_headroom(skb) < TKIP_IV_LEN))
		return -1;
195 196 197 198 199 200

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

	/* Increase IV for the frame */
201 202 203
	key->u.tkip.tx.iv16++;
	if (key->u.tkip.tx.iv16 == 0)
		key->u.tkip.tx.iv32++;
204

J
Johannes Berg 已提交
205
	if (tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) {
206
		/* hwaccel - with preallocated room for IV */
207
		ieee80211_tkip_add_iv(pos, key, key->u.tkip.tx.iv16);
208

209
		info->control.hw_key = &tx->key->conf;
210 211 212 213 214 215 216 217 218 219 220 221 222
		return 0;
	}

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

	hdr = (struct ieee80211_hdr *) skb->data;
	ieee80211_tkip_encrypt_data(tx->local->wep_tx_tfm,
				    key, pos, len, hdr->addr2);
	return 0;
}


223
ieee80211_tx_result
224
ieee80211_crypto_tkip_encrypt(struct ieee80211_tx_data *tx)
225 226 227
{
	struct sk_buff *skb = tx->skb;

228
	ieee80211_tx_set_protected(tx);
229

230
	if (tkip_encrypt_skb(tx, skb) < 0)
231
		return TX_DROP;
232

233
	if (tx->extra_frag) {
234
		int i;
235
		for (i = 0; i < tx->num_extra_frag; i++) {
236
			if (tkip_encrypt_skb(tx, tx->extra_frag[i]) < 0)
237
				return TX_DROP;
238 239 240
		}
	}

241
	return TX_CONTINUE;
242 243 244
}


245
ieee80211_rx_result
246
ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx)
247 248 249 250 251
{
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data;
	int hdrlen, res, hwaccel = 0, wpa_test = 0;
	struct ieee80211_key *key = rx->key;
	struct sk_buff *skb = rx->skb;
252
	DECLARE_MAC_BUF(mac);
253

254
	hdrlen = ieee80211_hdrlen(hdr->frame_control);
255

256
	if ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA)
257
		return RX_CONTINUE;
258 259

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

262 263
	if (rx->status->flag & RX_FLAG_DECRYPTED) {
		if (rx->status->flag & RX_FLAG_IV_STRIPPED) {
264 265 266 267 268
			/*
			 * Hardware took care of all processing, including
			 * replay protection, and stripped the ICV/IV so
			 * we cannot do any checks here.
			 */
269
			return RX_CONTINUE;
270 271 272 273 274 275 276 277 278
		}

		/* let TKIP code verify IV, but skip decryption */
		hwaccel = 1;
	}

	res = ieee80211_tkip_decrypt_data(rx->local->wep_rx_tfm,
					  key, skb->data + hdrlen,
					  skb->len - hdrlen, rx->sta->addr,
279
					  hdr->addr1, hwaccel, rx->queue,
280 281
					  &rx->tkip_iv32,
					  &rx->tkip_iv16);
282
	if (res != TKIP_DECRYPT_OK || wpa_test)
J
Johannes Berg 已提交
283
		return RX_DROP_UNUSABLE;
284 285 286 287 288 289 290 291

	/* 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);

292
	return RX_CONTINUE;
293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388
}


static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *b_0, u8 *aad,
				int encrypted)
{
	u16 fc;
	int a4_included, qos_included;
	u8 qos_tid, *fc_pos, *data, *sa, *da;
	int len_a;
	size_t data_len;
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;

	fc_pos = (u8 *) &hdr->frame_control;
	fc = fc_pos[0] ^ (fc_pos[1] << 8);
	a4_included = (fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
		(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS);

	ieee80211_get_hdr_info(skb, &sa, &da, &qos_tid, &data, &data_len);
	data_len -= CCMP_HDR_LEN + (encrypted ? CCMP_MIC_LEN : 0);
	if (qos_tid & 0x80) {
		qos_included = 1;
		qos_tid &= 0x0f;
	} else
		qos_included = 0;
	/* First block, b_0 */

	b_0[0] = 0x59; /* flags: Adata: 1, M: 011, L: 001 */
	/* Nonce: QoS Priority | A2 | PN */
	b_0[1] = qos_tid;
	memcpy(&b_0[2], hdr->addr2, 6);
	memcpy(&b_0[8], pn, CCMP_PN_LEN);
	/* l(m) */
	b_0[14] = (data_len >> 8) & 0xff;
	b_0[15] = data_len & 0xff;


	/* AAD (extra authenticate-only data) / masked 802.11 header
	 * FC | A1 | A2 | A3 | SC | [A4] | [QC] */

	len_a = a4_included ? 28 : 22;
	if (qos_included)
		len_a += 2;

	aad[0] = 0; /* (len_a >> 8) & 0xff; */
	aad[1] = len_a & 0xff;
	/* Mask FC: zero subtype b4 b5 b6 */
	aad[2] = fc_pos[0] & ~(BIT(4) | BIT(5) | BIT(6));
	/* Retry, PwrMgt, MoreData; set Protected */
	aad[3] = (fc_pos[1] & ~(BIT(3) | BIT(4) | BIT(5))) | BIT(6);
	memcpy(&aad[4], &hdr->addr1, 18);

	/* Mask Seq#, leave Frag# */
	aad[22] = *((u8 *) &hdr->seq_ctrl) & 0x0f;
	aad[23] = 0;
	if (a4_included) {
		memcpy(&aad[24], hdr->addr4, 6);
		aad[30] = 0;
		aad[31] = 0;
	} else
		memset(&aad[24], 0, 8);
	if (qos_included) {
		u8 *dpos = &aad[a4_included ? 30 : 24];

		/* Mask QoS Control field */
		dpos[0] = qos_tid;
		dpos[1] = 0;
	}
}


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];
}


static inline int ccmp_hdr2pn(u8 *pn, u8 *hdr)
{
	pn[0] = hdr[7];
	pn[1] = hdr[6];
	pn[2] = hdr[5];
	pn[3] = hdr[4];
	pn[4] = hdr[1];
	pn[5] = hdr[0];
	return (hdr[3] >> 6) & 0x03;
}


389
static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
390 391 392
{
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
	struct ieee80211_key *key = tx->key;
393
	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
394
	int hdrlen, len, tail;
395 396 397
	u8 *pos, *pn, *b_0, *aad, *scratch;
	int i;

398 399 400 401 402 403 404 405
	info->control.icv_len = CCMP_MIC_LEN;
	info->control.iv_len = CCMP_HDR_LEN;

	if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) &&
	    !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) {
		/* hwaccel - with no need for preallocated room for CCMP "
		 * header or MIC fields */
		info->control.hw_key = &tx->key->conf;
406
		return 0;
407 408
	}

409 410 411 412
	scratch = key->u.ccmp.tx_crypto_buf;
	b_0 = scratch + 3 * AES_BLOCK_LEN;
	aad = scratch + 4 * AES_BLOCK_LEN;

413
	hdrlen = ieee80211_hdrlen(hdr->frame_control);
414 415
	len = skb->len - hdrlen;

J
Johannes Berg 已提交
416
	if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)
417
		tail = 0;
J
Johannes Berg 已提交
418
	else
419 420 421 422 423
		tail = CCMP_MIC_LEN;

	if (WARN_ON(skb_tailroom(skb) < tail ||
		    skb_headroom(skb) < CCMP_HDR_LEN))
		return -1;
424 425 426 427 428 429 430 431 432 433 434 435 436 437 438

	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;
	}

439
	ccmp_pn2hdr(pos, pn, key->conf.keyidx);
440

J
Johannes Berg 已提交
441
	if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) {
442
		/* hwaccel - with preallocated room for CCMP header */
443
		info->control.hw_key = &tx->key->conf;
444 445 446 447 448 449 450 451 452 453 454 455
		return 0;
	}

	pos += CCMP_HDR_LEN;
	ccmp_special_blocks(skb, pn, b_0, aad, 0);
	ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, scratch, b_0, aad, pos, len,
				  pos, skb_put(skb, CCMP_MIC_LEN));

	return 0;
}


456
ieee80211_tx_result
457
ieee80211_crypto_ccmp_encrypt(struct ieee80211_tx_data *tx)
458 459 460
{
	struct sk_buff *skb = tx->skb;

461
	ieee80211_tx_set_protected(tx);
462

463
	if (ccmp_encrypt_skb(tx, skb) < 0)
464
		return TX_DROP;
465

466
	if (tx->extra_frag) {
467
		int i;
468
		for (i = 0; i < tx->num_extra_frag; i++) {
469
			if (ccmp_encrypt_skb(tx, tx->extra_frag[i]) < 0)
470
				return TX_DROP;
471 472 473
		}
	}

474
	return TX_CONTINUE;
475 476 477
}


478
ieee80211_rx_result
479
ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx)
480 481 482 483 484 485 486
{
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data;
	int hdrlen;
	struct ieee80211_key *key = rx->key;
	struct sk_buff *skb = rx->skb;
	u8 pn[CCMP_PN_LEN];
	int data_len;
487
	DECLARE_MAC_BUF(mac);
488

489
	hdrlen = ieee80211_hdrlen(hdr->frame_control);
490

491
	if ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA)
492
		return RX_CONTINUE;
493 494 495

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

498 499
	if ((rx->status->flag & RX_FLAG_DECRYPTED) &&
	    (rx->status->flag & RX_FLAG_IV_STRIPPED))
500
		return RX_CONTINUE;
501 502 503

	(void) ccmp_hdr2pn(pn, skb->data + hdrlen);

504
	if (memcmp(pn, key->u.ccmp.rx_pn[rx->queue], CCMP_PN_LEN) <= 0) {
505
		key->u.ccmp.replays++;
J
Johannes Berg 已提交
506
		return RX_DROP_UNUSABLE;
507 508
	}

509
	if (!(rx->status->flag & RX_FLAG_DECRYPTED)) {
510
		/* hardware didn't decrypt/verify MIC */
511 512 513 514 515 516 517 518 519 520 521 522 523
		u8 *scratch, *b_0, *aad;

		scratch = key->u.ccmp.rx_crypto_buf;
		b_0 = scratch + 3 * AES_BLOCK_LEN;
		aad = scratch + 4 * AES_BLOCK_LEN;

		ccmp_special_blocks(skb, pn, b_0, aad, 1);

		if (ieee80211_aes_ccm_decrypt(
			    key->u.ccmp.tfm, scratch, b_0, aad,
			    skb->data + hdrlen + CCMP_HDR_LEN, data_len,
			    skb->data + skb->len - CCMP_MIC_LEN,
			    skb->data + hdrlen + CCMP_HDR_LEN)) {
J
Johannes Berg 已提交
524
			return RX_DROP_UNUSABLE;
525 526 527
		}
	}

528
	memcpy(key->u.ccmp.rx_pn[rx->queue], pn, CCMP_PN_LEN);
529 530 531 532 533 534

	/* 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);

535
	return RX_CONTINUE;
536
}