Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8b523f20 authored by Jeremy Sowden's avatar Jeremy Sowden Committed by Greg Kroah-Hartman
Browse files

staging: ks7010: removed custom Michael MIC implementation.



Changed the driver to use the kernel's own implementation.

Signed-off-by: default avatarJeremy Sowden <jeremy@azazel.net>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 050bd74b
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
obj-$(CONFIG_KS7010) += ks7010.o

ks7010-y	     := michael_mic.o ks_hostif.o ks_wlan_net.o ks7010_sdio.o
ks7010-y	:= ks_hostif.o ks_wlan_net.o ks7010_sdio.o
+0 −2
Original line number Diff line number Diff line
@@ -27,8 +27,6 @@ Now the TODOs:
- fix the 'card removal' event when card is inserted when booting
- check what other upstream wireless mechanisms can be used instead of the
  custom ones here
- replace custom Michael MIC implementation with the kernel
  implementation. This task is only required for a *clean* WEXT interface.

Please send any patches to:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+92 −19
Original line number Diff line number Diff line
@@ -6,15 +6,18 @@
 *   Copyright (C) 2009 Renesas Technology Corp.
 */

#include <crypto/hash.h>
#include <linux/circ_buf.h>
#include <linux/if_arp.h>
#include <net/iw_handler.h>
#include <uapi/linux/llc.h>
#include "eap_packet.h"
#include "ks_wlan.h"
#include "michael_mic.h"
#include "ks_hostif.h"

#define MICHAEL_MIC_KEY_LEN 8
#define MICHAEL_MIC_LEN     8

static inline void inc_smeqhead(struct ks_wlan_private *priv)
{
	priv->sme_i.qhead = (priv->sme_i.qhead + 1) % SME_EVENT_BUFF_SIZE;
@@ -191,6 +194,68 @@ static u8 read_ie(unsigned char *bp, u8 max, u8 *body)
	return size;
}

static int
michael_mic(u8 *key, u8 *data, unsigned int len, u8 priority, u8 *result)
{
	u8 pad_data[4] = { priority, 0, 0, 0 };
	struct crypto_shash *tfm = NULL;
	struct shash_desc *desc = NULL;
	int ret;

	tfm = crypto_alloc_shash("michael_mic", 0, 0);
	if (IS_ERR(tfm)) {
		ret = PTR_ERR(tfm);
		goto err;
	}

	ret = crypto_shash_setkey(tfm, key, MICHAEL_MIC_KEY_LEN);
	if (ret < 0)
		goto err_free_tfm;

	desc = kmalloc(sizeof(*desc) + crypto_shash_descsize(tfm), GFP_KERNEL);
	if (!desc) {
		ret = -ENOMEM;
		goto err_free_tfm;
	}

	desc->tfm = tfm;
	desc->flags = 0;

	ret = crypto_shash_init(desc);
	if (ret < 0)
		goto err_free_desc;

	// Compute the MIC value
	/*
	 * IEEE802.11i  page 47
	 * Figure 43g TKIP MIC processing format
	 * +--+--+--------+--+----+--+--+--+--+--+--+--+--+
	 * |6 |6 |1       |3 |M   |1 |1 |1 |1 |1 |1 |1 |1 | Octet
	 * +--+--+--------+--+----+--+--+--+--+--+--+--+--+
	 * |DA|SA|Priority|0 |Data|M0|M1|M2|M3|M4|M5|M6|M7|
	 * +--+--+--------+--+----+--+--+--+--+--+--+--+--+
	 */

	ret = crypto_shash_update(desc, data, 12);
	if (ret < 0)
		goto err_free_desc;

	ret = crypto_shash_update(desc, pad_data, 4);
	if (ret < 0)
		goto err_free_desc;

	ret = crypto_shash_finup(desc, data + 12, len - 12, result);

err_free_desc:
	kzfree(desc);

err_free_tfm:
	crypto_free_shash(tfm);

err:
	return ret;
}

static
int get_ap_information(struct ks_wlan_private *priv, struct ap_info *ap_info,
		       struct local_ap *ap)
@@ -273,11 +338,11 @@ int hostif_data_indication_wpa(struct ks_wlan_private *priv,
{
	struct ether_hdr *eth_hdr;
	unsigned short eth_proto;
	unsigned char recv_mic[8];
	unsigned char recv_mic[MICHAEL_MIC_LEN];
	char buf[128];
	unsigned long now;
	struct mic_failure *mic_failure;
	struct michael_mic michael_mic;
	u8 mic[MICHAEL_MIC_LEN];
	union iwreq_data wrqu;
	unsigned int key_index = auth_type - 1;
	struct wpa_key *key = &priv->wpa.key[key_index];
@@ -300,14 +365,20 @@ int hostif_data_indication_wpa(struct ks_wlan_private *priv,
		netdev_dbg(priv->net_dev, "TKIP: protocol=%04X: size=%u\n",
			   eth_proto, priv->rx_size);
		/* MIC save */
		memcpy(&recv_mic[0], (priv->rxp) + ((priv->rx_size) - 8), 8);
		priv->rx_size = priv->rx_size - 8;
		memcpy(&recv_mic[0],
		       (priv->rxp) + ((priv->rx_size) - sizeof(recv_mic)),
		       sizeof(recv_mic));
		priv->rx_size = priv->rx_size - sizeof(recv_mic);
		if (auth_type > 0 && auth_type < 4) {	/* auth_type check */
			michael_mic_function(&michael_mic, key->rx_mic_key,
			int ret;

			ret = michael_mic(key->rx_mic_key,
					  priv->rxp, priv->rx_size,
					     0,	michael_mic.result);
					  0, mic);
			if (ret < 0)
				return ret;
		}
		if (memcmp(michael_mic.result, recv_mic, 8) != 0) {
		if (memcmp(mic, recv_mic, sizeof(mic)) != 0) {
			now = jiffies;
			mic_failure = &priv->wpa.mic_failure;
			/* MIC FAILURE */
@@ -1002,7 +1073,6 @@ int hostif_data_request(struct ks_wlan_private *priv, struct sk_buff *skb)
	int result = 0;
	unsigned short eth_proto;
	struct ether_hdr *eth_hdr;
	struct michael_mic michael_mic;
	unsigned short keyinfo = 0;
	struct ieee802_1x_hdr *aa1x_hdr;
	struct wpa_eapol_key *eap_key;
@@ -1109,17 +1179,20 @@ int hostif_data_request(struct ks_wlan_private *priv, struct sk_buff *skb)
			pp->auth_type = cpu_to_le16(TYPE_AUTH);
		} else {
			if (priv->wpa.pairwise_suite == IW_AUTH_CIPHER_TKIP) {
				michael_mic_function(&michael_mic,
						     priv->wpa.key[0].tx_mic_key,
				u8 mic[MICHAEL_MIC_LEN];

				ret = michael_mic(priv->wpa.key[0].tx_mic_key,
						  &pp->data[0], skb_len,
						     0,	michael_mic.result);
				memcpy(p, michael_mic.result, 8);
				length += 8;
				skb_len += 8;
				p += 8;
						  0, mic);
				if (ret < 0)
					goto err_kfree;

				memcpy(p, mic, sizeof(mic));
				length += sizeof(mic);
				skb_len += sizeof(mic);
				p += sizeof(mic);
				pp->auth_type =
				    cpu_to_le16(TYPE_DATA);

			} else if (priv->wpa.pairwise_suite ==
				   IW_AUTH_CIPHER_CCMP) {
				pp->auth_type =
+0 −127
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0
/*
 *   Driver for KeyStream wireless LAN
 *
 *   Copyright (C) 2005-2008 KeyStream Corp.
 *   Copyright (C) 2009 Renesas Technology Corp.
 */

#include <asm/unaligned.h>
#include <linux/bitops.h>
#include <linux/string.h>
#include "michael_mic.h"

// Reset the state to the empty message.
static inline void michael_clear(struct michael_mic *mic)
{
	mic->l = mic->k0;
	mic->r = mic->k1;
	mic->m_bytes = 0;
}

static void michael_init(struct michael_mic *mic, u8 *key)
{
	// Set the key
	mic->k0 = get_unaligned_le32(key);
	mic->k1 = get_unaligned_le32(key + 4);

	//clear();
	michael_clear(mic);
}

static inline void michael_block(struct michael_mic *mic)
{
	mic->r ^= rol32(mic->l, 17);
	mic->l += mic->r;
	mic->r ^= ((mic->l & 0xff00ff00) >> 8) |
		  ((mic->l & 0x00ff00ff) << 8);
	mic->l += mic->r;
	mic->r ^= rol32(mic->l, 3);
	mic->l += mic->r;
	mic->r ^= ror32(mic->l, 2);
	mic->l += mic->r;
}

static void michael_append(struct michael_mic *mic, u8 *src, int bytes)
{
	int addlen;

	if (mic->m_bytes) {
		addlen = 4 - mic->m_bytes;
		if (addlen > bytes)
			addlen = bytes;
		memcpy(&mic->m[mic->m_bytes], src, addlen);
		mic->m_bytes += addlen;
		src += addlen;
		bytes -= addlen;

		if (mic->m_bytes < 4)
			return;

		mic->l ^= get_unaligned_le32(mic->m);
		michael_block(mic);
		mic->m_bytes = 0;
	}

	while (bytes >= 4) {
		mic->l ^= get_unaligned_le32(src);
		michael_block(mic);
		src += 4;
		bytes -= 4;
	}

	if (bytes > 0) {
		mic->m_bytes = bytes;
		memcpy(mic->m, src, bytes);
	}
}

static void michael_get_mic(struct michael_mic *mic, u8 *dst)
{
	u8 *data = mic->m;

	switch (mic->m_bytes) {
	case 0:
		mic->l ^= 0x5a;
		break;
	case 1:
		mic->l ^= data[0] | 0x5a00;
		break;
	case 2:
		mic->l ^= data[0] | (data[1] << 8) | 0x5a0000;
		break;
	case 3:
		mic->l ^= data[0] | (data[1] << 8) | (data[2] << 16) |
		    0x5a000000;
		break;
	}
	michael_block(mic);
	michael_block(mic);
	// The appendByte function has already computed the result.
	put_unaligned_le32(mic->l, dst);
	put_unaligned_le32(mic->r, dst + 4);

	// Reset to the empty message.
	michael_clear(mic);
}

void michael_mic_function(struct michael_mic *mic, u8 *key,
			  u8 *data, unsigned int len, u8 priority, u8 *result)
{
	u8 pad_data[4] = { priority, 0, 0, 0 };
	// Compute the MIC value
	/*
	 * IEEE802.11i  page 47
	 * Figure 43g TKIP MIC processing format
	 * +--+--+--------+--+----+--+--+--+--+--+--+--+--+
	 * |6 |6 |1       |3 |M   |1 |1 |1 |1 |1 |1 |1 |1 | Octet
	 * +--+--+--------+--+----+--+--+--+--+--+--+--+--+
	 * |DA|SA|Priority|0 |Data|M0|M1|M2|M3|M4|M5|M6|M7|
	 * +--+--+--------+--+----+--+--+--+--+--+--+--+--+
	 */
	michael_init(mic, key);
	michael_append(mic, data, 12);	/* |DA|SA| */
	michael_append(mic, pad_data, 4);	/* |Priority|0|0|0| */
	michael_append(mic, data + 12, len - 12);	/* |Data| */
	michael_get_mic(mic, result);
}
+0 −21
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */
/*
 *   Driver for KeyStream wireless LAN
 *
 *   Copyright (C) 2005-2008 KeyStream Corp.
 *   Copyright (C) 2009 Renesas Technology Corp.
 */

/* MichaelMIC routine define */
struct michael_mic {
	u32 k0;	// Key
	u32 k1;	// Key
	u32 l;	// Current state
	u32 r;	// Current state
	u8 m[4];	// Message accumulator (single word)
	int m_bytes;	// # bytes in M
	u8 result[8];
};

void michael_mic_function(struct michael_mic *mic, u8 *key,
			  u8 *data, unsigned int len, u8 priority, u8 *result);