Commit 90a42210 authored by Dan Williams's avatar Dan Williams Committed by John W. Linville

[PATCH] libertas: Make WPA work through supplicant handshake

Fix WPA so it works up through the supplicant 4-Way handshake process.
Doesn't successfully pass traffic yet; may be problems installing
the GTK to the firmware.

- RSN needs to be enabled before the association command is sent
- Use keys from the association request not the adapter structure
- cmd_act_mac_strict_protection_enable != IW_AUTH_DROP_UNENCRYPTED
- Fix network filtering logic in is_network_compatible() WPA helpers
Signed-off-by: default avatarDan Williams <dcbw@redhat.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 45f43de8
...@@ -347,7 +347,17 @@ static int assoc_helper_secinfo(wlan_private *priv, ...@@ -347,7 +347,17 @@ static int assoc_helper_secinfo(wlan_private *priv,
sizeof(struct wlan_802_11_security)); sizeof(struct wlan_802_11_security));
ret = libertas_set_mac_packet_filter(priv); ret = libertas_set_mac_packet_filter(priv);
if (ret)
goto out;
/* enable/disable RSN */
ret = libertas_prepare_and_send_command(priv,
cmd_802_11_enable_rsn,
cmd_act_set,
cmd_option_waitforrsp,
0, assoc_req);
out:
lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
return ret; return ret;
} }
...@@ -360,22 +370,12 @@ static int assoc_helper_wpa_keys(wlan_private *priv, ...@@ -360,22 +370,12 @@ static int assoc_helper_wpa_keys(wlan_private *priv,
lbs_deb_enter(LBS_DEB_ASSOC); lbs_deb_enter(LBS_DEB_ASSOC);
/* enable/Disable RSN */
ret = libertas_prepare_and_send_command(priv,
cmd_802_11_enable_rsn,
cmd_act_set,
cmd_option_waitforrsp,
0, assoc_req);
if (ret)
goto out;
ret = libertas_prepare_and_send_command(priv, ret = libertas_prepare_and_send_command(priv,
cmd_802_11_key_material, cmd_802_11_key_material,
cmd_act_set, cmd_act_set,
cmd_option_waitforrsp, cmd_option_waitforrsp,
0, assoc_req); 0, assoc_req);
out:
lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
return ret; return ret;
} }
......
...@@ -232,22 +232,25 @@ static int wlan_cmd_802_11_set_wep(wlan_private * priv, ...@@ -232,22 +232,25 @@ static int wlan_cmd_802_11_set_wep(wlan_private * priv,
static int wlan_cmd_802_11_enable_rsn(wlan_private * priv, static int wlan_cmd_802_11_enable_rsn(wlan_private * priv,
struct cmd_ds_command *cmd, struct cmd_ds_command *cmd,
u16 cmd_action) u16 cmd_action,
void * pdata_buf)
{ {
struct cmd_ds_802_11_enable_rsn *penableRSN = &cmd->params.enbrsn; struct cmd_ds_802_11_enable_rsn *penableRSN = &cmd->params.enbrsn;
wlan_adapter *adapter = priv->adapter; struct assoc_request * assoc_req = pdata_buf;
lbs_deb_enter(LBS_DEB_CMD);
cmd->command = cpu_to_le16(cmd_802_11_enable_rsn); cmd->command = cpu_to_le16(cmd_802_11_enable_rsn);
cmd->size = cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_enable_rsn) +
cpu_to_le16(sizeof(struct cmd_ds_802_11_enable_rsn) +
S_DS_GEN); S_DS_GEN);
penableRSN->action = cpu_to_le16(cmd_action); penableRSN->action = cpu_to_le16(cmd_action);
if (adapter->secinfo.WPAenabled || adapter->secinfo.WPA2enabled) { if (assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled) {
penableRSN->enable = cpu_to_le16(cmd_enable_rsn); penableRSN->enable = cpu_to_le16(cmd_enable_rsn);
} else { } else {
penableRSN->enable = cpu_to_le16(cmd_disable_rsn); penableRSN->enable = cpu_to_le16(cmd_disable_rsn);
} }
lbs_deb_leave(LBS_DEB_CMD);
return 0; return 0;
} }
...@@ -258,14 +261,12 @@ static void set_one_wpa_key(struct MrvlIEtype_keyParamSet * pkeyparamset, ...@@ -258,14 +261,12 @@ static void set_one_wpa_key(struct MrvlIEtype_keyParamSet * pkeyparamset,
pkeyparamset->keytypeid = cpu_to_le16(pkey->type); pkeyparamset->keytypeid = cpu_to_le16(pkey->type);
if (pkey->flags & KEY_INFO_WPA_ENABLED) { if (pkey->flags & KEY_INFO_WPA_ENABLED) {
pkeyparamset->keyinfo = cpu_to_le16(KEY_INFO_WPA_ENABLED); pkeyparamset->keyinfo |= cpu_to_le16(KEY_INFO_WPA_ENABLED);
} else {
pkeyparamset->keyinfo = cpu_to_le16(!KEY_INFO_WPA_ENABLED);
} }
if (pkey->flags & KEY_INFO_WPA_UNICAST) { if (pkey->flags & KEY_INFO_WPA_UNICAST) {
pkeyparamset->keyinfo |= cpu_to_le16(KEY_INFO_WPA_UNICAST); pkeyparamset->keyinfo |= cpu_to_le16(KEY_INFO_WPA_UNICAST);
} else if (pkey->flags & KEY_INFO_WPA_MCAST) { }
if (pkey->flags & KEY_INFO_WPA_MCAST) {
pkeyparamset->keyinfo |= cpu_to_le16(KEY_INFO_WPA_MCAST); pkeyparamset->keyinfo |= cpu_to_le16(KEY_INFO_WPA_MCAST);
} }
...@@ -283,9 +284,9 @@ static int wlan_cmd_802_11_key_material(wlan_private * priv, ...@@ -283,9 +284,9 @@ static int wlan_cmd_802_11_key_material(wlan_private * priv,
u16 cmd_action, u16 cmd_action,
u32 cmd_oid, void *pdata_buf) u32 cmd_oid, void *pdata_buf)
{ {
wlan_adapter *adapter = priv->adapter;
struct cmd_ds_802_11_key_material *pkeymaterial = struct cmd_ds_802_11_key_material *pkeymaterial =
&cmd->params.keymaterial; &cmd->params.keymaterial;
struct assoc_request * assoc_req = pdata_buf;
int ret = 0; int ret = 0;
int index = 0; int index = 0;
...@@ -295,29 +296,28 @@ static int wlan_cmd_802_11_key_material(wlan_private * priv, ...@@ -295,29 +296,28 @@ static int wlan_cmd_802_11_key_material(wlan_private * priv,
pkeymaterial->action = cpu_to_le16(cmd_action); pkeymaterial->action = cpu_to_le16(cmd_action);
if (cmd_action == cmd_act_get) { if (cmd_action == cmd_act_get) {
cmd->size = cpu_to_le16( S_DS_GEN cmd->size = cpu_to_le16(S_DS_GEN + sizeof (pkeymaterial->action));
+ sizeof (pkeymaterial->action));
ret = 0; ret = 0;
goto done; goto done;
} }
memset(&pkeymaterial->keyParamSet, 0, sizeof(pkeymaterial->keyParamSet)); memset(&pkeymaterial->keyParamSet, 0, sizeof(pkeymaterial->keyParamSet));
if (adapter->wpa_unicast_key.len) { if (test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) {
set_one_wpa_key(&pkeymaterial->keyParamSet[index], set_one_wpa_key(&pkeymaterial->keyParamSet[index],
&adapter->wpa_unicast_key); &assoc_req->wpa_unicast_key);
index++; index++;
} }
if (adapter->wpa_mcast_key.len) { if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags)) {
set_one_wpa_key(&pkeymaterial->keyParamSet[index], set_one_wpa_key(&pkeymaterial->keyParamSet[index],
&adapter->wpa_mcast_key); &assoc_req->wpa_mcast_key);
index++; index++;
} }
cmd->size = cpu_to_le16( S_DS_GEN cmd->size = cpu_to_le16( S_DS_GEN
+ sizeof (pkeymaterial->action) + sizeof (pkeymaterial->action)
+ index * sizeof(struct MrvlIEtype_keyParamSet)); + (index * sizeof(struct MrvlIEtype_keyParamSet)));
ret = 0; ret = 0;
...@@ -1302,13 +1302,13 @@ int libertas_prepare_and_send_command(wlan_private * priv, ...@@ -1302,13 +1302,13 @@ int libertas_prepare_and_send_command(wlan_private * priv,
break; break;
case cmd_802_11_enable_rsn: case cmd_802_11_enable_rsn:
ret = wlan_cmd_802_11_enable_rsn(priv, cmdptr, cmd_action); ret = wlan_cmd_802_11_enable_rsn(priv, cmdptr, cmd_action,
pdata_buf);
break; break;
case cmd_802_11_key_material: case cmd_802_11_key_material:
ret = wlan_cmd_802_11_key_material(priv, cmdptr, ret = wlan_cmd_802_11_key_material(priv, cmdptr, cmd_action,
cmd_action, cmd_oid, cmd_oid, pdata_buf);
pdata_buf);
break; break;
case cmd_802_11_pairwise_tsc: case cmd_802_11_pairwise_tsc:
......
...@@ -99,7 +99,6 @@ static inline int match_bss_wpa(struct wlan_802_11_security * secinfo, ...@@ -99,7 +99,6 @@ static inline int match_bss_wpa(struct wlan_802_11_security * secinfo,
{ {
if ( !secinfo->wep_enabled if ( !secinfo->wep_enabled
&& secinfo->WPAenabled && secinfo->WPAenabled
&& !secinfo->WPA2enabled
&& (match_bss->wpa_ie[0] == WPA_IE) && (match_bss->wpa_ie[0] == WPA_IE)
/* privacy bit may NOT be set in some APs like LinkSys WRT54G /* privacy bit may NOT be set in some APs like LinkSys WRT54G
&& bss->privacy */ && bss->privacy */
...@@ -113,7 +112,6 @@ static inline int match_bss_wpa2(struct wlan_802_11_security * secinfo, ...@@ -113,7 +112,6 @@ static inline int match_bss_wpa2(struct wlan_802_11_security * secinfo,
struct bss_descriptor * match_bss) struct bss_descriptor * match_bss)
{ {
if ( !secinfo->wep_enabled if ( !secinfo->wep_enabled
&& !secinfo->WPAenabled
&& secinfo->WPA2enabled && secinfo->WPA2enabled
&& (match_bss->rsn_ie[0] == WPA2_IE) && (match_bss->rsn_ie[0] == WPA2_IE)
/* privacy bit may NOT be set in some APs like LinkSys WRT54G /* privacy bit may NOT be set in some APs like LinkSys WRT54G
......
...@@ -1498,6 +1498,8 @@ static void disable_wep(struct assoc_request *assoc_req) ...@@ -1498,6 +1498,8 @@ static void disable_wep(struct assoc_request *assoc_req)
{ {
int i; int i;
lbs_deb_enter(LBS_DEB_WEXT);
/* Set Open System auth mode */ /* Set Open System auth mode */
assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM; assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
...@@ -1508,6 +1510,27 @@ static void disable_wep(struct assoc_request *assoc_req) ...@@ -1508,6 +1510,27 @@ static void disable_wep(struct assoc_request *assoc_req)
set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags); set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags);
set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags); set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags);
lbs_deb_leave(LBS_DEB_WEXT);
}
static void disable_wpa(struct assoc_request *assoc_req)
{
lbs_deb_enter(LBS_DEB_WEXT);
memset(&assoc_req->wpa_mcast_key, 0, sizeof (struct WLAN_802_11_KEY));
assoc_req->wpa_mcast_key.flags = KEY_INFO_WPA_MCAST;
set_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags);
memset(&assoc_req->wpa_unicast_key, 0, sizeof (struct WLAN_802_11_KEY));
assoc_req->wpa_unicast_key.flags = KEY_INFO_WPA_UNICAST;
set_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags);
assoc_req->secinfo.WPAenabled = 0;
assoc_req->secinfo.WPA2enabled = 0;
set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags);
lbs_deb_leave(LBS_DEB_WEXT);
} }
/** /**
...@@ -1540,6 +1563,7 @@ static int wlan_set_encode(struct net_device *dev, ...@@ -1540,6 +1563,7 @@ static int wlan_set_encode(struct net_device *dev,
if (dwrq->flags & IW_ENCODE_DISABLED) { if (dwrq->flags & IW_ENCODE_DISABLED) {
disable_wep (assoc_req); disable_wep (assoc_req);
disable_wpa (assoc_req);
goto out; goto out;
} }
...@@ -1641,6 +1665,7 @@ static int wlan_get_encodeext(struct net_device *dev, ...@@ -1641,6 +1665,7 @@ static int wlan_get_encodeext(struct net_device *dev,
if ( adapter->secinfo.wep_enabled if ( adapter->secinfo.wep_enabled
&& !adapter->secinfo.WPAenabled && !adapter->secinfo.WPAenabled
&& !adapter->secinfo.WPA2enabled) { && !adapter->secinfo.WPA2enabled) {
/* WEP */
ext->alg = IW_ENCODE_ALG_WEP; ext->alg = IW_ENCODE_ALG_WEP;
ext->key_len = adapter->wep_keys[index].len; ext->key_len = adapter->wep_keys[index].len;
key = &adapter->wep_keys[index].key[0]; key = &adapter->wep_keys[index].key[0];
...@@ -1648,8 +1673,27 @@ static int wlan_get_encodeext(struct net_device *dev, ...@@ -1648,8 +1673,27 @@ static int wlan_get_encodeext(struct net_device *dev,
&& (adapter->secinfo.WPAenabled || && (adapter->secinfo.WPAenabled ||
adapter->secinfo.WPA2enabled)) { adapter->secinfo.WPA2enabled)) {
/* WPA */ /* WPA */
struct WLAN_802_11_KEY * pkey = NULL;
if ( adapter->wpa_mcast_key.len
&& (adapter->wpa_mcast_key.flags & KEY_INFO_WPA_ENABLED))
pkey = &adapter->wpa_mcast_key;
else if ( adapter->wpa_unicast_key.len
&& (adapter->wpa_unicast_key.flags & KEY_INFO_WPA_ENABLED))
pkey = &adapter->wpa_unicast_key;
if (pkey) {
if (pkey->type == KEY_TYPE_ID_AES) {
ext->alg = IW_ENCODE_ALG_CCMP;
} else {
ext->alg = IW_ENCODE_ALG_TKIP;
}
ext->key_len = pkey->len;
key = &pkey->key[0];
} else {
ext->alg = IW_ENCODE_ALG_TKIP; ext->alg = IW_ENCODE_ALG_TKIP;
ext->key_len = 0; ext->key_len = 0;
}
} else { } else {
goto out; goto out;
} }
...@@ -1704,6 +1748,7 @@ static int wlan_set_encodeext(struct net_device *dev, ...@@ -1704,6 +1748,7 @@ static int wlan_set_encodeext(struct net_device *dev,
if ((alg == IW_ENCODE_ALG_NONE) || (dwrq->flags & IW_ENCODE_DISABLED)) { if ((alg == IW_ENCODE_ALG_NONE) || (dwrq->flags & IW_ENCODE_DISABLED)) {
disable_wep (assoc_req); disable_wep (assoc_req);
disable_wpa (assoc_req);
} else if (alg == IW_ENCODE_ALG_WEP) { } else if (alg == IW_ENCODE_ALG_WEP) {
u16 is_default = 0, index, set_tx_key = 0; u16 is_default = 0, index, set_tx_key = 0;
...@@ -1739,7 +1784,6 @@ static int wlan_set_encodeext(struct net_device *dev, ...@@ -1739,7 +1784,6 @@ static int wlan_set_encodeext(struct net_device *dev,
set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags); set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags);
if (set_tx_key) if (set_tx_key)
set_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags); set_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags);
} else if ((alg == IW_ENCODE_ALG_TKIP) || (alg == IW_ENCODE_ALG_CCMP)) { } else if ((alg == IW_ENCODE_ALG_TKIP) || (alg == IW_ENCODE_ALG_CCMP)) {
struct WLAN_802_11_KEY * pkey; struct WLAN_802_11_KEY * pkey;
...@@ -1756,28 +1800,35 @@ static int wlan_set_encodeext(struct net_device *dev, ...@@ -1756,28 +1800,35 @@ static int wlan_set_encodeext(struct net_device *dev,
goto out; goto out;
} }
if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
pkey = &assoc_req->wpa_mcast_key; pkey = &assoc_req->wpa_mcast_key;
else set_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags);
} else {
pkey = &assoc_req->wpa_unicast_key; pkey = &assoc_req->wpa_unicast_key;
set_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags);
}
memset(pkey, 0, sizeof (struct WLAN_802_11_KEY)); memset(pkey, 0, sizeof (struct WLAN_802_11_KEY));
memcpy(pkey->key, ext->key, ext->key_len); memcpy(pkey->key, ext->key, ext->key_len);
pkey->len = ext->key_len; pkey->len = ext->key_len;
pkey->flags = KEY_INFO_WPA_ENABLED; if (pkey->len)
pkey->flags |= KEY_INFO_WPA_ENABLED;
/* Do this after zeroing key structure */
if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) { if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
pkey->flags |= KEY_INFO_WPA_MCAST; pkey->flags |= KEY_INFO_WPA_MCAST;
set_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags);
} else { } else {
pkey->flags |= KEY_INFO_WPA_UNICAST; pkey->flags |= KEY_INFO_WPA_UNICAST;
set_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags);
} }
if (alg == IW_ENCODE_ALG_TKIP) if (alg == IW_ENCODE_ALG_TKIP) {
pkey->type = KEY_TYPE_ID_TKIP; pkey->type = KEY_TYPE_ID_TKIP;
else if (alg == IW_ENCODE_ALG_CCMP) } else if (alg == IW_ENCODE_ALG_CCMP) {
pkey->type = KEY_TYPE_ID_AES; pkey->type = KEY_TYPE_ID_AES;
} else {
ret = -EINVAL;
goto out;
}
/* If WPA isn't enabled yet, do that now */ /* If WPA isn't enabled yet, do that now */
if ( assoc_req->secinfo.WPAenabled == 0 if ( assoc_req->secinfo.WPAenabled == 0
...@@ -1904,6 +1955,7 @@ static int wlan_set_auth(struct net_device *dev, ...@@ -1904,6 +1955,7 @@ static int wlan_set_auth(struct net_device *dev,
case IW_AUTH_CIPHER_PAIRWISE: case IW_AUTH_CIPHER_PAIRWISE:
case IW_AUTH_CIPHER_GROUP: case IW_AUTH_CIPHER_GROUP:
case IW_AUTH_KEY_MGMT: case IW_AUTH_KEY_MGMT:
case IW_AUTH_DROP_UNENCRYPTED:
/* /*
* libertas does not use these parameters * libertas does not use these parameters
*/ */
...@@ -1913,6 +1965,7 @@ static int wlan_set_auth(struct net_device *dev, ...@@ -1913,6 +1965,7 @@ static int wlan_set_auth(struct net_device *dev,
if (dwrq->value & IW_AUTH_WPA_VERSION_DISABLED) { if (dwrq->value & IW_AUTH_WPA_VERSION_DISABLED) {
assoc_req->secinfo.WPAenabled = 0; assoc_req->secinfo.WPAenabled = 0;
assoc_req->secinfo.WPA2enabled = 0; assoc_req->secinfo.WPA2enabled = 0;
disable_wpa (assoc_req);
} }
if (dwrq->value & IW_AUTH_WPA_VERSION_WPA) { if (dwrq->value & IW_AUTH_WPA_VERSION_WPA) {
assoc_req->secinfo.WPAenabled = 1; assoc_req->secinfo.WPAenabled = 1;
...@@ -1927,17 +1980,6 @@ static int wlan_set_auth(struct net_device *dev, ...@@ -1927,17 +1980,6 @@ static int wlan_set_auth(struct net_device *dev,
updated = 1; updated = 1;
break; break;
case IW_AUTH_DROP_UNENCRYPTED:
if (dwrq->value) {
adapter->currentpacketfilter |=
cmd_act_mac_strict_protection_enable;
} else {
adapter->currentpacketfilter &=
~cmd_act_mac_strict_protection_enable;
}
updated = 1;
break;
case IW_AUTH_80211_AUTH_ALG: case IW_AUTH_80211_AUTH_ALG:
if (dwrq->value & IW_AUTH_ALG_SHARED_KEY) { if (dwrq->value & IW_AUTH_ALG_SHARED_KEY) {
assoc_req->secinfo.auth_mode = IW_AUTH_ALG_SHARED_KEY; assoc_req->secinfo.auth_mode = IW_AUTH_ALG_SHARED_KEY;
...@@ -1963,6 +2005,7 @@ static int wlan_set_auth(struct net_device *dev, ...@@ -1963,6 +2005,7 @@ static int wlan_set_auth(struct net_device *dev,
} else { } else {
assoc_req->secinfo.WPAenabled = 0; assoc_req->secinfo.WPAenabled = 0;
assoc_req->secinfo.WPA2enabled = 0; assoc_req->secinfo.WPA2enabled = 0;
disable_wpa (assoc_req);
} }
updated = 1; updated = 1;
break; break;
...@@ -2008,13 +2051,6 @@ static int wlan_get_auth(struct net_device *dev, ...@@ -2008,13 +2051,6 @@ static int wlan_get_auth(struct net_device *dev,
dwrq->value |= IW_AUTH_WPA_VERSION_DISABLED; dwrq->value |= IW_AUTH_WPA_VERSION_DISABLED;
break; break;
case IW_AUTH_DROP_UNENCRYPTED:
dwrq->value = 0;
if (adapter->currentpacketfilter &
cmd_act_mac_strict_protection_enable)
dwrq->value = 1;
break;
case IW_AUTH_80211_AUTH_ALG: case IW_AUTH_80211_AUTH_ALG:
dwrq->value = adapter->secinfo.auth_mode; dwrq->value = adapter->secinfo.auth_mode;
break; break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment