aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/rndis_wlan.c
diff options
context:
space:
mode:
authorJussi Kivilinna <jussi.kivilinna@mbnet.fi>2009-07-30 12:42:08 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-08-04 16:44:17 -0400
commitb7cfc5b35eed2fe8a5c45793e6e52ef0edddc824 (patch)
tree6831aa9f4e352eb4afa35c336ff4b243a9a1fd44 /drivers/net/wireless/rndis_wlan.c
parent9d40934e5e28314731d4b32acd2fdf5fb805a3ed (diff)
rndis_wlan: rework key handling
Organize key data in private structure better and store WPA keys, so they can be restored as WEP keys. Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/rndis_wlan.c')
-rw-r--r--drivers/net/wireless/rndis_wlan.c188
1 files changed, 142 insertions, 46 deletions
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index 3d92b77d9599..828dc1825bba 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -413,6 +413,15 @@ static const struct ieee80211_rate rndis_rates[] = {
413 { .bitrate = 540 } 413 { .bitrate = 540 }
414}; 414};
415 415
416struct rndis_wlan_encr_key {
417 int len;
418 int cipher;
419 u8 material[32];
420 u8 bssid[ETH_ALEN];
421 bool pairwise;
422 bool tx_key;
423};
424
416/* RNDIS device private data */ 425/* RNDIS device private data */
417struct rndis_wlan_private { 426struct rndis_wlan_private {
418 struct usbnet *usbdev; 427 struct usbnet *usbdev;
@@ -456,9 +465,7 @@ struct rndis_wlan_private {
456 465
457 /* encryption stuff */ 466 /* encryption stuff */
458 int encr_tx_key_index; 467 int encr_tx_key_index;
459 char encr_keys[4][32]; 468 struct rndis_wlan_encr_key encr_keys[4];
460 int encr_key_len[4];
461 char encr_key_wpa[4];
462 int wpa_version; 469 int wpa_version;
463 int wpa_keymgmt; 470 int wpa_keymgmt;
464 int wpa_authalg; 471 int wpa_authalg;
@@ -525,6 +532,15 @@ static u32 get_bcm4320_power_dbm(struct rndis_wlan_private *priv)
525} 532}
526 533
527 534
535static bool is_wpa_key(struct rndis_wlan_private *priv, int idx)
536{
537 int cipher = priv->encr_keys[idx].cipher;
538
539 return (cipher == WLAN_CIPHER_SUITE_CCMP ||
540 cipher == WLAN_CIPHER_SUITE_TKIP);
541}
542
543
528#ifdef DEBUG 544#ifdef DEBUG
529static const char *oid_to_string(__le32 oid) 545static const char *oid_to_string(__le32 oid)
530{ 546{
@@ -895,8 +911,7 @@ static int freq_to_dsconfig(struct iw_freq *freq, unsigned int *dsconfig)
895/* 911/*
896 * common functions 912 * common functions
897 */ 913 */
898static int 914static void restore_keys(struct usbnet *usbdev);
899add_wep_key(struct usbnet *usbdev, char *key, int key_len, int index);
900 915
901static int get_essid(struct usbnet *usbdev, struct ndis_80211_ssid *ssid) 916static int get_essid(struct usbnet *usbdev, struct ndis_80211_ssid *ssid)
902{ 917{
@@ -1115,7 +1130,7 @@ static int set_infra_mode(struct usbnet *usbdev, int mode)
1115{ 1130{
1116 struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); 1131 struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
1117 __le32 tmp; 1132 __le32 tmp;
1118 int ret, i; 1133 int ret;
1119 1134
1120 devdbg(usbdev, "set_infra_mode: infra_mode=0x%x", priv->infra_mode); 1135 devdbg(usbdev, "set_infra_mode: infra_mode=0x%x", priv->infra_mode);
1121 1136
@@ -1130,14 +1145,7 @@ static int set_infra_mode(struct usbnet *usbdev, int mode)
1130 /* NDIS drivers clear keys when infrastructure mode is 1145 /* NDIS drivers clear keys when infrastructure mode is
1131 * changed. But Linux tools assume otherwise. So set the 1146 * changed. But Linux tools assume otherwise. So set the
1132 * keys */ 1147 * keys */
1133 if (priv->wpa_keymgmt == 0 || 1148 restore_keys(usbdev);
1134 priv->wpa_keymgmt == IW_AUTH_KEY_MGMT_802_1X) {
1135 for (i = 0; i < 4; i++) {
1136 if (priv->encr_key_len[i] > 0 && !priv->encr_key_wpa[i])
1137 add_wep_key(usbdev, priv->encr_keys[i],
1138 priv->encr_key_len[i], i);
1139 }
1140 }
1141 1149
1142 priv->infra_mode = mode; 1150 priv->infra_mode = mode;
1143 return 0; 1151 return 0;
@@ -1204,11 +1212,16 @@ static int add_wep_key(struct usbnet *usbdev, char *key, int key_len, int index)
1204{ 1212{
1205 struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); 1213 struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
1206 struct ndis_80211_wep_key ndis_key; 1214 struct ndis_80211_wep_key ndis_key;
1207 int ret; 1215 int cipher, ret;
1208 1216
1209 if (key_len <= 0 || key_len > 32 || index < 0 || index >= 4) 1217 if ((key_len != 5 || key_len != 13) || index < 0 || index > 3)
1210 return -EINVAL; 1218 return -EINVAL;
1211 1219
1220 if (key_len == 5)
1221 cipher = WLAN_CIPHER_SUITE_WEP40;
1222 else
1223 cipher = WLAN_CIPHER_SUITE_WEP104;
1224
1212 memset(&ndis_key, 0, sizeof(ndis_key)); 1225 memset(&ndis_key, 0, sizeof(ndis_key));
1213 1226
1214 ndis_key.size = cpu_to_le32(sizeof(ndis_key)); 1227 ndis_key.size = cpu_to_le32(sizeof(ndis_key));
@@ -1233,30 +1246,44 @@ static int add_wep_key(struct usbnet *usbdev, char *key, int key_len, int index)
1233 return ret; 1246 return ret;
1234 } 1247 }
1235 1248
1236 priv->encr_key_len[index] = key_len; 1249 priv->encr_keys[index].len = key_len;
1237 priv->encr_key_wpa[index] = 0; 1250 priv->encr_keys[index].cipher = cipher;
1238 memcpy(&priv->encr_keys[index], key, key_len); 1251 memcpy(&priv->encr_keys[index].material, key, key_len);
1252 memset(&priv->encr_keys[index].bssid, 0xff, ETH_ALEN);
1239 1253
1240 return 0; 1254 return 0;
1241} 1255}
1242 1256
1243 1257
1244static int add_wpa_key(struct usbnet *usbdev, const u8 *key, int key_len, 1258static int add_wpa_key(struct usbnet *usbdev, const u8 *key, int key_len,
1245 int index, const struct sockaddr *addr, 1259 int index, const u8 *addr, const u8 *rx_seq, int cipher,
1246 const u8 *rx_seq, int alg, int flags) 1260 int flags)
1247{ 1261{
1248 struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); 1262 struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
1249 struct ndis_80211_key ndis_key; 1263 struct ndis_80211_key ndis_key;
1264 bool is_addr_ok;
1250 int ret; 1265 int ret;
1251 1266
1252 if (index < 0 || index >= 4) 1267 if (index < 0 || index >= 4) {
1268 devdbg(usbdev, "add_wpa_key: index out of range (%i)", index);
1253 return -EINVAL; 1269 return -EINVAL;
1254 if (key_len > sizeof(ndis_key.material) || key_len < 0) 1270 }
1271 if (key_len > sizeof(ndis_key.material) || key_len < 0) {
1272 devdbg(usbdev, "add_wpa_key: key length out of range (%i)",
1273 key_len);
1255 return -EINVAL; 1274 return -EINVAL;
1256 if ((flags & NDIS_80211_ADDKEY_SET_INIT_RECV_SEQ) && !rx_seq) 1275 }
1276 if ((flags & NDIS_80211_ADDKEY_SET_INIT_RECV_SEQ) && !rx_seq) {
1277 devdbg(usbdev, "add_wpa_key: recv seq flag without buffer");
1257 return -EINVAL; 1278 return -EINVAL;
1258 if ((flags & NDIS_80211_ADDKEY_PAIRWISE_KEY) && !addr) 1279 }
1280 is_addr_ok = addr && memcmp(addr, zero_bssid, ETH_ALEN) != 0 &&
1281 memcmp(addr, ffff_bssid, ETH_ALEN) != 0;
1282 if ((flags & NDIS_80211_ADDKEY_PAIRWISE_KEY) && !is_addr_ok) {
1283 devdbg(usbdev, "add_wpa_key: pairwise but bssid invalid (%pM)",
1284 addr);
1259 return -EINVAL; 1285 return -EINVAL;
1286 }
1260 1287
1261 devdbg(usbdev, "add_wpa_key(%i): flags:%i%i%i", index, 1288 devdbg(usbdev, "add_wpa_key(%i): flags:%i%i%i", index,
1262 !!(flags & NDIS_80211_ADDKEY_TRANSMIT_KEY), 1289 !!(flags & NDIS_80211_ADDKEY_TRANSMIT_KEY),
@@ -1270,7 +1297,7 @@ static int add_wpa_key(struct usbnet *usbdev, const u8 *key, int key_len,
1270 ndis_key.length = cpu_to_le32(key_len); 1297 ndis_key.length = cpu_to_le32(key_len);
1271 ndis_key.index = cpu_to_le32(index) | flags; 1298 ndis_key.index = cpu_to_le32(index) | flags;
1272 1299
1273 if (alg == IW_ENCODE_ALG_TKIP && key_len == 32) { 1300 if (cipher == WLAN_CIPHER_SUITE_TKIP && key_len == 32) {
1274 /* wpa_supplicant gives us the Michael MIC RX/TX keys in 1301 /* wpa_supplicant gives us the Michael MIC RX/TX keys in
1275 * different order than NDIS spec, so swap the order here. */ 1302 * different order than NDIS spec, so swap the order here. */
1276 memcpy(ndis_key.material, key, 16); 1303 memcpy(ndis_key.material, key, 16);
@@ -1284,7 +1311,7 @@ static int add_wpa_key(struct usbnet *usbdev, const u8 *key, int key_len,
1284 1311
1285 if (flags & NDIS_80211_ADDKEY_PAIRWISE_KEY) { 1312 if (flags & NDIS_80211_ADDKEY_PAIRWISE_KEY) {
1286 /* pairwise key */ 1313 /* pairwise key */
1287 memcpy(ndis_key.bssid, addr->sa_data, ETH_ALEN); 1314 memcpy(ndis_key.bssid, addr, ETH_ALEN);
1288 } else { 1315 } else {
1289 /* group key */ 1316 /* group key */
1290 if (priv->infra_mode == NDIS_80211_INFRA_ADHOC) 1317 if (priv->infra_mode == NDIS_80211_INFRA_ADHOC)
@@ -1299,8 +1326,14 @@ static int add_wpa_key(struct usbnet *usbdev, const u8 *key, int key_len,
1299 if (ret != 0) 1326 if (ret != 0)
1300 return ret; 1327 return ret;
1301 1328
1302 priv->encr_key_len[index] = key_len; 1329 memset(&priv->encr_keys[index], 0, sizeof(priv->encr_keys[index]));
1303 priv->encr_key_wpa[index] = 1; 1330 priv->encr_keys[index].len = key_len;
1331 priv->encr_keys[index].cipher = cipher;
1332 memcpy(&priv->encr_keys[index].material, key, key_len);
1333 if (flags & NDIS_80211_ADDKEY_PAIRWISE_KEY)
1334 memcpy(&priv->encr_keys[index].bssid, ndis_key.bssid, ETH_ALEN);
1335 else
1336 memset(&priv->encr_keys[index].bssid, 0xff, ETH_ALEN);
1304 1337
1305 if (flags & NDIS_80211_ADDKEY_TRANSMIT_KEY) 1338 if (flags & NDIS_80211_ADDKEY_TRANSMIT_KEY)
1306 priv->encr_tx_key_index = index; 1339 priv->encr_tx_key_index = index;
@@ -1309,25 +1342,74 @@ static int add_wpa_key(struct usbnet *usbdev, const u8 *key, int key_len,
1309} 1342}
1310 1343
1311 1344
1345static int restore_key(struct usbnet *usbdev, int key_idx)
1346{
1347 struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
1348 struct rndis_wlan_encr_key key;
1349 int flags;
1350
1351 key = priv->encr_keys[key_idx];
1352
1353 devdbg(usbdev, "restore_key: %i:%s:%i", key_idx,
1354 is_wpa_key(priv, key_idx) ? "wpa" : "wep",
1355 key.len);
1356
1357 if (key.len == 0)
1358 return 0;
1359
1360 if (is_wpa_key(priv, key_idx)) {
1361 flags = 0;
1362
1363 /*if (priv->encr_tx_key_index == key_idx)
1364 flags |= NDIS_80211_ADDKEY_TRANSMIT_KEY;*/
1365
1366 if (memcmp(key.bssid, zero_bssid, ETH_ALEN) != 0 &&
1367 memcmp(key.bssid, ffff_bssid, ETH_ALEN) != 0)
1368 flags |= NDIS_80211_ADDKEY_PAIRWISE_KEY;
1369
1370 return add_wpa_key(usbdev, key.material, key.len, key_idx,
1371 key.bssid, NULL, key.cipher, flags);
1372 }
1373
1374 return add_wep_key(usbdev, key.material, key.len, key_idx);
1375}
1376
1377
1378static void restore_keys(struct usbnet *usbdev)
1379{
1380 int i;
1381
1382 for (i = 0; i < 4; i++)
1383 restore_key(usbdev, i);
1384}
1385
1386
1387static void clear_key(struct rndis_wlan_private *priv, int idx)
1388{
1389 memset(&priv->encr_keys[idx], 0, sizeof(priv->encr_keys[idx]));
1390}
1391
1392
1312/* remove_key is for both wep and wpa */ 1393/* remove_key is for both wep and wpa */
1313static int remove_key(struct usbnet *usbdev, int index, u8 bssid[ETH_ALEN]) 1394static int remove_key(struct usbnet *usbdev, int index, u8 bssid[ETH_ALEN])
1314{ 1395{
1315 struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); 1396 struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
1316 struct ndis_80211_remove_key remove_key; 1397 struct ndis_80211_remove_key remove_key;
1317 __le32 keyindex; 1398 __le32 keyindex;
1399 bool is_wpa;
1318 int ret; 1400 int ret;
1319 1401
1320 if (priv->encr_key_len[index] == 0) 1402 if (priv->encr_keys[index].len == 0)
1321 return 0; 1403 return 0;
1322 1404
1323 priv->encr_key_len[index] = 0; 1405 is_wpa = is_wpa_key(priv, index);
1324 priv->encr_key_wpa[index] = 0;
1325 memset(&priv->encr_keys[index], 0, sizeof(priv->encr_keys[index]));
1326 1406
1327 if (priv->wpa_cipher_pair == IW_AUTH_CIPHER_TKIP || 1407 devdbg(usbdev, "remove_key: %i:%s:%i", index, is_wpa ? "wpa" : "wep",
1328 priv->wpa_cipher_pair == IW_AUTH_CIPHER_CCMP || 1408 priv->encr_keys[index].len);
1329 priv->wpa_cipher_group == IW_AUTH_CIPHER_TKIP || 1409
1330 priv->wpa_cipher_group == IW_AUTH_CIPHER_CCMP) { 1410 clear_key(priv, index);
1411
1412 if (is_wpa) {
1331 remove_key.size = cpu_to_le32(sizeof(remove_key)); 1413 remove_key.size = cpu_to_le32(sizeof(remove_key));
1332 remove_key.index = cpu_to_le32(index); 1414 remove_key.index = cpu_to_le32(index);
1333 if (bssid) { 1415 if (bssid) {
@@ -1871,8 +1953,9 @@ static int rndis_iw_set_encode(struct net_device *dev,
1871{ 1953{
1872 struct usbnet *usbdev = netdev_priv(dev); 1954 struct usbnet *usbdev = netdev_priv(dev);
1873 struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); 1955 struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
1956 struct rndis_wlan_encr_key key;
1874 int ret, index, key_len; 1957 int ret, index, key_len;
1875 u8 *key; 1958 u8 *keybuf;
1876 1959
1877 index = (wrqu->encoding.flags & IW_ENCODE_INDEX); 1960 index = (wrqu->encoding.flags & IW_ENCODE_INDEX);
1878 1961
@@ -1907,17 +1990,18 @@ static int rndis_iw_set_encode(struct net_device *dev,
1907 1990
1908 if (wrqu->data.length > 0) { 1991 if (wrqu->data.length > 0) {
1909 key_len = wrqu->data.length; 1992 key_len = wrqu->data.length;
1910 key = extra; 1993 keybuf = extra;
1911 } else { 1994 } else {
1912 /* must be set as tx key */ 1995 /* must be set as tx key */
1913 if (priv->encr_key_len[index] == 0) 1996 if (priv->encr_keys[index].len == 0)
1914 return -EINVAL; 1997 return -EINVAL;
1915 key_len = priv->encr_key_len[index];
1916 key = priv->encr_keys[index]; 1998 key = priv->encr_keys[index];
1999 key_len = key.len;
2000 keybuf = key.material;
1917 priv->encr_tx_key_index = index; 2001 priv->encr_tx_key_index = index;
1918 } 2002 }
1919 2003
1920 if (add_wep_key(usbdev, key, key_len, index) != 0) 2004 if (add_wep_key(usbdev, keybuf, key_len, index) != 0)
1921 return -EINVAL; 2005 return -EINVAL;
1922 2006
1923 if (index == priv->encr_tx_key_index) 2007 if (index == priv->encr_tx_key_index)
@@ -1934,7 +2018,7 @@ static int rndis_iw_set_encode_ext(struct net_device *dev,
1934 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; 2018 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
1935 struct usbnet *usbdev = netdev_priv(dev); 2019 struct usbnet *usbdev = netdev_priv(dev);
1936 struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); 2020 struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
1937 int keyidx, flags; 2021 int keyidx, flags, cipher;
1938 2022
1939 keyidx = wrqu->encoding.flags & IW_ENCODE_INDEX; 2023 keyidx = wrqu->encoding.flags & IW_ENCODE_INDEX;
1940 2024
@@ -1944,8 +2028,10 @@ static int rndis_iw_set_encode_ext(struct net_device *dev,
1944 else 2028 else
1945 keyidx = priv->encr_tx_key_index; 2029 keyidx = priv->encr_tx_key_index;
1946 2030
1947 if (keyidx < 0 || keyidx >= 4) 2031 if (keyidx < 0 || keyidx >= 4) {
2032 devwarn(usbdev, "encryption index out of range (%u)", keyidx);
1948 return -EINVAL; 2033 return -EINVAL;
2034 }
1949 2035
1950 if (ext->alg == WPA_ALG_WEP) { 2036 if (ext->alg == WPA_ALG_WEP) {
1951 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) 2037 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
@@ -1953,10 +2039,19 @@ static int rndis_iw_set_encode_ext(struct net_device *dev,
1953 return add_wep_key(usbdev, ext->key, ext->key_len, keyidx); 2039 return add_wep_key(usbdev, ext->key, ext->key_len, keyidx);
1954 } 2040 }
1955 2041
2042 cipher = -1;
2043 if (ext->alg == IW_ENCODE_ALG_TKIP)
2044 cipher = WLAN_CIPHER_SUITE_TKIP;
2045 else if (ext->alg == IW_ENCODE_ALG_CCMP)
2046 cipher = WLAN_CIPHER_SUITE_CCMP;
2047
1956 if ((wrqu->encoding.flags & IW_ENCODE_DISABLED) || 2048 if ((wrqu->encoding.flags & IW_ENCODE_DISABLED) ||
1957 ext->alg == IW_ENCODE_ALG_NONE || ext->key_len == 0) 2049 ext->alg == IW_ENCODE_ALG_NONE || ext->key_len == 0)
1958 return remove_key(usbdev, keyidx, NULL); 2050 return remove_key(usbdev, keyidx, NULL);
1959 2051
2052 if (cipher == -1)
2053 return -EOPNOTSUPP;
2054
1960 flags = 0; 2055 flags = 0;
1961 if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) 2056 if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID)
1962 flags |= NDIS_80211_ADDKEY_SET_INIT_RECV_SEQ; 2057 flags |= NDIS_80211_ADDKEY_SET_INIT_RECV_SEQ;
@@ -1965,8 +2060,9 @@ static int rndis_iw_set_encode_ext(struct net_device *dev,
1965 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) 2060 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
1966 flags |= NDIS_80211_ADDKEY_TRANSMIT_KEY; 2061 flags |= NDIS_80211_ADDKEY_TRANSMIT_KEY;
1967 2062
1968 return add_wpa_key(usbdev, ext->key, ext->key_len, keyidx, &ext->addr, 2063 return add_wpa_key(usbdev, ext->key, ext->key_len, keyidx,
1969 ext->rx_seq, ext->alg, flags); 2064 (u8 *)&ext->addr.sa_data, ext->rx_seq, cipher,
2065 flags);
1970} 2066}
1971 2067
1972 2068