/*
 * Copyright 2002-2004, Instant802 Networks, Inc.
 * Copyright 2005, Devicescape Software, 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/kernel.h>
#include <linux/types.h>
#include <linux/netdevice.h>

#include <net/mac80211.h>
#include "key.h"
#include "tkip.h"
#include "wep.h"


/* TKIP key mixing functions */


#define PHASE1_LOOP_COUNT 8


/* 2-byte by 2-byte subset of the full AES S-box table; second part of this
 * table is identical to first part but byte-swapped */
static const u16 tkip_sbox[256] =
{
	0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154,
	0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A,
	0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B,
	0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B,
	0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F,
	0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F,
	0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5,
	0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F,
	0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB,
	0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397,
	0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED,
	0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A,
	0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194,
	0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3,
	0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104,
	0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D,
	0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39,
	0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695,
	0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83,
	0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76,
	0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4,
	0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B,
	0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0,
	0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018,
	0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751,
	0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85,
	0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12,
	0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9,
	0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7,
	0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A,
	0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8,
	0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A,
};


static inline u16 Mk16(u8 x, u8 y)
{
	return ((u16) x << 8) | (u16) y;
}


static inline u8 Hi8(u16 v)
{
	return v >> 8;
}


static inline u8 Lo8(u16 v)
{
	return v & 0xff;
}


static inline u16 Hi16(u32 v)
{
	return v >> 16;
}


static inline u16 Lo16(u32 v)
{
	return v & 0xffff;
}


static inline u16 RotR1(u16 v)
{
	return (v >> 1) | ((v & 0x0001) << 15);
}


static inline u16 tkip_S(u16 val)
{
	u16 a = tkip_sbox[Hi8(val)];

	return tkip_sbox[Lo8(val)] ^ Hi8(a) ^ (Lo8(a) << 8);
}



/* P1K := Phase1(TA, TK, TSC)
 * TA = transmitter address (48 bits)
 * TK = dot11DefaultKeyValue or dot11KeyMappingValue (128 bits)
 * TSC = TKIP sequence counter (48 bits, only 32 msb bits used)
 * P1K: 80 bits
 */
static void tkip_mixing_phase1(const u8 *ta, const u8 *tk, u32 tsc_IV32,
			       u16 *p1k)
{
	int i, j;

	p1k[0] = Lo16(tsc_IV32);
	p1k[1] = Hi16(tsc_IV32);
	p1k[2] = Mk16(ta[1], ta[0]);
	p1k[3] = Mk16(ta[3], ta[2]);
	p1k[4] = Mk16(ta[5], ta[4]);

	for (i = 0; i < PHASE1_LOOP_COUNT; i++) {
		j = 2 * (i & 1);
		p1k[0] += tkip_S(p1k[4] ^ Mk16(tk[ 1 + j], tk[ 0 + j]));
		p1k[1] += tkip_S(p1k[0] ^ Mk16(tk[ 5 + j], tk[ 4 + j]));
		p1k[2] += tkip_S(p1k[1] ^ Mk16(tk[ 9 + j], tk[ 8 + j]));
		p1k[3] += tkip_S(p1k[2] ^ Mk16(tk[13 + j], tk[12 + j]));
		p1k[4] += tkip_S(p1k[3] ^ Mk16(tk[ 1 + j], tk[ 0 + j])) + i;
	}
}


static void tkip_mixing_phase2(const u16 *p1k, const u8 *tk, u16 tsc_IV16,
			       u8 *rc4key)
{
	u16 ppk[6];
	int i;

	ppk[0] = p1k[0];
	ppk[1] = p1k[1];
	ppk[2] = p1k[2];
	ppk[3] = p1k[3];
	ppk[4] = p1k[4];
	ppk[5] = p1k[4] + tsc_IV16;

	ppk[0] += tkip_S(ppk[5] ^ Mk16(tk[ 1], tk[ 0]));
	ppk[1] += tkip_S(ppk[0] ^ Mk16(tk[ 3], tk[ 2]));
	ppk[2] += tkip_S(ppk[1] ^ Mk16(tk[ 5], tk[ 4]));
	ppk[3] += tkip_S(ppk[2] ^ Mk16(tk[ 7], tk[ 6]));
	ppk[4] += tkip_S(ppk[3] ^ Mk16(tk[ 9], tk[ 8]));
	ppk[5] += tkip_S(ppk[4] ^ Mk16(tk[11], tk[10]));
	ppk[0] +=  RotR1(ppk[5] ^ Mk16(tk[13], tk[12]));
	ppk[1] +=  RotR1(ppk[0] ^ Mk16(tk[15], tk[14]));
	ppk[2] +=  RotR1(ppk[1]);
	ppk[3] +=  RotR1(ppk[2]);
	ppk[4] +=  RotR1(ppk[3]);
	ppk[5] +=  RotR1(ppk[4]);

	rc4key[0] = Hi8(tsc_IV16);
	rc4key[1] = (Hi8(tsc_IV16) | 0x20) & 0x7f;
	rc4key[2] = Lo8(tsc_IV16);
	rc4key[3] = Lo8((ppk[5] ^ Mk16(tk[1], tk[0])) >> 1);

	for (i = 0; i < 6; i++) {
		rc4key[4 + 2 * i] = Lo8(ppk[i]);
		rc4key[5 + 2 * i] = Hi8(ppk[i]);
	}
}


/* Add TKIP IV and Ext. IV at @pos. @iv0, @iv1, and @iv2 are the first octets
 * of the IV. Returns pointer to the octet following IVs (i.e., beginning of
 * the packet payload). */
u8 * ieee80211_tkip_add_iv(u8 *pos, struct ieee80211_key *key,
			   u8 iv0, u8 iv1, u8 iv2)
{
	*pos++ = iv0;
	*pos++ = iv1;
	*pos++ = iv2;
	*pos++ = (key->conf.keyidx << 6) | (1 << 5) /* Ext IV */;
	*pos++ = key->u.tkip.iv32 & 0xff;
	*pos++ = (key->u.tkip.iv32 >> 8) & 0xff;
	*pos++ = (key->u.tkip.iv32 >> 16) & 0xff;
	*pos++ = (key->u.tkip.iv32 >> 24) & 0xff;
	return pos;
}


void ieee80211_tkip_gen_phase1key(struct ieee80211_key *key, u8 *ta,
				  u16 *phase1key)
{
	tkip_mixing_phase1(ta, &key->conf.key[ALG_TKIP_TEMP_ENCR_KEY],
			   key->u.tkip.iv32, phase1key);
}

void ieee80211_tkip_gen_rc4key(struct ieee80211_key *key, u8 *ta,
			       u8 *rc4key)
{
	/* Calculate per-packet key */
	if (key->u.tkip.iv16 == 0 || !key->u.tkip.tx_initialized) {
		/* IV16 wrapped around - perform TKIP phase 1 */
		tkip_mixing_phase1(ta, &key->conf.key[ALG_TKIP_TEMP_ENCR_KEY],
				   key->u.tkip.iv32, key->u.tkip.p1k);
		key->u.tkip.tx_initialized = 1;
	}

	tkip_mixing_phase2(key->u.tkip.p1k,
			   &key->conf.key[ALG_TKIP_TEMP_ENCR_KEY],
			   key->u.tkip.iv16, rc4key);
}

void ieee80211_get_tkip_key(struct ieee80211_key_conf *keyconf,
			struct sk_buff *skb, enum ieee80211_tkip_key_type type,
			u8 *outkey)
{
	struct ieee80211_key *key = (struct ieee80211_key *)
			container_of(keyconf, struct ieee80211_key, conf);
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
	u8 *data = (u8 *) hdr;
	u16 fc = le16_to_cpu(hdr->frame_control);
	int hdr_len = ieee80211_get_hdrlen(fc);
	u8 *ta = hdr->addr2;
	u16 iv16;
	u32 iv32;

	iv16 = data[hdr_len] << 8;
	iv16 += data[hdr_len + 2];
	iv32 = data[hdr_len + 4] +
		(data[hdr_len + 5] >> 8) +
		(data[hdr_len + 6] >> 16) +
		(data[hdr_len + 7] >> 24);

#ifdef CONFIG_TKIP_DEBUG
	printk(KERN_DEBUG "TKIP encrypt: iv16 = 0x%04x, iv32 = 0x%08x\n",
			iv16, iv32);

	if (iv32 != key->u.tkip.iv32) {
		printk(KERN_DEBUG "skb: iv32 = 0x%08x key: iv32 = 0x%08x\n",
			iv32, key->u.tkip.iv32);
		printk(KERN_DEBUG "Wrap around of iv16 in the middle of a "
			"fragmented packet\n");
	}
#endif /* CONFIG_TKIP_DEBUG */

	/* Update the p1k only when the iv16 in the packet wraps around, this
	 * might occur after the wrap around of iv16 in the key in case of
	 * fragmented packets. */
	if (iv16 == 0 || !key->u.tkip.tx_initialized) {
		/* IV16 wrapped around - perform TKIP phase 1 */
		tkip_mixing_phase1(ta, &key->conf.key[ALG_TKIP_TEMP_ENCR_KEY],
			iv32, key->u.tkip.p1k);
		key->u.tkip.tx_initialized = 1;
	}

	if (type == IEEE80211_TKIP_P1_KEY) {
		memcpy(outkey, key->u.tkip.p1k, sizeof(u16) * 5);
		return;
	}

	tkip_mixing_phase2(key->u.tkip.p1k,
		&key->conf.key[ALG_TKIP_TEMP_ENCR_KEY],	iv16, outkey);
}
EXPORT_SYMBOL(ieee80211_get_tkip_key);

/* Encrypt packet payload with TKIP using @key. @pos is a pointer to the
 * beginning of the buffer containing payload. This payload must include
 * headroom of eight octets for IV and Ext. IV and taildroom of four octets
 * for ICV. @payload_len is the length of payload (_not_ including extra
 * headroom and tailroom). @ta is the transmitter addresses. */
void ieee80211_tkip_encrypt_data(struct crypto_blkcipher *tfm,
				 struct ieee80211_key *key,
				 u8 *pos, size_t payload_len, u8 *ta)
{
	u8 rc4key[16];

	ieee80211_tkip_gen_rc4key(key, ta, rc4key);
	pos = ieee80211_tkip_add_iv(pos, key, rc4key[0], rc4key[1], rc4key[2]);
	ieee80211_wep_encrypt_data(tfm, rc4key, 16, pos, payload_len);
}


/* Decrypt packet payload with TKIP using @key. @pos is a pointer to the
 * beginning of the buffer containing IEEE 802.11 header payload, i.e.,
 * including IV, Ext. IV, real data, Michael MIC, ICV. @payload_len is the
 * length of payload, including IV, Ext. IV, MIC, ICV.  */
int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm,
				struct ieee80211_key *key,
				u8 *payload, size_t payload_len, u8 *ta,
				u8 *ra, int only_iv, int queue,
				u32 *out_iv32, u16 *out_iv16)
{
	u32 iv32;
	u32 iv16;
	u8 rc4key[16], keyid, *pos = payload;
	int res;

	if (payload_len < 12)
		return -1;

	iv16 = (pos[0] << 8) | pos[2];
	keyid = pos[3];
	iv32 = pos[4] | (pos[5] << 8) | (pos[6] << 16) | (pos[7] << 24);
	pos += 8;
#ifdef CONFIG_TKIP_DEBUG
	{
		int i;
		printk(KERN_DEBUG "TKIP decrypt: data(len=%zd)", payload_len);
		for (i = 0; i < payload_len; i++)
			printk(" %02x", payload[i]);
		printk("\n");
		printk(KERN_DEBUG "TKIP decrypt: iv16=%04x iv32=%08x\n",
		       iv16, iv32);
	}
#endif /* CONFIG_TKIP_DEBUG */

	if (!(keyid & (1 << 5)))
		return TKIP_DECRYPT_NO_EXT_IV;

	if ((keyid >> 6) != key->conf.keyidx)
		return TKIP_DECRYPT_INVALID_KEYIDX;

	if (key->u.tkip.rx_initialized[queue] &&
	    (iv32 < key->u.tkip.iv32_rx[queue] ||
	     (iv32 == key->u.tkip.iv32_rx[queue] &&
	      iv16 <= key->u.tkip.iv16_rx[queue]))) {
#ifdef CONFIG_TKIP_DEBUG
		DECLARE_MAC_BUF(mac);
		printk(KERN_DEBUG "TKIP replay detected for RX frame from "
		       "%s (RX IV (%04x,%02x) <= prev. IV (%04x,%02x)\n",
		       print_mac(mac, ta),
		       iv32, iv16, key->u.tkip.iv32_rx[queue],
		       key->u.tkip.iv16_rx[queue]);
#endif /* CONFIG_TKIP_DEBUG */
		return TKIP_DECRYPT_REPLAY;
	}

	if (only_iv) {
		res = TKIP_DECRYPT_OK;
		key->u.tkip.rx_initialized[queue] = 1;
		goto done;
	}

	if (!key->u.tkip.rx_initialized[queue] ||
	    key->u.tkip.iv32_rx[queue] != iv32) {
		key->u.tkip.rx_initialized[queue] = 1;
		/* IV16 wrapped around - perform TKIP phase 1 */
		tkip_mixing_phase1(ta, &key->conf.key[ALG_TKIP_TEMP_ENCR_KEY],
				   iv32, key->u.tkip.p1k_rx[queue]);
#ifdef CONFIG_TKIP_DEBUG
		{
			int i;
			DECLARE_MAC_BUF(mac);
			printk(KERN_DEBUG "TKIP decrypt: Phase1 TA=%s"
			       " TK=", print_mac(mac, ta));
			for (i = 0; i < 16; i++)
				printk("%02x ",
				       key->conf.key[
						ALG_TKIP_TEMP_ENCR_KEY + i]);
			printk("\n");
			printk(KERN_DEBUG "TKIP decrypt: P1K=");
			for (i = 0; i < 5; i++)
				printk("%04x ", key->u.tkip.p1k_rx[queue][i]);
			printk("\n");
		}
#endif /* CONFIG_TKIP_DEBUG */
		if (key->local->ops->update_tkip_key &&
			key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) {
			u8 bcast[ETH_ALEN] =
				{0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
			u8 *sta_addr = key->sta->addr;

			if (is_multicast_ether_addr(ra))
				sta_addr = bcast;

			key->local->ops->update_tkip_key(
				local_to_hw(key->local), &key->conf,
				sta_addr, iv32, key->u.tkip.p1k_rx[queue]);
		}
	}

	tkip_mixing_phase2(key->u.tkip.p1k_rx[queue],
			   &key->conf.key[ALG_TKIP_TEMP_ENCR_KEY],
			   iv16, rc4key);
#ifdef CONFIG_TKIP_DEBUG
	{
		int i;
		printk(KERN_DEBUG "TKIP decrypt: Phase2 rc4key=");
		for (i = 0; i < 16; i++)
			printk("%02x ", rc4key[i]);
		printk("\n");
	}
#endif /* CONFIG_TKIP_DEBUG */

	res = ieee80211_wep_decrypt_data(tfm, rc4key, 16, pos, payload_len - 12);
 done:
	if (res == TKIP_DECRYPT_OK) {
		/*
		 * Record previously received IV, will be copied into the
		 * key information after MIC verification. It is possible
		 * that we don't catch replays of fragments but that's ok
		 * because the Michael MIC verication will then fail.
		 */
		*out_iv32 = iv32;
		*out_iv16 = iv16;
	}

	return res;
}


