/*
	Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
	<http://rt2x00.serialmonkey.com>

	This program is free software; you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation; either version 2 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program; if not, write to the
	Free Software Foundation, Inc.,
	59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

/*
	Module: rt2x00lib
	Abstract: rt2x00 crypto specific routines.
 */

#include <linux/kernel.h>
#include <linux/module.h>

#include "rt2x00.h"
#include "rt2x00lib.h"

enum cipher rt2x00crypto_key_to_cipher(struct ieee80211_key_conf *key)
{
	switch (key->alg) {
	case ALG_WEP:
		if (key->keylen == WLAN_KEY_LEN_WEP40)
			return CIPHER_WEP64;
		else
			return CIPHER_WEP128;
	case ALG_TKIP:
		return CIPHER_TKIP;
	case ALG_CCMP:
		return CIPHER_AES;
	default:
		return CIPHER_NONE;
	}
}

void rt2x00crypto_create_tx_descriptor(struct queue_entry *entry,
				       struct txentry_desc *txdesc)
{
	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
	struct ieee80211_key_conf *hw_key = tx_info->control.hw_key;

	if (!test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags) ||
	    !hw_key || entry->skb->do_not_encrypt)
		return;

	__set_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags);

	txdesc->cipher = rt2x00crypto_key_to_cipher(hw_key);

	if (hw_key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
		__set_bit(ENTRY_TXD_ENCRYPT_PAIRWISE, &txdesc->flags);

	txdesc->key_idx = hw_key->hw_key_idx;
	txdesc->iv_offset = txdesc->header_length;
	txdesc->iv_len = hw_key->iv_len;

	if (!(hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV))
		__set_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags);

	if (!(hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_MMIC))
		__set_bit(ENTRY_TXD_ENCRYPT_MMIC, &txdesc->flags);
}

unsigned int rt2x00crypto_tx_overhead(struct rt2x00_dev *rt2x00dev,
				      struct sk_buff *skb)
{
	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
	struct ieee80211_key_conf *key = tx_info->control.hw_key;
	unsigned int overhead = 0;

	if (!test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags) ||
	    !key || skb->do_not_encrypt)
		return overhead;

	/*
	 * Extend frame length to include IV/EIV/ICV/MMIC,
	 * note that these lengths should only be added when
	 * mac80211 does not generate it.
	 */
	overhead += key->icv_len;

	if (!(key->flags & IEEE80211_KEY_FLAG_GENERATE_IV))
		overhead += key->iv_len;

	if (!(key->flags & IEEE80211_KEY_FLAG_GENERATE_MMIC)) {
		if (key->alg == ALG_TKIP)
			overhead += 8;
	}

	return overhead;
}

void rt2x00crypto_tx_copy_iv(struct sk_buff *skb, struct txentry_desc *txdesc)
{
	struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);

	if (unlikely(!txdesc->iv_len))
		return;

	/* Copy IV/EIV data */
	memcpy(skbdesc->iv, skb->data + txdesc->iv_offset, txdesc->iv_len);
}

void rt2x00crypto_tx_remove_iv(struct sk_buff *skb, struct txentry_desc *txdesc)
{
	struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);

	if (unlikely(!txdesc->iv_len))
		return;

	/* Copy IV/EIV data */
	memcpy(skbdesc->iv, skb->data + txdesc->iv_offset, txdesc->iv_len);

	/* Move ieee80211 header */
	memmove(skb->data + txdesc->iv_len, skb->data, txdesc->iv_offset);

	/* Pull buffer to correct size */
	skb_pull(skb, txdesc->iv_len);

	/* IV/EIV data has officially be stripped */
	skbdesc->flags |= SKBDESC_IV_STRIPPED;
}

void rt2x00crypto_tx_insert_iv(struct sk_buff *skb, unsigned int header_length)
{
	struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
	const unsigned int iv_len =
	    ((!!(skbdesc->iv[0])) * 4) + ((!!(skbdesc->iv[1])) * 4);

	if (!(skbdesc->flags & SKBDESC_IV_STRIPPED))
		return;

	skb_push(skb, iv_len);

	/* Move ieee80211 header */
	memmove(skb->data, skb->data + iv_len, header_length);

	/* Copy IV/EIV data */
	memcpy(skb->data + header_length, skbdesc->iv, iv_len);

	/* IV/EIV data has returned into the frame */
	skbdesc->flags &= ~SKBDESC_IV_STRIPPED;
}

void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, bool l2pad,
			       unsigned int header_length,
			       struct rxdone_entry_desc *rxdesc)
{
	unsigned int payload_len = rxdesc->size - header_length;
	unsigned int align = ALIGN_SIZE(skb, header_length);
	unsigned int iv_len;
	unsigned int icv_len;
	unsigned int transfer = 0;

	/*
	 * WEP64/WEP128: Provides IV & ICV
	 * TKIP: Provides IV/EIV & ICV
	 * AES: Provies IV/EIV & ICV
	 */
	switch (rxdesc->cipher) {
	case CIPHER_WEP64:
	case CIPHER_WEP128:
		iv_len = 4;
		icv_len = 4;
		break;
	case CIPHER_TKIP:
		iv_len = 8;
		icv_len = 4;
		break;
	case CIPHER_AES:
		iv_len = 8;
		icv_len = 8;
		break;
	default:
		/* Unsupport type */
		return;
	}

	/*
	 * Make room for new data. There are 2 possibilities
	 * either the alignment is already present between
	 * the 802.11 header and payload. In that case we
	 * we have to move the header less then the iv_len
	 * since we can use the already available l2pad bytes
	 * for the iv data.
	 * When the alignment must be added manually we must
	 * move the header more then iv_len since we must
	 * make room for the payload move as well.
	 */
	if (l2pad) {
		skb_push(skb, iv_len - align);
		skb_put(skb, icv_len);

		/* Move ieee80211 header */
		memmove(skb->data + transfer,
			skb->data + transfer + (iv_len - align),
			header_length);
		transfer += header_length;
	} else {
		skb_push(skb, iv_len + align);
		if (align < icv_len)
			skb_put(skb, icv_len - align);
		else if (align > icv_len)
			skb_trim(skb, rxdesc->size + iv_len + icv_len);

		/* Move ieee80211 header */
		memmove(skb->data + transfer,
			skb->data + transfer + iv_len + align,
			header_length);
		transfer += header_length;
	}

	/* Copy IV/EIV data */
	memcpy(skb->data + transfer, rxdesc->iv, iv_len);
	transfer += iv_len;

	/*
	 * Move payload for alignment purposes. Note that
	 * this is only needed when no l2 padding is present.
	 */
	if (!l2pad) {
		memmove(skb->data + transfer,
			skb->data + transfer + align,
			payload_len);
	}

	/*
	 * NOTE: Always count the payload as transfered,
	 * even when alignment was set to zero. This is required
	 * for determining the correct offset for the ICV data.
	 */
	transfer += payload_len;

	/*
	 * Copy ICV data
	 * AES appends 8 bytes, we can't fill the upper
	 * 4 bytes, but mac80211 doesn't care about what
	 * we provide here anyway and strips it immediately.
	 */
	memcpy(skb->data + transfer, &rxdesc->icv, 4);
	transfer += icv_len;

	/* IV/EIV/ICV has been inserted into frame */
	rxdesc->size = transfer;
	rxdesc->flags &= ~RX_FLAG_IV_STRIPPED;
}
