[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: Dan Williams <dcbw@redhat.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c
index 48fc6d1..2ee38a2 100644
--- a/drivers/net/wireless/libertas/assoc.c
+++ b/drivers/net/wireless/libertas/assoc.c
@@ -347,7 +347,17 @@
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 @@
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;
}
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c
index 53ac28e..8da788e 100644
--- a/drivers/net/wireless/libertas/cmd.c
+++ b/drivers/net/wireless/libertas/cmd.c
@@ -232,22 +232,25 @@
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 @@
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 @@
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 @@
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 @@
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:
diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c
index ec16cd0..3da1efd 100644
--- a/drivers/net/wireless/libertas/scan.c
+++ b/drivers/net/wireless/libertas/scan.c
@@ -99,7 +99,6 @@
{
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 @@
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
diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c
index 40dd080..2edc10c 100644
--- a/drivers/net/wireless/libertas/wext.c
+++ b/drivers/net/wireless/libertas/wext.c
@@ -1498,6 +1498,8 @@
{
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 @@
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 @@
if (dwrq->flags & IW_ENCODE_DISABLED) {
disable_wep (assoc_req);
+ disable_wpa (assoc_req);
goto out;
}
@@ -1641,6 +1665,7 @@
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 @@
&& (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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
} else {
assoc_req->secinfo.WPAenabled = 0;
assoc_req->secinfo.WPA2enabled = 0;
+ disable_wpa (assoc_req);
}
updated = 1;
break;
@@ -2008,13 +2051,6 @@
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;