aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ipw2200.c
diff options
context:
space:
mode:
authorZhu Yi <yi.zhu@intel.com>2005-08-05 05:22:56 -0400
committerJames Ketrenos <jketreno@linux.intel.com>2005-11-07 18:50:39 -0500
commit1fbfea549f07f1f7afd436f1e45b25437f0172c2 (patch)
tree96dced82fc405eab36695e1f7568c4c77fc77324 /drivers/net/wireless/ipw2200.c
parente402c9374112aaf1fc5796013dc3040ebb3954ca (diff)
[Bug 792] Fix WPA-PSK AES both for -Dipw and -Dwext.
Signed-off-by: Zhu Yi <yi.zhu@intel.com>
Diffstat (limited to 'drivers/net/wireless/ipw2200.c')
-rw-r--r--drivers/net/wireless/ipw2200.c141
1 files changed, 125 insertions, 16 deletions
diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c
index f8dac52df93a..c6da5f534250 100644
--- a/drivers/net/wireless/ipw2200.c
+++ b/drivers/net/wireless/ipw2200.c
@@ -5557,6 +5557,55 @@ static void ipw_send_wep_keys(struct ipw_priv *priv, int type)
5557 } 5557 }
5558} 5558}
5559 5559
5560static void ipw_set_hw_decrypt_unicast(struct ipw_priv *priv, int level)
5561{
5562 if (priv->ieee->host_encrypt)
5563 return;
5564
5565 switch (level) {
5566 case SEC_LEVEL_3:
5567 priv->sys_config.disable_unicast_decryption = 0;
5568 priv->ieee->host_decrypt = 0;
5569 break;
5570 case SEC_LEVEL_2:
5571 priv->sys_config.disable_unicast_decryption = 1;
5572 priv->ieee->host_decrypt = 1;
5573 break;
5574 case SEC_LEVEL_1:
5575 priv->sys_config.disable_unicast_decryption = 0;
5576 priv->ieee->host_decrypt = 0;
5577 break;
5578 case SEC_LEVEL_0:
5579 priv->sys_config.disable_unicast_decryption = 1;
5580 break;
5581 default:
5582 break;
5583 }
5584}
5585
5586static void ipw_set_hw_decrypt_multicast(struct ipw_priv *priv, int level)
5587{
5588 if (priv->ieee->host_encrypt)
5589 return;
5590
5591 switch (level) {
5592 case SEC_LEVEL_3:
5593 priv->sys_config.disable_multicast_decryption = 0;
5594 break;
5595 case SEC_LEVEL_2:
5596 priv->sys_config.disable_multicast_decryption = 1;
5597 break;
5598 case SEC_LEVEL_1:
5599 priv->sys_config.disable_multicast_decryption = 0;
5600 break;
5601 case SEC_LEVEL_0:
5602 priv->sys_config.disable_multicast_decryption = 1;
5603 break;
5604 default:
5605 break;
5606 }
5607}
5608
5560static void ipw_set_hwcrypto_keys(struct ipw_priv *priv) 5609static void ipw_set_hwcrypto_keys(struct ipw_priv *priv)
5561{ 5610{
5562 switch (priv->ieee->sec.level) { 5611 switch (priv->ieee->sec.level) {
@@ -5567,33 +5616,23 @@ static void ipw_set_hwcrypto_keys(struct ipw_priv *priv)
5567 priv->ieee->sec.active_key); 5616 priv->ieee->sec.active_key);
5568 5617
5569 ipw_send_wep_keys(priv, DCW_WEP_KEY_SEC_TYPE_CCM); 5618 ipw_send_wep_keys(priv, DCW_WEP_KEY_SEC_TYPE_CCM);
5570 priv->sys_config.disable_unicast_decryption = 0;
5571 priv->sys_config.disable_multicast_decryption = 0;
5572 priv->ieee->host_decrypt = 0;
5573 break; 5619 break;
5574 case SEC_LEVEL_2: 5620 case SEC_LEVEL_2:
5575 if (priv->ieee->sec.flags & SEC_ACTIVE_KEY) 5621 if (priv->ieee->sec.flags & SEC_ACTIVE_KEY)
5576 ipw_send_tgi_tx_key(priv, 5622 ipw_send_tgi_tx_key(priv,
5577 DCT_FLAG_EXT_SECURITY_TKIP, 5623 DCT_FLAG_EXT_SECURITY_TKIP,
5578 priv->ieee->sec.active_key); 5624 priv->ieee->sec.active_key);
5579
5580 priv->sys_config.disable_unicast_decryption = 1;
5581 priv->sys_config.disable_multicast_decryption = 1;
5582 priv->ieee->host_decrypt = 1;
5583 break; 5625 break;
5584 case SEC_LEVEL_1: 5626 case SEC_LEVEL_1:
5585 ipw_send_wep_keys(priv, DCW_WEP_KEY_SEC_TYPE_WEP); 5627 ipw_send_wep_keys(priv, DCW_WEP_KEY_SEC_TYPE_WEP);
5586 priv->sys_config.disable_unicast_decryption = 0;
5587 priv->sys_config.disable_multicast_decryption = 0;
5588 priv->ieee->host_decrypt = 0;
5589 break; 5628 break;
5590 case SEC_LEVEL_0: 5629 case SEC_LEVEL_0:
5591 priv->sys_config.disable_unicast_decryption = 1;
5592 priv->sys_config.disable_multicast_decryption = 1;
5593 break;
5594 default: 5630 default:
5595 break; 5631 break;
5596 } 5632 }
5633
5634 ipw_set_hw_decrypt_unicast(priv, priv->ieee->sec.level);
5635 ipw_set_hw_decrypt_multicast(priv, priv->ieee->sec.level);
5597} 5636}
5598 5637
5599static void ipw_adhoc_check(void *data) 5638static void ipw_adhoc_check(void *data)
@@ -6185,12 +6224,31 @@ static int ipw_wpa_mlme(struct net_device *dev, int command, int reason)
6185 return ret; 6224 return ret;
6186} 6225}
6187 6226
6227static int ipw_wpa_ie_cipher2level(u8 cipher)
6228{
6229 switch (cipher) {
6230 case 4: /* CCMP */
6231 return SEC_LEVEL_3;
6232 case 2: /* TKIP */
6233 return SEC_LEVEL_2;
6234 case 5: /* WEP104 */
6235 case 1: /* WEP40 */
6236 return SEC_LEVEL_1;
6237 case 0: /* NONE */
6238 return SEC_LEVEL_0;
6239 default:
6240 return -1;
6241 }
6242}
6243
6188static int ipw_wpa_set_wpa_ie(struct net_device *dev, 6244static int ipw_wpa_set_wpa_ie(struct net_device *dev,
6189 struct ipw_param *param, int plen) 6245 struct ipw_param *param, int plen)
6190{ 6246{
6191 struct ipw_priv *priv = ieee80211_priv(dev); 6247 struct ipw_priv *priv = ieee80211_priv(dev);
6192 struct ieee80211_device *ieee = priv->ieee; 6248 struct ieee80211_device *ieee = priv->ieee;
6193 u8 *buf; 6249 u8 *buf;
6250 u8 *ptk, *gtk;
6251 int level;
6194 6252
6195 if (param->u.wpa_ie.len > MAX_WPA_IE_LEN || 6253 if (param->u.wpa_ie.len > MAX_WPA_IE_LEN ||
6196 (param->u.wpa_ie.len && param->u.wpa_ie.data == NULL)) 6254 (param->u.wpa_ie.len && param->u.wpa_ie.data == NULL))
@@ -6209,8 +6267,35 @@ static int ipw_wpa_set_wpa_ie(struct net_device *dev,
6209 kfree(ieee->wpa_ie); 6267 kfree(ieee->wpa_ie);
6210 ieee->wpa_ie = NULL; 6268 ieee->wpa_ie = NULL;
6211 ieee->wpa_ie_len = 0; 6269 ieee->wpa_ie_len = 0;
6270 goto done;
6271 }
6272
6273 if (priv->ieee->host_encrypt)
6274 goto done;
6275
6276 /* HACK: Parse wpa_ie here to get pairwise suite, otherwise
6277 * we need to change driver_ipw.c from wpa_supplicant. This
6278 * is OK since -Dipw is deprecated. The -Dwext driver has a
6279 * clean way to handle this. */
6280 gtk = ptk = (u8 *) ieee->wpa_ie;
6281 if (ieee->wpa_ie[0] == 0x30) { /* RSN IE */
6282 gtk += 4 + 3;
6283 ptk += 4 + 4 + 2 + 3;
6284 } else { /* WPA IE */
6285 gtk += 8 + 3;
6286 ptk += 8 + 4 + 2 + 3;
6212 } 6287 }
6213 6288
6289 if (ptk - (u8 *) ieee->wpa_ie > ieee->wpa_ie_len)
6290 return -EINVAL;
6291
6292 level = ipw_wpa_ie_cipher2level(*gtk);
6293 ipw_set_hw_decrypt_multicast(priv, level);
6294
6295 level = ipw_wpa_ie_cipher2level(*ptk);
6296 ipw_set_hw_decrypt_unicast(priv, level);
6297
6298 done:
6214 ipw_wpa_assoc_frame(priv, ieee->wpa_ie, ieee->wpa_ie_len); 6299 ipw_wpa_assoc_frame(priv, ieee->wpa_ie, ieee->wpa_ie_len);
6215 return 0; 6300 return 0;
6216} 6301}
@@ -6510,6 +6595,23 @@ static int ipw_wx_get_genie(struct net_device *dev,
6510 return err; 6595 return err;
6511} 6596}
6512 6597
6598static int wext_cipher2level(int cipher)
6599{
6600 switch (cipher) {
6601 case IW_AUTH_CIPHER_NONE:
6602 return SEC_LEVEL_0;
6603 case IW_AUTH_CIPHER_WEP40:
6604 case IW_AUTH_CIPHER_WEP104:
6605 return SEC_LEVEL_1;
6606 case IW_AUTH_CIPHER_TKIP:
6607 return SEC_LEVEL_2;
6608 case IW_AUTH_CIPHER_CCMP:
6609 return SEC_LEVEL_3;
6610 default:
6611 return -1;
6612 }
6613}
6614
6513/* SIOCSIWAUTH */ 6615/* SIOCSIWAUTH */
6514static int ipw_wx_set_auth(struct net_device *dev, 6616static int ipw_wx_set_auth(struct net_device *dev,
6515 struct iw_request_info *info, 6617 struct iw_request_info *info,
@@ -6524,8 +6626,15 @@ static int ipw_wx_set_auth(struct net_device *dev,
6524 6626
6525 switch (param->flags & IW_AUTH_INDEX) { 6627 switch (param->flags & IW_AUTH_INDEX) {
6526 case IW_AUTH_WPA_VERSION: 6628 case IW_AUTH_WPA_VERSION:
6629 break;
6527 case IW_AUTH_CIPHER_PAIRWISE: 6630 case IW_AUTH_CIPHER_PAIRWISE:
6631 ipw_set_hw_decrypt_unicast(priv,
6632 wext_cipher2level(param->value));
6633 break;
6528 case IW_AUTH_CIPHER_GROUP: 6634 case IW_AUTH_CIPHER_GROUP:
6635 ipw_set_hw_decrypt_multicast(priv,
6636 wext_cipher2level(param->value));
6637 break;
6529 case IW_AUTH_KEY_MGMT: 6638 case IW_AUTH_KEY_MGMT:
6530 /* 6639 /*
6531 * ipw2200 does not use these parameters 6640 * ipw2200 does not use these parameters
@@ -10256,11 +10365,11 @@ static void shim__set_security(struct net_device *dev,
10256 priv->ieee->sec.level = sec->level; 10365 priv->ieee->sec.level = sec->level;
10257 priv->ieee->sec.flags |= SEC_LEVEL; 10366 priv->ieee->sec.flags |= SEC_LEVEL;
10258 priv->status |= STATUS_SECURITY_UPDATED; 10367 priv->status |= STATUS_SECURITY_UPDATED;
10259
10260 if (!priv->ieee->host_encrypt && (sec->flags & SEC_ENCRYPT))
10261 ipw_set_hwcrypto_keys(priv);
10262 } 10368 }
10263 10369
10370 if (!priv->ieee->host_encrypt && (sec->flags & SEC_ENCRYPT))
10371 ipw_set_hwcrypto_keys(priv);
10372
10264 /* To match current functionality of ipw2100 (which works well w/ 10373 /* To match current functionality of ipw2100 (which works well w/
10265 * various supplicants, we don't force a disassociate if the 10374 * various supplicants, we don't force a disassociate if the
10266 * privacy capability changes ... */ 10375 * privacy capability changes ... */