aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/orinoco.c
diff options
context:
space:
mode:
authorDavid Kilroy <kilroyd@gmail.com>2008-08-21 18:28:05 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-08-22 19:28:07 -0400
commit23edcc4147ad36f8d55f0eb79c21e245ffb9f211 (patch)
tree20aaa2208d7ba51769639bcedd6be3bc3cd8673c /drivers/net/wireless/orinoco.c
parent31afcef385bb8bf528c6fbe05b359af9f456f02a (diff)
orinoco: Add MIC on TX and check on RX
Use the MIC algorithm from the crypto subsystem. Signed-off-by: David Kilroy <kilroyd@gmail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/orinoco.c')
-rw-r--r--drivers/net/wireless/orinoco.c234
1 files changed, 218 insertions, 16 deletions
diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c
index 768b39452674..6a196c31de43 100644
--- a/drivers/net/wireless/orinoco.c
+++ b/drivers/net/wireless/orinoco.c
@@ -89,6 +89,9 @@
89#include <net/iw_handler.h> 89#include <net/iw_handler.h>
90#include <net/ieee80211.h> 90#include <net/ieee80211.h>
91 91
92#include <linux/scatterlist.h>
93#include <linux/crypto.h>
94
92#include "hermes_rid.h" 95#include "hermes_rid.h"
93#include "hermes_dld.h" 96#include "hermes_dld.h"
94#include "orinoco.h" 97#include "orinoco.h"
@@ -244,6 +247,74 @@ static int __orinoco_program_rids(struct net_device *dev);
244static void __orinoco_set_multicast_list(struct net_device *dev); 247static void __orinoco_set_multicast_list(struct net_device *dev);
245 248
246/********************************************************************/ 249/********************************************************************/
250/* Michael MIC crypto setup */
251/********************************************************************/
252#define MICHAEL_MIC_LEN 8
253static int orinoco_mic_init(struct orinoco_private *priv)
254{
255 priv->tx_tfm_mic = crypto_alloc_hash("michael_mic", 0, 0);
256 if (IS_ERR(priv->tx_tfm_mic)) {
257 printk(KERN_DEBUG "orinoco_mic_init: could not allocate "
258 "crypto API michael_mic\n");
259 priv->tx_tfm_mic = NULL;
260 return -ENOMEM;
261 }
262
263 priv->rx_tfm_mic = crypto_alloc_hash("michael_mic", 0, 0);
264 if (IS_ERR(priv->rx_tfm_mic)) {
265 printk(KERN_DEBUG "orinoco_mic_init: could not allocate "
266 "crypto API michael_mic\n");
267 priv->rx_tfm_mic = NULL;
268 return -ENOMEM;
269 }
270
271 return 0;
272}
273
274static void orinoco_mic_free(struct orinoco_private *priv)
275{
276 if (priv->tx_tfm_mic)
277 crypto_free_hash(priv->tx_tfm_mic);
278 if (priv->rx_tfm_mic)
279 crypto_free_hash(priv->rx_tfm_mic);
280}
281
282static int michael_mic(struct crypto_hash *tfm_michael, u8 *key,
283 u8 *da, u8 *sa, u8 priority,
284 u8 *data, size_t data_len, u8 *mic)
285{
286 struct hash_desc desc;
287 struct scatterlist sg[2];
288 u8 hdr[ETH_HLEN + 2]; /* size of header + padding */
289
290 if (tfm_michael == NULL) {
291 printk(KERN_WARNING "michael_mic: tfm_michael == NULL\n");
292 return -1;
293 }
294
295 /* Copy header into buffer. We need the padding on the end zeroed */
296 memcpy(&hdr[0], da, ETH_ALEN);
297 memcpy(&hdr[ETH_ALEN], sa, ETH_ALEN);
298 hdr[ETH_ALEN*2] = priority;
299 hdr[ETH_ALEN*2+1] = 0;
300 hdr[ETH_ALEN*2+2] = 0;
301 hdr[ETH_ALEN*2+3] = 0;
302
303 /* Use scatter gather to MIC header and data in one go */
304 sg_init_table(sg, 2);
305 sg_set_buf(&sg[0], hdr, sizeof(hdr));
306 sg_set_buf(&sg[1], data, data_len);
307
308 if (crypto_hash_setkey(tfm_michael, key, MIC_KEYLEN))
309 return -1;
310
311 desc.tfm = tfm_michael;
312 desc.flags = 0;
313 return crypto_hash_digest(&desc, sg, data_len + sizeof(hdr),
314 mic);
315}
316
317/********************************************************************/
247/* Internal helper functions */ 318/* Internal helper functions */
248/********************************************************************/ 319/********************************************************************/
249 320
@@ -764,7 +835,6 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
764 int err = 0; 835 int err = 0;
765 u16 txfid = priv->txfid; 836 u16 txfid = priv->txfid;
766 struct ethhdr *eh; 837 struct ethhdr *eh;
767 int data_off;
768 int tx_control; 838 int tx_control;
769 unsigned long flags; 839 unsigned long flags;
770 840
@@ -797,10 +867,12 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
797 if (skb->len < ETH_HLEN) 867 if (skb->len < ETH_HLEN)
798 goto drop; 868 goto drop;
799 869
800 eh = (struct ethhdr *)skb->data;
801
802 tx_control = HERMES_TXCTRL_TX_OK | HERMES_TXCTRL_TX_EX; 870 tx_control = HERMES_TXCTRL_TX_OK | HERMES_TXCTRL_TX_EX;
803 871
872 if (priv->encode_alg == IW_ENCODE_ALG_TKIP)
873 tx_control |= (priv->tx_key << HERMES_MIC_KEY_ID_SHIFT) |
874 HERMES_TXCTRL_MIC;
875
804 if (priv->has_alt_txcntl) { 876 if (priv->has_alt_txcntl) {
805 /* WPA enabled firmwares have tx_cntl at the end of 877 /* WPA enabled firmwares have tx_cntl at the end of
806 * the 802.11 header. So write zeroed descriptor and 878 * the 802.11 header. So write zeroed descriptor and
@@ -842,6 +914,8 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
842 HERMES_802_3_OFFSET - HERMES_802_11_OFFSET); 914 HERMES_802_3_OFFSET - HERMES_802_11_OFFSET);
843 } 915 }
844 916
917 eh = (struct ethhdr *)skb->data;
918
845 /* Encapsulate Ethernet-II frames */ 919 /* Encapsulate Ethernet-II frames */
846 if (ntohs(eh->h_proto) > ETH_DATA_LEN) { /* Ethernet-II frame */ 920 if (ntohs(eh->h_proto) > ETH_DATA_LEN) { /* Ethernet-II frame */
847 struct header_struct { 921 struct header_struct {
@@ -851,33 +925,65 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
851 925
852 /* Strip destination and source from the data */ 926 /* Strip destination and source from the data */
853 skb_pull(skb, 2 * ETH_ALEN); 927 skb_pull(skb, 2 * ETH_ALEN);
854 data_off = HERMES_802_2_OFFSET + sizeof(encaps_hdr);
855 928
856 /* And move them to a separate header */ 929 /* And move them to a separate header */
857 memcpy(&hdr.eth, eh, 2 * ETH_ALEN); 930 memcpy(&hdr.eth, eh, 2 * ETH_ALEN);
858 hdr.eth.h_proto = htons(sizeof(encaps_hdr) + skb->len); 931 hdr.eth.h_proto = htons(sizeof(encaps_hdr) + skb->len);
859 memcpy(hdr.encap, encaps_hdr, sizeof(encaps_hdr)); 932 memcpy(hdr.encap, encaps_hdr, sizeof(encaps_hdr));
860 933
861 err = hermes_bap_pwrite(hw, USER_BAP, &hdr, sizeof(hdr), 934 /* Insert the SNAP header */
862 txfid, HERMES_802_3_OFFSET); 935 if (skb_headroom(skb) < sizeof(hdr)) {
863 if (err) { 936 printk(KERN_ERR
864 if (net_ratelimit()) 937 "%s: Not enough headroom for 802.2 headers %d\n",
865 printk(KERN_ERR "%s: Error %d writing packet " 938 dev->name, skb_headroom(skb));
866 "header to BAP\n", dev->name, err); 939 goto drop;
867 goto busy;
868 } 940 }
869 } else { /* IEEE 802.3 frame */ 941 eh = (struct ethhdr *) skb_push(skb, sizeof(hdr));
870 data_off = HERMES_802_3_OFFSET; 942 memcpy(eh, &hdr, sizeof(hdr));
871 } 943 }
872 944
873 err = hermes_bap_pwrite(hw, USER_BAP, skb->data, skb->len, 945 err = hermes_bap_pwrite(hw, USER_BAP, skb->data, skb->len,
874 txfid, data_off); 946 txfid, HERMES_802_3_OFFSET);
875 if (err) { 947 if (err) {
876 printk(KERN_ERR "%s: Error %d writing packet to BAP\n", 948 printk(KERN_ERR "%s: Error %d writing packet to BAP\n",
877 dev->name, err); 949 dev->name, err);
878 goto busy; 950 goto busy;
879 } 951 }
880 952
953 /* Calculate Michael MIC */
954 if (priv->encode_alg == IW_ENCODE_ALG_TKIP) {
955 u8 mic_buf[MICHAEL_MIC_LEN + 1];
956 u8 *mic;
957 size_t offset;
958 size_t len;
959
960 if (skb->len % 2) {
961 /* MIC start is on an odd boundary */
962 mic_buf[0] = skb->data[skb->len - 1];
963 mic = &mic_buf[1];
964 offset = skb->len - 1;
965 len = MICHAEL_MIC_LEN + 1;
966 } else {
967 mic = &mic_buf[0];
968 offset = skb->len;
969 len = MICHAEL_MIC_LEN;
970 }
971
972 michael_mic(priv->tx_tfm_mic,
973 priv->tkip_key[priv->tx_key].tx_mic,
974 eh->h_dest, eh->h_source, 0 /* priority */,
975 skb->data + ETH_HLEN, skb->len - ETH_HLEN, mic);
976
977 /* Write the MIC */
978 err = hermes_bap_pwrite(hw, USER_BAP, &mic_buf[0], len,
979 txfid, HERMES_802_3_OFFSET + offset);
980 if (err) {
981 printk(KERN_ERR "%s: Error %d writing MIC to BAP\n",
982 dev->name, err);
983 goto busy;
984 }
985 }
986
881 /* Finally, we actually initiate the send */ 987 /* Finally, we actually initiate the send */
882 netif_stop_queue(dev); 988 netif_stop_queue(dev);
883 989
@@ -892,7 +998,7 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
892 } 998 }
893 999
894 dev->trans_start = jiffies; 1000 dev->trans_start = jiffies;
895 stats->tx_bytes += data_off + skb->len; 1001 stats->tx_bytes += HERMES_802_3_OFFSET + skb->len;
896 goto ok; 1002 goto ok;
897 1003
898 drop: 1004 drop:
@@ -1172,6 +1278,25 @@ static void orinoco_rx_monitor(struct net_device *dev, u16 rxfid,
1172 stats->rx_dropped++; 1278 stats->rx_dropped++;
1173} 1279}
1174 1280
1281/* Get tsc from the firmware */
1282static int orinoco_hw_get_tkip_iv(struct orinoco_private *priv, int key,
1283 u8 *tsc)
1284{
1285 hermes_t *hw = &priv->hw;
1286 int err = 0;
1287 u8 tsc_arr[4][IW_ENCODE_SEQ_MAX_SIZE];
1288
1289 if ((key < 0) || (key > 4))
1290 return -EINVAL;
1291
1292 err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_TKIP_IV,
1293 sizeof(tsc_arr), NULL, &tsc_arr);
1294 if (!err)
1295 memcpy(tsc, &tsc_arr[key][0], sizeof(tsc_arr[0]));
1296
1297 return err;
1298}
1299
1175static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw) 1300static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
1176{ 1301{
1177 struct orinoco_private *priv = netdev_priv(dev); 1302 struct orinoco_private *priv = netdev_priv(dev);
@@ -1240,6 +1365,11 @@ static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
1240 goto update_stats; 1365 goto update_stats;
1241 } 1366 }
1242 1367
1368 /* Payload size does not include Michael MIC. Increase payload
1369 * size to read it together with the data. */
1370 if (status & HERMES_RXSTAT_MIC)
1371 length += MICHAEL_MIC_LEN;
1372
1243 /* We need space for the packet data itself, plus an ethernet 1373 /* We need space for the packet data itself, plus an ethernet
1244 header, plus 2 bytes so we can align the IP header on a 1374 header, plus 2 bytes so we can align the IP header on a
1245 32bit boundary, plus 1 byte so we can read in odd length 1375 32bit boundary, plus 1 byte so we can read in odd length
@@ -1303,6 +1433,63 @@ static void orinoco_rx(struct net_device *dev,
1303 length = le16_to_cpu(desc->data_len); 1433 length = le16_to_cpu(desc->data_len);
1304 fc = le16_to_cpu(desc->frame_ctl); 1434 fc = le16_to_cpu(desc->frame_ctl);
1305 1435
1436 /* Calculate and check MIC */
1437 if (status & HERMES_RXSTAT_MIC) {
1438 int key_id = ((status & HERMES_RXSTAT_MIC_KEY_ID) >>
1439 HERMES_MIC_KEY_ID_SHIFT);
1440 u8 mic[MICHAEL_MIC_LEN];
1441 u8 *rxmic;
1442 u8 *src = (fc & IEEE80211_FCTL_FROMDS) ?
1443 desc->addr3 : desc->addr2;
1444
1445 /* Extract Michael MIC from payload */
1446 rxmic = skb->data + skb->len - MICHAEL_MIC_LEN;
1447
1448 skb_trim(skb, skb->len - MICHAEL_MIC_LEN);
1449 length -= MICHAEL_MIC_LEN;
1450
1451 michael_mic(priv->rx_tfm_mic,
1452 priv->tkip_key[key_id].rx_mic,
1453 desc->addr1,
1454 src,
1455 0, /* priority or QoS? */
1456 skb->data,
1457 skb->len,
1458 &mic[0]);
1459
1460 if (memcmp(mic, rxmic,
1461 MICHAEL_MIC_LEN)) {
1462 union iwreq_data wrqu;
1463 struct iw_michaelmicfailure wxmic;
1464 DECLARE_MAC_BUF(mac);
1465
1466 printk(KERN_WARNING "%s: "
1467 "Invalid Michael MIC in data frame from %s, "
1468 "using key %i\n",
1469 dev->name, print_mac(mac, src), key_id);
1470
1471 /* TODO: update stats */
1472
1473 /* Notify userspace */
1474 memset(&wxmic, 0, sizeof(wxmic));
1475 wxmic.flags = key_id & IW_MICFAILURE_KEY_ID;
1476 wxmic.flags |= (desc->addr1[0] & 1) ?
1477 IW_MICFAILURE_GROUP : IW_MICFAILURE_PAIRWISE;
1478 wxmic.src_addr.sa_family = ARPHRD_ETHER;
1479 memcpy(wxmic.src_addr.sa_data, src, ETH_ALEN);
1480
1481 (void) orinoco_hw_get_tkip_iv(priv, key_id,
1482 &wxmic.tsc[0]);
1483
1484 memset(&wrqu, 0, sizeof(wrqu));
1485 wrqu.data.length = sizeof(wxmic);
1486 wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu,
1487 (char *) &wxmic);
1488
1489 goto drop;
1490 }
1491 }
1492
1306 /* Handle decapsulation 1493 /* Handle decapsulation
1307 * In most cases, the firmware tell us about SNAP frames. 1494 * In most cases, the firmware tell us about SNAP frames.
1308 * For some reason, the SNAP frames sent by LinkSys APs 1495 * For some reason, the SNAP frames sent by LinkSys APs
@@ -1342,6 +1529,11 @@ static void orinoco_rx(struct net_device *dev,
1342 stats->rx_bytes += length; 1529 stats->rx_bytes += length;
1343 1530
1344 return; 1531 return;
1532
1533 drop:
1534 dev_kfree_skb(skb);
1535 stats->rx_errors++;
1536 stats->rx_dropped++;
1345} 1537}
1346 1538
1347static void orinoco_rx_isr_tasklet(unsigned long data) 1539static void orinoco_rx_isr_tasklet(unsigned long data)
@@ -3112,8 +3304,14 @@ static int orinoco_init(struct net_device *dev)
3112 else 3304 else
3113 printk("40-bit key\n"); 3305 printk("40-bit key\n");
3114 } 3306 }
3115 if (priv->has_wpa) 3307 if (priv->has_wpa) {
3116 printk(KERN_DEBUG "%s: WPA-PSK supported\n", dev->name); 3308 printk(KERN_DEBUG "%s: WPA-PSK supported\n", dev->name);
3309 if (orinoco_mic_init(priv)) {
3310 printk(KERN_ERR "%s: Failed to setup MIC crypto "
3311 "algorithm. Disabling WPA support\n", dev->name);
3312 priv->has_wpa = 0;
3313 }
3314 }
3117 3315
3118 /* Now we have the firmware capabilities, allocate appropiate 3316 /* Now we have the firmware capabilities, allocate appropiate
3119 * sized scan buffers */ 3317 * sized scan buffers */
@@ -3292,6 +3490,9 @@ struct net_device
3292 dev->set_multicast_list = orinoco_set_multicast_list; 3490 dev->set_multicast_list = orinoco_set_multicast_list;
3293 /* we use the default eth_mac_addr for setting the MAC addr */ 3491 /* we use the default eth_mac_addr for setting the MAC addr */
3294 3492
3493 /* Reserve space in skb for the SNAP header */
3494 dev->hard_header_len += ENCAPS_OVERHEAD;
3495
3295 /* Set up default callbacks */ 3496 /* Set up default callbacks */
3296 dev->open = orinoco_open; 3497 dev->open = orinoco_open;
3297 dev->stop = orinoco_stop; 3498 dev->stop = orinoco_stop;
@@ -3327,6 +3528,7 @@ void free_orinocodev(struct net_device *dev)
3327 tasklet_kill(&priv->rx_tasklet); 3528 tasklet_kill(&priv->rx_tasklet);
3328 priv->wpa_ie_len = 0; 3529 priv->wpa_ie_len = 0;
3329 kfree(priv->wpa_ie); 3530 kfree(priv->wpa_ie);
3531 orinoco_mic_free(priv);
3330 orinoco_bss_data_free(priv); 3532 orinoco_bss_data_free(priv);
3331 free_netdev(dev); 3533 free_netdev(dev);
3332} 3534}