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

#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;
	__le16 fc;

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

	hdrlen = ieee80211_hdrlen(fc);

	*sa = ieee80211_get_SA(hdr);
	*da = ieee80211_get_DA(hdr);

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

	if (ieee80211_is_data_qos(fc))
		*qos_tid = (*ieee80211_get_qos_ctl(hdr) & 0x0f) | 0x80;
	else
		*qos_tid = 0;

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


ieee80211_tx_result
ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx)
{
	u8 *data, *sa, *da, *key, *mic, qos_tid;
	size_t data_len;
	u16 fc;
	struct sk_buff *skb = tx->skb;
	int authenticator;
	int wpa_test = 0;
	int tail;

	fc = tx->fc;

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

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

	if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) &&
	    !(tx->flags & IEEE80211_TX_FRAGMENTED) &&
	    !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) &&
	    !wpa_test) {
		/* hwaccel - with no need for preallocated room for Michael MIC
		 */
		return TX_CONTINUE;
	}

	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;

#if 0
	authenticator = fc & IEEE80211_FCTL_FROMDS; /* FIX */
#else
	authenticator = 1;
#endif
	key = &tx->key->conf.key[authenticator ? ALG_TKIP_TEMP_AUTH_TX_MIC_KEY :
				 ALG_TKIP_TEMP_AUTH_RX_MIC_KEY];
	mic = skb_put(skb, MICHAEL_MIC_LEN);
	michael_mic(key, da, sa, qos_tid & 0x0f, data, data_len, mic);

	return TX_CONTINUE;
}


ieee80211_rx_result
ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx)
{
	u8 *data, *sa, *da, *key = NULL, qos_tid;
	size_t data_len;
	u16 fc;
	u8 mic[MICHAEL_MIC_LEN];
	struct sk_buff *skb = rx->skb;
	int authenticator = 1, wpa_test = 0;
	DECLARE_MAC_BUF(mac);

	fc = rx->fc;

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

	if (!rx->key || rx->key->conf.alg != ALG_TKIP ||
	    !(rx->fc & IEEE80211_FCTL_PROTECTED) || !WLAN_FC_DATA_PRESENT(fc))
		return RX_CONTINUE;

	if (ieee80211_get_hdr_info(skb, &sa, &da, &qos_tid, &data, &data_len)
	    || data_len < MICHAEL_MIC_LEN)
		return RX_DROP_UNUSABLE;

	data_len -= MICHAEL_MIC_LEN;

#if 0
	authenticator = fc & IEEE80211_FCTL_TODS; /* FIX */
#else
	authenticator = 1;
#endif
	key = &rx->key->conf.key[authenticator ? ALG_TKIP_TEMP_AUTH_RX_MIC_KEY :
				 ALG_TKIP_TEMP_AUTH_TX_MIC_KEY];
	michael_mic(key, da, sa, qos_tid & 0x0f, data, data_len, mic);
	if (memcmp(mic, data + data_len, MICHAEL_MIC_LEN) != 0 || wpa_test) {
		if (!(rx->flags & IEEE80211_RX_RA_MATCH))
			return RX_DROP_UNUSABLE;

		printk(KERN_DEBUG "%s: invalid Michael MIC in data frame from "
		       "%s\n", rx->dev->name, print_mac(mac, sa));

		mac80211_ev_michael_mic_failure(rx->dev, rx->key->conf.keyidx,
						(void *) skb->data);
		return RX_DROP_UNUSABLE;
	}

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

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

	return RX_CONTINUE;
}


static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
{
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
	struct ieee80211_key *key = tx->key;
	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
	unsigned int hdrlen;
	int len, tail;
	u8 *pos;

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

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

	if (tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)
		tail = 0;
	else
		tail = TKIP_ICV_LEN;

	if (WARN_ON(skb_tailroom(skb) < tail ||
		    skb_headroom(skb) < TKIP_IV_LEN))
		return -1;

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

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

	if (tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) {
		hdr = (struct ieee80211_hdr *)skb->data;

		/* hwaccel - with preallocated room for IV */
		ieee80211_tkip_add_iv(pos, key,
				      (u8) (key->u.tkip.tx.iv16 >> 8),
				      (u8) (((key->u.tkip.tx.iv16 >> 8) | 0x20) &
					    0x7f),
				      (u8) key->u.tkip.tx.iv16);

		info->control.hw_key = &tx->key->conf;
		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;
}


ieee80211_tx_result
ieee80211_crypto_tkip_encrypt(struct ieee80211_tx_data *tx)
{
	struct sk_buff *skb = tx->skb;

	ieee80211_tx_set_protected(tx);

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

	if (tx->extra_frag) {
		int i;
		for (i = 0; i < tx->num_extra_frag; i++) {
			if (tkip_encrypt_skb(tx, tx->extra_frag[i]) < 0)
				return TX_DROP;
		}
	}

	return TX_CONTINUE;
}


ieee80211_rx_result
ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx)
{
	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;
	DECLARE_MAC_BUF(mac);

	hdrlen = ieee80211_hdrlen(hdr->frame_control);

	if ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA)
		return RX_CONTINUE;

	if (!rx->sta || skb->len - hdrlen < 12)
		return RX_DROP_UNUSABLE;

	if (rx->status->flag & RX_FLAG_DECRYPTED) {
		if (rx->status->flag & RX_FLAG_IV_STRIPPED) {
			/*
			 * Hardware took care of all processing, including
			 * replay protection, and stripped the ICV/IV so
			 * we cannot do any checks here.
			 */
			return RX_CONTINUE;
		}

		/* 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,
					  hdr->addr1, hwaccel, rx->queue,
					  &rx->tkip_iv32,
					  &rx->tkip_iv16);
	if (res != TKIP_DECRYPT_OK || wpa_test) {
#ifdef CONFIG_MAC80211_DEBUG
		if (net_ratelimit())
			printk(KERN_DEBUG "%s: TKIP decrypt failed for RX "
			       "frame from %s (res=%d)\n", rx->dev->name,
			       print_mac(mac, rx->sta->addr), res);
#endif /* CONFIG_MAC80211_DEBUG */
		return RX_DROP_UNUSABLE;
	}

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

	return RX_CONTINUE;
}


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


static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
{
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
	struct ieee80211_key *key = tx->key;
	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
	int hdrlen, len, tail;
	u8 *pos, *pn, *b_0, *aad, *scratch;
	int i;

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

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

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

	if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)
		tail = 0;
	else
		tail = CCMP_MIC_LEN;

	if (WARN_ON(skb_tailroom(skb) < tail ||
		    skb_headroom(skb) < CCMP_HDR_LEN))
		return -1;

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

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

	if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) {
		/* hwaccel - with preallocated room for CCMP header */
		info->control.hw_key = &tx->key->conf;
		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;
}


ieee80211_tx_result
ieee80211_crypto_ccmp_encrypt(struct ieee80211_tx_data *tx)
{
	struct sk_buff *skb = tx->skb;

	ieee80211_tx_set_protected(tx);

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

	if (tx->extra_frag) {
		int i;
		for (i = 0; i < tx->num_extra_frag; i++) {
			if (ccmp_encrypt_skb(tx, tx->extra_frag[i]) < 0)
				return TX_DROP;
		}
	}

	return TX_CONTINUE;
}


ieee80211_rx_result
ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx)
{
	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;
	DECLARE_MAC_BUF(mac);

	hdrlen = ieee80211_hdrlen(hdr->frame_control);

	if ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA)
		return RX_CONTINUE;

	data_len = skb->len - hdrlen - CCMP_HDR_LEN - CCMP_MIC_LEN;
	if (!rx->sta || data_len < 0)
		return RX_DROP_UNUSABLE;

	if ((rx->status->flag & RX_FLAG_DECRYPTED) &&
	    (rx->status->flag & RX_FLAG_IV_STRIPPED))
		return RX_CONTINUE;

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

	if (memcmp(pn, key->u.ccmp.rx_pn[rx->queue], CCMP_PN_LEN) <= 0) {
#ifdef CONFIG_MAC80211_DEBUG
		u8 *ppn = key->u.ccmp.rx_pn[rx->queue];

		printk(KERN_DEBUG "%s: CCMP replay detected for RX frame from "
		       "%s (RX PN %02x%02x%02x%02x%02x%02x <= prev. PN "
		       "%02x%02x%02x%02x%02x%02x)\n", rx->dev->name,
		       print_mac(mac, rx->sta->addr),
		       pn[0], pn[1], pn[2], pn[3], pn[4], pn[5],
		       ppn[0], ppn[1], ppn[2], ppn[3], ppn[4], ppn[5]);
#endif /* CONFIG_MAC80211_DEBUG */
		key->u.ccmp.replays++;
		return RX_DROP_UNUSABLE;
	}

	if (!(rx->status->flag & RX_FLAG_DECRYPTED)) {
		/* hardware didn't decrypt/verify MIC */
		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)) {
#ifdef CONFIG_MAC80211_DEBUG
			if (net_ratelimit())
				printk(KERN_DEBUG "%s: CCMP decrypt failed "
				       "for RX frame from %s\n", rx->dev->name,
				       print_mac(mac, rx->sta->addr));
#endif /* CONFIG_MAC80211_DEBUG */
			return RX_DROP_UNUSABLE;
		}
	}

	memcpy(key->u.ccmp.rx_pn[rx->queue], pn, CCMP_PN_LEN);

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

	return RX_CONTINUE;
}
