diff options
Diffstat (limited to 'drivers/staging/ks7010/ks_hostif.c')
-rw-r--r-- | drivers/staging/ks7010/ks_hostif.c | 119 |
1 files changed, 96 insertions, 23 deletions
diff --git a/drivers/staging/ks7010/ks_hostif.c b/drivers/staging/ks7010/ks_hostif.c index 065bce193fac..06ebea0be118 100644 --- a/drivers/staging/ks7010/ks_hostif.c +++ b/drivers/staging/ks7010/ks_hostif.c @@ -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; @@ -35,7 +38,7 @@ static inline u8 get_byte(struct ks_wlan_private *priv) { u8 data; - data = *(priv->rxp)++; + data = *priv->rxp++; /* length check in advance ! */ --(priv->rx_size); return data; @@ -171,7 +174,7 @@ int get_current_ap(struct ks_wlan_private *priv, struct link_ap_info *ap_info) "- rate_set_size=%d\n", ap->bssid[0], ap->bssid[1], ap->bssid[2], ap->bssid[3], ap->bssid[4], ap->bssid[5], - &(ap->ssid.body[0]), + &ap->ssid.body[0], ap->rate_set.body[0], ap->rate_set.body[1], ap->rate_set.body[2], ap->rate_set.body[3], ap->rate_set.body[4], ap->rate_set.body[5], @@ -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, - 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 */ @@ -730,9 +801,9 @@ void hostif_scan_indication(struct ks_wlan_private *priv) priv->scan_ind_count++; if (priv->scan_ind_count < LOCAL_APLIST_MAX + 1) { netdev_dbg(priv->net_dev, " scan_ind_count=%d :: aplist.size=%d\n", - priv->scan_ind_count, priv->aplist.size); + priv->scan_ind_count, priv->aplist.size); get_ap_information(priv, (struct ap_info *)(priv->rxp), - &(priv->aplist.ap[priv->scan_ind_count - 1])); + &priv->aplist.ap[priv->scan_ind_count - 1]); priv->aplist.size = priv->scan_ind_count; } else { netdev_dbg(priv->net_dev, " count over :: scan_ind_count=%d\n", @@ -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, - &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 = |