···336336 depends on (PPC_PMAC || PCI || PCMCIA) && WLAN_80211337337 select WIRELESS_EXT338338 select FW_LOADER339339+ select CRYPTO340340+ select CRYPTO_MICHAEL_MIC339341 ---help---340342 A driver for 802.11b wireless cards based on the "Hermes" or341343 Intersil HFA384x (Prism 2) MAC controller. This includes the vast
+7
drivers/net/wireless/hermes.h
···184184#define HERMES_RXSTAT_ERR (0x0003)185185#define HERMES_RXSTAT_BADCRC (0x0001)186186#define HERMES_RXSTAT_UNDECRYPTABLE (0x0002)187187+#define HERMES_RXSTAT_MIC (0x0010) /* Frame contains MIC */187188#define HERMES_RXSTAT_MACPORT (0x0700)188189#define HERMES_RXSTAT_PCF (0x1000) /* Frame was received in CF period */190190+#define HERMES_RXSTAT_MIC_KEY_ID (0x1800) /* MIC key used */189191#define HERMES_RXSTAT_MSGTYPE (0xE000)190192#define HERMES_RXSTAT_1042 (0x2000) /* RFC-1042 frame */191193#define HERMES_RXSTAT_TUNNEL (0x4000) /* bridge-tunnel encoded frame */192194#define HERMES_RXSTAT_WMP (0x6000) /* Wavelan-II Management Protocol frame */195195+196196+/* Shift amount for key ID in RXSTAT and TXCTRL */197197+#define HERMES_MIC_KEY_ID_SHIFT 11193198194199struct hermes_tx_descriptor {195200 __le16 status;···214209#define HERMES_TXCTRL_TX_OK (0x0002) /* ?? interrupt on Tx complete */215210#define HERMES_TXCTRL_TX_EX (0x0004) /* ?? interrupt on Tx exception */216211#define HERMES_TXCTRL_802_11 (0x0008) /* We supply 802.11 header */212212+#define HERMES_TXCTRL_MIC (0x0010) /* 802.3 + TKIP */213213+#define HERMES_TXCTRL_MIC_KEY_ID (0x1800) /* MIC Key ID mask */217214#define HERMES_TXCTRL_ALT_RTRY (0x0020)218215219216/* Inquiry constants and data types */
+218-16
drivers/net/wireless/orinoco.c
···8989#include <net/iw_handler.h>9090#include <net/ieee80211.h>91919292+#include <linux/scatterlist.h>9393+#include <linux/crypto.h>9494+9295#include "hermes_rid.h"9396#include "hermes_dld.h"9497#include "orinoco.h"···245242246243static int __orinoco_program_rids(struct net_device *dev);247244static void __orinoco_set_multicast_list(struct net_device *dev);245245+246246+/********************************************************************/247247+/* Michael MIC crypto setup */248248+/********************************************************************/249249+#define MICHAEL_MIC_LEN 8250250+static int orinoco_mic_init(struct orinoco_private *priv)251251+{252252+ priv->tx_tfm_mic = crypto_alloc_hash("michael_mic", 0, 0);253253+ if (IS_ERR(priv->tx_tfm_mic)) {254254+ printk(KERN_DEBUG "orinoco_mic_init: could not allocate "255255+ "crypto API michael_mic\n");256256+ priv->tx_tfm_mic = NULL;257257+ return -ENOMEM;258258+ }259259+260260+ priv->rx_tfm_mic = crypto_alloc_hash("michael_mic", 0, 0);261261+ if (IS_ERR(priv->rx_tfm_mic)) {262262+ printk(KERN_DEBUG "orinoco_mic_init: could not allocate "263263+ "crypto API michael_mic\n");264264+ priv->rx_tfm_mic = NULL;265265+ return -ENOMEM;266266+ }267267+268268+ return 0;269269+}270270+271271+static void orinoco_mic_free(struct orinoco_private *priv)272272+{273273+ if (priv->tx_tfm_mic)274274+ crypto_free_hash(priv->tx_tfm_mic);275275+ if (priv->rx_tfm_mic)276276+ crypto_free_hash(priv->rx_tfm_mic);277277+}278278+279279+static int michael_mic(struct crypto_hash *tfm_michael, u8 *key,280280+ u8 *da, u8 *sa, u8 priority,281281+ u8 *data, size_t data_len, u8 *mic)282282+{283283+ struct hash_desc desc;284284+ struct scatterlist sg[2];285285+ u8 hdr[ETH_HLEN + 2]; /* size of header + padding */286286+287287+ if (tfm_michael == NULL) {288288+ printk(KERN_WARNING "michael_mic: tfm_michael == NULL\n");289289+ return -1;290290+ }291291+292292+ /* Copy header into buffer. We need the padding on the end zeroed */293293+ memcpy(&hdr[0], da, ETH_ALEN);294294+ memcpy(&hdr[ETH_ALEN], sa, ETH_ALEN);295295+ hdr[ETH_ALEN*2] = priority;296296+ hdr[ETH_ALEN*2+1] = 0;297297+ hdr[ETH_ALEN*2+2] = 0;298298+ hdr[ETH_ALEN*2+3] = 0;299299+300300+ /* Use scatter gather to MIC header and data in one go */301301+ sg_init_table(sg, 2);302302+ sg_set_buf(&sg[0], hdr, sizeof(hdr));303303+ sg_set_buf(&sg[1], data, data_len);304304+305305+ if (crypto_hash_setkey(tfm_michael, key, MIC_KEYLEN))306306+ return -1;307307+308308+ desc.tfm = tfm_michael;309309+ desc.flags = 0;310310+ return crypto_hash_digest(&desc, sg, data_len + sizeof(hdr),311311+ mic);312312+}248313249314/********************************************************************/250315/* Internal helper functions */···835764 int err = 0;836765 u16 txfid = priv->txfid;837766 struct ethhdr *eh;838838- int data_off;839767 int tx_control;840768 unsigned long flags;841769···867797 if (skb->len < ETH_HLEN)868798 goto drop;869799870870- eh = (struct ethhdr *)skb->data;871871-872800 tx_control = HERMES_TXCTRL_TX_OK | HERMES_TXCTRL_TX_EX;801801+802802+ if (priv->encode_alg == IW_ENCODE_ALG_TKIP)803803+ tx_control |= (priv->tx_key << HERMES_MIC_KEY_ID_SHIFT) |804804+ HERMES_TXCTRL_MIC;873805874806 if (priv->has_alt_txcntl) {875807 /* WPA enabled firmwares have tx_cntl at the end of···914842 HERMES_802_3_OFFSET - HERMES_802_11_OFFSET);915843 }916844845845+ eh = (struct ethhdr *)skb->data;846846+917847 /* Encapsulate Ethernet-II frames */918848 if (ntohs(eh->h_proto) > ETH_DATA_LEN) { /* Ethernet-II frame */919849 struct header_struct {···925851926852 /* Strip destination and source from the data */927853 skb_pull(skb, 2 * ETH_ALEN);928928- data_off = HERMES_802_2_OFFSET + sizeof(encaps_hdr);929854930855 /* And move them to a separate header */931856 memcpy(&hdr.eth, eh, 2 * ETH_ALEN);932857 hdr.eth.h_proto = htons(sizeof(encaps_hdr) + skb->len);933858 memcpy(hdr.encap, encaps_hdr, sizeof(encaps_hdr));934859935935- err = hermes_bap_pwrite(hw, USER_BAP, &hdr, sizeof(hdr),936936- txfid, HERMES_802_3_OFFSET);937937- if (err) {938938- if (net_ratelimit())939939- printk(KERN_ERR "%s: Error %d writing packet "940940- "header to BAP\n", dev->name, err);941941- goto busy;860860+ /* Insert the SNAP header */861861+ if (skb_headroom(skb) < sizeof(hdr)) {862862+ printk(KERN_ERR863863+ "%s: Not enough headroom for 802.2 headers %d\n",864864+ dev->name, skb_headroom(skb));865865+ goto drop;942866 }943943- } else { /* IEEE 802.3 frame */944944- data_off = HERMES_802_3_OFFSET;867867+ eh = (struct ethhdr *) skb_push(skb, sizeof(hdr));868868+ memcpy(eh, &hdr, sizeof(hdr));945869 }946870947871 err = hermes_bap_pwrite(hw, USER_BAP, skb->data, skb->len,948948- txfid, data_off);872872+ txfid, HERMES_802_3_OFFSET);949873 if (err) {950874 printk(KERN_ERR "%s: Error %d writing packet to BAP\n",951875 dev->name, err);952876 goto busy;877877+ }878878+879879+ /* Calculate Michael MIC */880880+ if (priv->encode_alg == IW_ENCODE_ALG_TKIP) {881881+ u8 mic_buf[MICHAEL_MIC_LEN + 1];882882+ u8 *mic;883883+ size_t offset;884884+ size_t len;885885+886886+ if (skb->len % 2) {887887+ /* MIC start is on an odd boundary */888888+ mic_buf[0] = skb->data[skb->len - 1];889889+ mic = &mic_buf[1];890890+ offset = skb->len - 1;891891+ len = MICHAEL_MIC_LEN + 1;892892+ } else {893893+ mic = &mic_buf[0];894894+ offset = skb->len;895895+ len = MICHAEL_MIC_LEN;896896+ }897897+898898+ michael_mic(priv->tx_tfm_mic,899899+ priv->tkip_key[priv->tx_key].tx_mic,900900+ eh->h_dest, eh->h_source, 0 /* priority */,901901+ skb->data + ETH_HLEN, skb->len - ETH_HLEN, mic);902902+903903+ /* Write the MIC */904904+ err = hermes_bap_pwrite(hw, USER_BAP, &mic_buf[0], len,905905+ txfid, HERMES_802_3_OFFSET + offset);906906+ if (err) {907907+ printk(KERN_ERR "%s: Error %d writing MIC to BAP\n",908908+ dev->name, err);909909+ goto busy;910910+ }953911 }954912955913 /* Finally, we actually initiate the send */···998892 }9998931000894 dev->trans_start = jiffies;10011001- stats->tx_bytes += data_off + skb->len;895895+ stats->tx_bytes += HERMES_802_3_OFFSET + skb->len;1002896 goto ok;10038971004898 drop:···12781172 stats->rx_dropped++;12791173}1280117411751175+/* Get tsc from the firmware */11761176+static int orinoco_hw_get_tkip_iv(struct orinoco_private *priv, int key,11771177+ u8 *tsc)11781178+{11791179+ hermes_t *hw = &priv->hw;11801180+ int err = 0;11811181+ u8 tsc_arr[4][IW_ENCODE_SEQ_MAX_SIZE];11821182+11831183+ if ((key < 0) || (key > 4))11841184+ return -EINVAL;11851185+11861186+ err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_TKIP_IV,11871187+ sizeof(tsc_arr), NULL, &tsc_arr);11881188+ if (!err)11891189+ memcpy(tsc, &tsc_arr[key][0], sizeof(tsc_arr[0]));11901190+11911191+ return err;11921192+}11931193+12811194static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)12821195{12831196 struct orinoco_private *priv = netdev_priv(dev);···13651240 goto update_stats;13661241 }1367124212431243+ /* Payload size does not include Michael MIC. Increase payload12441244+ * size to read it together with the data. */12451245+ if (status & HERMES_RXSTAT_MIC)12461246+ length += MICHAEL_MIC_LEN;12471247+13681248 /* We need space for the packet data itself, plus an ethernet13691249 header, plus 2 bytes so we can align the IP header on a13701250 32bit boundary, plus 1 byte so we can read in odd length···14331303 length = le16_to_cpu(desc->data_len);14341304 fc = le16_to_cpu(desc->frame_ctl);1435130513061306+ /* Calculate and check MIC */13071307+ if (status & HERMES_RXSTAT_MIC) {13081308+ int key_id = ((status & HERMES_RXSTAT_MIC_KEY_ID) >>13091309+ HERMES_MIC_KEY_ID_SHIFT);13101310+ u8 mic[MICHAEL_MIC_LEN];13111311+ u8 *rxmic;13121312+ u8 *src = (fc & IEEE80211_FCTL_FROMDS) ?13131313+ desc->addr3 : desc->addr2;13141314+13151315+ /* Extract Michael MIC from payload */13161316+ rxmic = skb->data + skb->len - MICHAEL_MIC_LEN;13171317+13181318+ skb_trim(skb, skb->len - MICHAEL_MIC_LEN);13191319+ length -= MICHAEL_MIC_LEN;13201320+13211321+ michael_mic(priv->rx_tfm_mic,13221322+ priv->tkip_key[key_id].rx_mic,13231323+ desc->addr1,13241324+ src,13251325+ 0, /* priority or QoS? */13261326+ skb->data,13271327+ skb->len,13281328+ &mic[0]);13291329+13301330+ if (memcmp(mic, rxmic,13311331+ MICHAEL_MIC_LEN)) {13321332+ union iwreq_data wrqu;13331333+ struct iw_michaelmicfailure wxmic;13341334+ DECLARE_MAC_BUF(mac);13351335+13361336+ printk(KERN_WARNING "%s: "13371337+ "Invalid Michael MIC in data frame from %s, "13381338+ "using key %i\n",13391339+ dev->name, print_mac(mac, src), key_id);13401340+13411341+ /* TODO: update stats */13421342+13431343+ /* Notify userspace */13441344+ memset(&wxmic, 0, sizeof(wxmic));13451345+ wxmic.flags = key_id & IW_MICFAILURE_KEY_ID;13461346+ wxmic.flags |= (desc->addr1[0] & 1) ?13471347+ IW_MICFAILURE_GROUP : IW_MICFAILURE_PAIRWISE;13481348+ wxmic.src_addr.sa_family = ARPHRD_ETHER;13491349+ memcpy(wxmic.src_addr.sa_data, src, ETH_ALEN);13501350+13511351+ (void) orinoco_hw_get_tkip_iv(priv, key_id,13521352+ &wxmic.tsc[0]);13531353+13541354+ memset(&wrqu, 0, sizeof(wrqu));13551355+ wrqu.data.length = sizeof(wxmic);13561356+ wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu,13571357+ (char *) &wxmic);13581358+13591359+ goto drop;13601360+ }13611361+ }13621362+14361363 /* Handle decapsulation14371364 * In most cases, the firmware tell us about SNAP frames.14381365 * For some reason, the SNAP frames sent by LinkSys APs···15291342 stats->rx_bytes += length;1530134315311344 return;13451345+13461346+ drop:13471347+ dev_kfree_skb(skb);13481348+ stats->rx_errors++;13491349+ stats->rx_dropped++;15321350}1533135115341352static void orinoco_rx_isr_tasklet(unsigned long data)···33043112 else33053113 printk("40-bit key\n");33063114 }33073307- if (priv->has_wpa)31153115+ if (priv->has_wpa) {33083116 printk(KERN_DEBUG "%s: WPA-PSK supported\n", dev->name);31173117+ if (orinoco_mic_init(priv)) {31183118+ printk(KERN_ERR "%s: Failed to setup MIC crypto "31193119+ "algorithm. Disabling WPA support\n", dev->name);31203120+ priv->has_wpa = 0;31213121+ }31223122+ }3309312333103124 /* Now we have the firmware capabilities, allocate appropiate33113125 * sized scan buffers */···34903292 dev->set_multicast_list = orinoco_set_multicast_list;34913293 /* we use the default eth_mac_addr for setting the MAC addr */3492329432953295+ /* Reserve space in skb for the SNAP header */32963296+ dev->hard_header_len += ENCAPS_OVERHEAD;32973297+34933298 /* Set up default callbacks */34943299 dev->open = orinoco_open;34953300 dev->stop = orinoco_stop;···35283327 tasklet_kill(&priv->rx_tasklet);35293328 priv->wpa_ie_len = 0;35303329 kfree(priv->wpa_ie);33303330+ orinoco_mic_free(priv);35313331 orinoco_bss_data_free(priv);35323332 free_netdev(dev);35333333}
+2
drivers/net/wireless/orinoco.h
···158158 int wpa_ie_len;159159160160 struct orinoco_tkip_key tkip_key[ORINOCO_MAX_KEYS];161161+ struct crypto_hash *rx_tfm_mic;162162+ struct crypto_hash *tx_tfm_mic;161163162164 unsigned int wpa_enabled:1;163165 unsigned int tkip_cm_active:1;