Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

David Kilroy and committed by
John W. Linville
23edcc41 31afcef3

+229 -16
+2
drivers/net/wireless/Kconfig
··· 336 336 depends on (PPC_PMAC || PCI || PCMCIA) && WLAN_80211 337 337 select WIRELESS_EXT 338 338 select FW_LOADER 339 + select CRYPTO 340 + select CRYPTO_MICHAEL_MIC 339 341 ---help--- 340 342 A driver for 802.11b wireless cards based on the "Hermes" or 341 343 Intersil HFA384x (Prism 2) MAC controller. This includes the vast
+7
drivers/net/wireless/hermes.h
··· 184 184 #define HERMES_RXSTAT_ERR (0x0003) 185 185 #define HERMES_RXSTAT_BADCRC (0x0001) 186 186 #define HERMES_RXSTAT_UNDECRYPTABLE (0x0002) 187 + #define HERMES_RXSTAT_MIC (0x0010) /* Frame contains MIC */ 187 188 #define HERMES_RXSTAT_MACPORT (0x0700) 188 189 #define HERMES_RXSTAT_PCF (0x1000) /* Frame was received in CF period */ 190 + #define HERMES_RXSTAT_MIC_KEY_ID (0x1800) /* MIC key used */ 189 191 #define HERMES_RXSTAT_MSGTYPE (0xE000) 190 192 #define HERMES_RXSTAT_1042 (0x2000) /* RFC-1042 frame */ 191 193 #define HERMES_RXSTAT_TUNNEL (0x4000) /* bridge-tunnel encoded frame */ 192 194 #define HERMES_RXSTAT_WMP (0x6000) /* Wavelan-II Management Protocol frame */ 195 + 196 + /* Shift amount for key ID in RXSTAT and TXCTRL */ 197 + #define HERMES_MIC_KEY_ID_SHIFT 11 193 198 194 199 struct hermes_tx_descriptor { 195 200 __le16 status; ··· 214 209 #define HERMES_TXCTRL_TX_OK (0x0002) /* ?? interrupt on Tx complete */ 215 210 #define HERMES_TXCTRL_TX_EX (0x0004) /* ?? interrupt on Tx exception */ 216 211 #define HERMES_TXCTRL_802_11 (0x0008) /* We supply 802.11 header */ 212 + #define HERMES_TXCTRL_MIC (0x0010) /* 802.3 + TKIP */ 213 + #define HERMES_TXCTRL_MIC_KEY_ID (0x1800) /* MIC Key ID mask */ 217 214 #define HERMES_TXCTRL_ALT_RTRY (0x0020) 218 215 219 216 /* Inquiry constants and data types */
+218 -16
drivers/net/wireless/orinoco.c
··· 89 89 #include <net/iw_handler.h> 90 90 #include <net/ieee80211.h> 91 91 92 + #include <linux/scatterlist.h> 93 + #include <linux/crypto.h> 94 + 92 95 #include "hermes_rid.h" 93 96 #include "hermes_dld.h" 94 97 #include "orinoco.h" ··· 245 242 246 243 static int __orinoco_program_rids(struct net_device *dev); 247 244 static void __orinoco_set_multicast_list(struct net_device *dev); 245 + 246 + /********************************************************************/ 247 + /* Michael MIC crypto setup */ 248 + /********************************************************************/ 249 + #define MICHAEL_MIC_LEN 8 250 + static int orinoco_mic_init(struct orinoco_private *priv) 251 + { 252 + priv->tx_tfm_mic = crypto_alloc_hash("michael_mic", 0, 0); 253 + if (IS_ERR(priv->tx_tfm_mic)) { 254 + printk(KERN_DEBUG "orinoco_mic_init: could not allocate " 255 + "crypto API michael_mic\n"); 256 + priv->tx_tfm_mic = NULL; 257 + return -ENOMEM; 258 + } 259 + 260 + priv->rx_tfm_mic = crypto_alloc_hash("michael_mic", 0, 0); 261 + if (IS_ERR(priv->rx_tfm_mic)) { 262 + printk(KERN_DEBUG "orinoco_mic_init: could not allocate " 263 + "crypto API michael_mic\n"); 264 + priv->rx_tfm_mic = NULL; 265 + return -ENOMEM; 266 + } 267 + 268 + return 0; 269 + } 270 + 271 + static void orinoco_mic_free(struct orinoco_private *priv) 272 + { 273 + if (priv->tx_tfm_mic) 274 + crypto_free_hash(priv->tx_tfm_mic); 275 + if (priv->rx_tfm_mic) 276 + crypto_free_hash(priv->rx_tfm_mic); 277 + } 278 + 279 + static int michael_mic(struct crypto_hash *tfm_michael, u8 *key, 280 + u8 *da, u8 *sa, u8 priority, 281 + u8 *data, size_t data_len, u8 *mic) 282 + { 283 + struct hash_desc desc; 284 + struct scatterlist sg[2]; 285 + u8 hdr[ETH_HLEN + 2]; /* size of header + padding */ 286 + 287 + if (tfm_michael == NULL) { 288 + printk(KERN_WARNING "michael_mic: tfm_michael == NULL\n"); 289 + return -1; 290 + } 291 + 292 + /* Copy header into buffer. We need the padding on the end zeroed */ 293 + memcpy(&hdr[0], da, ETH_ALEN); 294 + memcpy(&hdr[ETH_ALEN], sa, ETH_ALEN); 295 + hdr[ETH_ALEN*2] = priority; 296 + hdr[ETH_ALEN*2+1] = 0; 297 + hdr[ETH_ALEN*2+2] = 0; 298 + hdr[ETH_ALEN*2+3] = 0; 299 + 300 + /* Use scatter gather to MIC header and data in one go */ 301 + sg_init_table(sg, 2); 302 + sg_set_buf(&sg[0], hdr, sizeof(hdr)); 303 + sg_set_buf(&sg[1], data, data_len); 304 + 305 + if (crypto_hash_setkey(tfm_michael, key, MIC_KEYLEN)) 306 + return -1; 307 + 308 + desc.tfm = tfm_michael; 309 + desc.flags = 0; 310 + return crypto_hash_digest(&desc, sg, data_len + sizeof(hdr), 311 + mic); 312 + } 248 313 249 314 /********************************************************************/ 250 315 /* Internal helper functions */ ··· 835 764 int err = 0; 836 765 u16 txfid = priv->txfid; 837 766 struct ethhdr *eh; 838 - int data_off; 839 767 int tx_control; 840 768 unsigned long flags; 841 769 ··· 867 797 if (skb->len < ETH_HLEN) 868 798 goto drop; 869 799 870 - eh = (struct ethhdr *)skb->data; 871 - 872 800 tx_control = HERMES_TXCTRL_TX_OK | HERMES_TXCTRL_TX_EX; 801 + 802 + if (priv->encode_alg == IW_ENCODE_ALG_TKIP) 803 + tx_control |= (priv->tx_key << HERMES_MIC_KEY_ID_SHIFT) | 804 + HERMES_TXCTRL_MIC; 873 805 874 806 if (priv->has_alt_txcntl) { 875 807 /* WPA enabled firmwares have tx_cntl at the end of ··· 914 842 HERMES_802_3_OFFSET - HERMES_802_11_OFFSET); 915 843 } 916 844 845 + eh = (struct ethhdr *)skb->data; 846 + 917 847 /* Encapsulate Ethernet-II frames */ 918 848 if (ntohs(eh->h_proto) > ETH_DATA_LEN) { /* Ethernet-II frame */ 919 849 struct header_struct { ··· 925 851 926 852 /* Strip destination and source from the data */ 927 853 skb_pull(skb, 2 * ETH_ALEN); 928 - data_off = HERMES_802_2_OFFSET + sizeof(encaps_hdr); 929 854 930 855 /* And move them to a separate header */ 931 856 memcpy(&hdr.eth, eh, 2 * ETH_ALEN); 932 857 hdr.eth.h_proto = htons(sizeof(encaps_hdr) + skb->len); 933 858 memcpy(hdr.encap, encaps_hdr, sizeof(encaps_hdr)); 934 859 935 - err = hermes_bap_pwrite(hw, USER_BAP, &hdr, sizeof(hdr), 936 - txfid, HERMES_802_3_OFFSET); 937 - if (err) { 938 - if (net_ratelimit()) 939 - printk(KERN_ERR "%s: Error %d writing packet " 940 - "header to BAP\n", dev->name, err); 941 - goto busy; 860 + /* Insert the SNAP header */ 861 + if (skb_headroom(skb) < sizeof(hdr)) { 862 + printk(KERN_ERR 863 + "%s: Not enough headroom for 802.2 headers %d\n", 864 + dev->name, skb_headroom(skb)); 865 + goto drop; 942 866 } 943 - } else { /* IEEE 802.3 frame */ 944 - data_off = HERMES_802_3_OFFSET; 867 + eh = (struct ethhdr *) skb_push(skb, sizeof(hdr)); 868 + memcpy(eh, &hdr, sizeof(hdr)); 945 869 } 946 870 947 871 err = hermes_bap_pwrite(hw, USER_BAP, skb->data, skb->len, 948 - txfid, data_off); 872 + txfid, HERMES_802_3_OFFSET); 949 873 if (err) { 950 874 printk(KERN_ERR "%s: Error %d writing packet to BAP\n", 951 875 dev->name, err); 952 876 goto busy; 877 + } 878 + 879 + /* Calculate Michael MIC */ 880 + if (priv->encode_alg == IW_ENCODE_ALG_TKIP) { 881 + u8 mic_buf[MICHAEL_MIC_LEN + 1]; 882 + u8 *mic; 883 + size_t offset; 884 + size_t len; 885 + 886 + if (skb->len % 2) { 887 + /* MIC start is on an odd boundary */ 888 + mic_buf[0] = skb->data[skb->len - 1]; 889 + mic = &mic_buf[1]; 890 + offset = skb->len - 1; 891 + len = MICHAEL_MIC_LEN + 1; 892 + } else { 893 + mic = &mic_buf[0]; 894 + offset = skb->len; 895 + len = MICHAEL_MIC_LEN; 896 + } 897 + 898 + michael_mic(priv->tx_tfm_mic, 899 + priv->tkip_key[priv->tx_key].tx_mic, 900 + eh->h_dest, eh->h_source, 0 /* priority */, 901 + skb->data + ETH_HLEN, skb->len - ETH_HLEN, mic); 902 + 903 + /* Write the MIC */ 904 + err = hermes_bap_pwrite(hw, USER_BAP, &mic_buf[0], len, 905 + txfid, HERMES_802_3_OFFSET + offset); 906 + if (err) { 907 + printk(KERN_ERR "%s: Error %d writing MIC to BAP\n", 908 + dev->name, err); 909 + goto busy; 910 + } 953 911 } 954 912 955 913 /* Finally, we actually initiate the send */ ··· 998 892 } 999 893 1000 894 dev->trans_start = jiffies; 1001 - stats->tx_bytes += data_off + skb->len; 895 + stats->tx_bytes += HERMES_802_3_OFFSET + skb->len; 1002 896 goto ok; 1003 897 1004 898 drop: ··· 1278 1172 stats->rx_dropped++; 1279 1173 } 1280 1174 1175 + /* Get tsc from the firmware */ 1176 + static int orinoco_hw_get_tkip_iv(struct orinoco_private *priv, int key, 1177 + u8 *tsc) 1178 + { 1179 + hermes_t *hw = &priv->hw; 1180 + int err = 0; 1181 + u8 tsc_arr[4][IW_ENCODE_SEQ_MAX_SIZE]; 1182 + 1183 + if ((key < 0) || (key > 4)) 1184 + return -EINVAL; 1185 + 1186 + err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_TKIP_IV, 1187 + sizeof(tsc_arr), NULL, &tsc_arr); 1188 + if (!err) 1189 + memcpy(tsc, &tsc_arr[key][0], sizeof(tsc_arr[0])); 1190 + 1191 + return err; 1192 + } 1193 + 1281 1194 static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw) 1282 1195 { 1283 1196 struct orinoco_private *priv = netdev_priv(dev); ··· 1365 1240 goto update_stats; 1366 1241 } 1367 1242 1243 + /* Payload size does not include Michael MIC. Increase payload 1244 + * size to read it together with the data. */ 1245 + if (status & HERMES_RXSTAT_MIC) 1246 + length += MICHAEL_MIC_LEN; 1247 + 1368 1248 /* We need space for the packet data itself, plus an ethernet 1369 1249 header, plus 2 bytes so we can align the IP header on a 1370 1250 32bit boundary, plus 1 byte so we can read in odd length ··· 1433 1303 length = le16_to_cpu(desc->data_len); 1434 1304 fc = le16_to_cpu(desc->frame_ctl); 1435 1305 1306 + /* Calculate and check MIC */ 1307 + if (status & HERMES_RXSTAT_MIC) { 1308 + int key_id = ((status & HERMES_RXSTAT_MIC_KEY_ID) >> 1309 + HERMES_MIC_KEY_ID_SHIFT); 1310 + u8 mic[MICHAEL_MIC_LEN]; 1311 + u8 *rxmic; 1312 + u8 *src = (fc & IEEE80211_FCTL_FROMDS) ? 1313 + desc->addr3 : desc->addr2; 1314 + 1315 + /* Extract Michael MIC from payload */ 1316 + rxmic = skb->data + skb->len - MICHAEL_MIC_LEN; 1317 + 1318 + skb_trim(skb, skb->len - MICHAEL_MIC_LEN); 1319 + length -= MICHAEL_MIC_LEN; 1320 + 1321 + michael_mic(priv->rx_tfm_mic, 1322 + priv->tkip_key[key_id].rx_mic, 1323 + desc->addr1, 1324 + src, 1325 + 0, /* priority or QoS? */ 1326 + skb->data, 1327 + skb->len, 1328 + &mic[0]); 1329 + 1330 + if (memcmp(mic, rxmic, 1331 + MICHAEL_MIC_LEN)) { 1332 + union iwreq_data wrqu; 1333 + struct iw_michaelmicfailure wxmic; 1334 + DECLARE_MAC_BUF(mac); 1335 + 1336 + printk(KERN_WARNING "%s: " 1337 + "Invalid Michael MIC in data frame from %s, " 1338 + "using key %i\n", 1339 + dev->name, print_mac(mac, src), key_id); 1340 + 1341 + /* TODO: update stats */ 1342 + 1343 + /* Notify userspace */ 1344 + memset(&wxmic, 0, sizeof(wxmic)); 1345 + wxmic.flags = key_id & IW_MICFAILURE_KEY_ID; 1346 + wxmic.flags |= (desc->addr1[0] & 1) ? 1347 + IW_MICFAILURE_GROUP : IW_MICFAILURE_PAIRWISE; 1348 + wxmic.src_addr.sa_family = ARPHRD_ETHER; 1349 + memcpy(wxmic.src_addr.sa_data, src, ETH_ALEN); 1350 + 1351 + (void) orinoco_hw_get_tkip_iv(priv, key_id, 1352 + &wxmic.tsc[0]); 1353 + 1354 + memset(&wrqu, 0, sizeof(wrqu)); 1355 + wrqu.data.length = sizeof(wxmic); 1356 + wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu, 1357 + (char *) &wxmic); 1358 + 1359 + goto drop; 1360 + } 1361 + } 1362 + 1436 1363 /* Handle decapsulation 1437 1364 * In most cases, the firmware tell us about SNAP frames. 1438 1365 * For some reason, the SNAP frames sent by LinkSys APs ··· 1529 1342 stats->rx_bytes += length; 1530 1343 1531 1344 return; 1345 + 1346 + drop: 1347 + dev_kfree_skb(skb); 1348 + stats->rx_errors++; 1349 + stats->rx_dropped++; 1532 1350 } 1533 1351 1534 1352 static void orinoco_rx_isr_tasklet(unsigned long data) ··· 3304 3112 else 3305 3113 printk("40-bit key\n"); 3306 3114 } 3307 - if (priv->has_wpa) 3115 + if (priv->has_wpa) { 3308 3116 printk(KERN_DEBUG "%s: WPA-PSK supported\n", dev->name); 3117 + if (orinoco_mic_init(priv)) { 3118 + printk(KERN_ERR "%s: Failed to setup MIC crypto " 3119 + "algorithm. Disabling WPA support\n", dev->name); 3120 + priv->has_wpa = 0; 3121 + } 3122 + } 3309 3123 3310 3124 /* Now we have the firmware capabilities, allocate appropiate 3311 3125 * sized scan buffers */ ··· 3490 3292 dev->set_multicast_list = orinoco_set_multicast_list; 3491 3293 /* we use the default eth_mac_addr for setting the MAC addr */ 3492 3294 3295 + /* Reserve space in skb for the SNAP header */ 3296 + dev->hard_header_len += ENCAPS_OVERHEAD; 3297 + 3493 3298 /* Set up default callbacks */ 3494 3299 dev->open = orinoco_open; 3495 3300 dev->stop = orinoco_stop; ··· 3528 3327 tasklet_kill(&priv->rx_tasklet); 3529 3328 priv->wpa_ie_len = 0; 3530 3329 kfree(priv->wpa_ie); 3330 + orinoco_mic_free(priv); 3531 3331 orinoco_bss_data_free(priv); 3532 3332 free_netdev(dev); 3533 3333 }
+2
drivers/net/wireless/orinoco.h
··· 158 158 int wpa_ie_len; 159 159 160 160 struct orinoco_tkip_key tkip_key[ORINOCO_MAX_KEYS]; 161 + struct crypto_hash *rx_tfm_mic; 162 + struct crypto_hash *tx_tfm_mic; 161 163 162 164 unsigned int wpa_enabled:1; 163 165 unsigned int tkip_cm_active:1;