* 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;
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)
{
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];
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,
- priv->rxp, priv->rx_size,
- 0, michael_mic.result);
+ int ret;
+
+ ret = michael_mic(key->rx_mic_key,
+ priv->rxp, priv->rx_size,
+ 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 */
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;
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,
- &pp->data[0], skb_len,
- 0, michael_mic.result);
- memcpy(p, michael_mic.result, 8);
- length += 8;
- skb_len += 8;
- p += 8;
+ u8 mic[MICHAEL_MIC_LEN];
+
+ ret = michael_mic(priv->wpa.key[0].tx_mic_key,
+ &pp->data[0], skb_len,
+ 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 =
+++ /dev/null
-// 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);
-}