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,
sizeof(struct wlan_802_11_security));
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);
return ret;
}
......@@ -360,22 +370,12 @@ static int assoc_helper_wpa_keys(wlan_private *priv,
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,
cmd_802_11_key_material,
cmd_act_set,
cmd_option_waitforrsp,
0, assoc_req);
out:
lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
return ret;
}
......
......@@ -232,22 +232,25 @@ done:
static int wlan_cmd_802_11_enable_rsn(wlan_private * priv,
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;
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->size =
cpu_to_le16(sizeof(struct cmd_ds_802_11_enable_rsn) +
S_DS_GEN);
cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_enable_rsn) +
S_DS_GEN);
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);
} else {
penableRSN->enable = cpu_to_le16(cmd_disable_rsn);
}
lbs_deb_leave(LBS_DEB_CMD);
return 0;
}
......@@ -258,14 +261,12 @@ static void set_one_wpa_key(struct MrvlIEtype_keyParamSet * pkeyparamset,
pkeyparamset->keytypeid = cpu_to_le16(pkey->type);
if (pkey->flags & KEY_INFO_WPA_ENABLED) {
pkeyparamset->keyinfo = cpu_to_le16(KEY_INFO_WPA_ENABLED);
} else {
pkeyparamset->keyinfo = cpu_to_le16(!KEY_INFO_WPA_ENABLED);
pkeyparamset->keyinfo |= cpu_to_le16(KEY_INFO_WPA_ENABLED);
}
if (pkey->flags & 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);
}
......@@ -283,9 +284,9 @@ static int wlan_cmd_802_11_key_material(wlan_private * priv,
u16 cmd_action,
u32 cmd_oid, void *pdata_buf)
{
wlan_adapter *adapter = priv->adapter;
struct cmd_ds_802_11_key_material *pkeymaterial =
&cmd->params.keymaterial;
struct assoc_request * assoc_req = pdata_buf;
int ret = 0;
int index = 0;
......@@ -295,29 +296,28 @@ static int wlan_cmd_802_11_key_material(wlan_private * priv,
pkeymaterial->action = cpu_to_le16(cmd_action);
if (cmd_action == cmd_act_get) {
cmd->size = cpu_to_le16( S_DS_GEN
+ sizeof (pkeymaterial->action));
cmd->size = cpu_to_le16(S_DS_GEN + sizeof (pkeymaterial->action));
ret = 0;
goto done;
}
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],
&adapter->wpa_unicast_key);
&assoc_req->wpa_unicast_key);
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],
&adapter->wpa_mcast_key);
&assoc_req->wpa_mcast_key);
index++;
}
cmd->size = cpu_to_le16( S_DS_GEN
+ sizeof (pkeymaterial->action)
+ index * sizeof(struct MrvlIEtype_keyParamSet));
+ sizeof (pkeymaterial->action)
+ (index * sizeof(struct MrvlIEtype_keyParamSet)));
ret = 0;
......@@ -1302,13 +1302,13 @@ int libertas_prepare_and_send_command(wlan_private * priv,
break;
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;
case cmd_802_11_key_material:
ret = wlan_cmd_802_11_key_material(priv, cmdptr,
cmd_action, cmd_oid,
pdata_buf);
ret = wlan_cmd_802_11_key_material(priv, cmdptr, cmd_action,
cmd_oid, pdata_buf);
break;
case cmd_802_11_pairwise_tsc:
......
......@@ -99,7 +99,6 @@ static inline int match_bss_wpa(struct wlan_802_11_security * secinfo,
{
if ( !secinfo->wep_enabled
&& secinfo->WPAenabled
&& !secinfo->WPA2enabled
&& (match_bss->wpa_ie[0] == WPA_IE)
/* privacy bit may NOT be set in some APs like LinkSys WRT54G
&& bss->privacy */
......@@ -113,7 +112,6 @@ static inline int match_bss_wpa2(struct wlan_802_11_security * secinfo,
struct bss_descriptor * match_bss)
{
if ( !secinfo->wep_enabled
&& !secinfo->WPAenabled
&& secinfo->WPA2enabled
&& (match_bss->rsn_ie[0] == WPA2_IE)
/* 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)
{
int i;
lbs_deb_enter(LBS_DEB_WEXT);
/* Set Open System auth mode */
assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
......@@ -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_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,
if (dwrq->flags & IW_ENCODE_DISABLED) {
disable_wep (assoc_req);
disable_wpa (assoc_req);
goto out;
}
......@@ -1641,6 +1665,7 @@ static int wlan_get_encodeext(struct net_device *dev,
if ( adapter->secinfo.wep_enabled
&& !adapter->secinfo.WPAenabled
&& !adapter->secinfo.WPA2enabled) {
/* WEP */
ext->alg = IW_ENCODE_ALG_WEP;
ext->key_len = adapter->wep_keys[index].len;
key = &adapter->wep_keys[index].key[0];
......@@ -1648,8 +1673,27 @@ static int wlan_get_encodeext(struct net_device *dev,
&& (adapter->secinfo.WPAenabled ||
adapter->secinfo.WPA2enabled)) {
/* WPA */
ext->alg = IW_ENCODE_ALG_TKIP;
ext->key_len = 0;
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->key_len = 0;
}
} else {
goto out;
}
......@@ -1704,6 +1748,7 @@ static int wlan_set_encodeext(struct net_device *dev,
if ((alg == IW_ENCODE_ALG_NONE) || (dwrq->flags & IW_ENCODE_DISABLED)) {
disable_wep (assoc_req);
disable_wpa (assoc_req);
} else if (alg == IW_ENCODE_ALG_WEP) {
u16 is_default = 0, index, set_tx_key = 0;
......@@ -1739,7 +1784,6 @@ static int wlan_set_encodeext(struct net_device *dev,
set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags);
if (set_tx_key)
set_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags);
} else if ((alg == IW_ENCODE_ALG_TKIP) || (alg == IW_ENCODE_ALG_CCMP)) {
struct WLAN_802_11_KEY * pkey;
......@@ -1756,28 +1800,35 @@ static int wlan_set_encodeext(struct net_device *dev,
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;
else
set_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags);
} else {
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));
memcpy(pkey->key, ext->key, 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) {
pkey->flags |= KEY_INFO_WPA_MCAST;
set_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags);
} else {
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;
else if (alg == IW_ENCODE_ALG_CCMP)
} else if (alg == IW_ENCODE_ALG_CCMP) {
pkey->type = KEY_TYPE_ID_AES;
} else {
ret = -EINVAL;
goto out;
}
/* If WPA isn't enabled yet, do that now */
if ( assoc_req->secinfo.WPAenabled == 0
......@@ -1904,6 +1955,7 @@ static int wlan_set_auth(struct net_device *dev,
case IW_AUTH_CIPHER_PAIRWISE:
case IW_AUTH_CIPHER_GROUP:
case IW_AUTH_KEY_MGMT:
case IW_AUTH_DROP_UNENCRYPTED:
/*
* libertas does not use these parameters
*/
......@@ -1913,6 +1965,7 @@ static int wlan_set_auth(struct net_device *dev,
if (dwrq->value & IW_AUTH_WPA_VERSION_DISABLED) {
assoc_req->secinfo.WPAenabled = 0;
assoc_req->secinfo.WPA2enabled = 0;
disable_wpa (assoc_req);
}
if (dwrq->value & IW_AUTH_WPA_VERSION_WPA) {
assoc_req->secinfo.WPAenabled = 1;
......@@ -1927,17 +1980,6 @@ static int wlan_set_auth(struct net_device *dev,
updated = 1;
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:
if (dwrq->value & 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,
} else {
assoc_req->secinfo.WPAenabled = 0;
assoc_req->secinfo.WPA2enabled = 0;
disable_wpa (assoc_req);
}
updated = 1;
break;
......@@ -2008,13 +2051,6 @@ static int wlan_get_auth(struct net_device *dev,
dwrq->value |= IW_AUTH_WPA_VERSION_DISABLED;
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:
dwrq->value = adapter->secinfo.auth_mode;
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