3
0
mirror of https://git.kernel.org/pub/scm/network/wireless/iwd.git synced 2024-11-26 18:59:22 +01:00

netdev: station: support FT over SAE

Boiled down, FT over SAE is no different than FT over PSK, apart from
the different AKM suite. The bulk of this change fixes the current
netdev/station logic related to SAE by rebuilding the RSNE and adding
the MDE if present in the handshake to match what the PSK logic does.

A common function was introduced into station which will rebuild the
handshake rsne's for a target network. This is used for both new
network connections as well as fast transitions.
This commit is contained in:
James Prestwood 2018-09-19 11:30:36 -07:00 committed by Denis Kenzior
parent 8064cb599a
commit a553771ffe
2 changed files with 62 additions and 38 deletions

View File

@ -2292,6 +2292,8 @@ static void netdev_sae_complete(uint16_t status, void *user_data)
{ {
struct netdev *netdev = user_data; struct netdev *netdev = user_data;
struct l_genl_msg *msg; struct l_genl_msg *msg;
struct iovec iov[3];
int iov_elems = 0;
if (status != 0) { if (status != 0) {
l_error("SAE exchange failed on %u result %u", l_error("SAE exchange failed on %u result %u",
@ -2302,9 +2304,17 @@ static void netdev_sae_complete(uint16_t status, void *user_data)
msg = netdev_build_cmd_associate_common(netdev); msg = netdev_build_cmd_associate_common(netdev);
l_genl_msg_append_attr(msg, NL80211_ATTR_IE, iov[iov_elems].iov_base = netdev->handshake->supplicant_ie;
netdev->handshake->supplicant_ie[1] + 2, iov[iov_elems].iov_len = netdev->handshake->supplicant_ie[1] + 2;
netdev->handshake->supplicant_ie); iov_elems++;
if (netdev->handshake->mde) {
iov[iov_elems].iov_base = netdev->handshake->mde;
iov[iov_elems].iov_len = netdev->handshake->mde[1] + 2;
iov_elems++;
}
l_genl_msg_append_attrv(msg, NL80211_ATTR_IE, iov, iov_elems);
/* netdev_cmd_connect_cb can be reused */ /* netdev_cmd_connect_cb can be reused */
netdev->connect_cmd_id = l_genl_family_send(nl80211, msg, netdev->connect_cmd_id = l_genl_family_send(nl80211, msg,

View File

@ -431,25 +431,19 @@ static void station_handshake_event(struct handshake_state *hs,
} }
} }
static struct handshake_state *station_handshake_setup(struct station *station, static int station_build_handshake_rsn(struct handshake_state *hs,
struct network *network, struct wiphy *wiphy,
struct scan_bss *bss) struct network *network,
struct scan_bss *bss)
{ {
enum security security = network_get_security(network); enum security security = network_get_security(network);
struct wiphy *wiphy = station->wiphy;
struct handshake_state *hs;
bool add_mde = false; bool add_mde = false;
hs = netdev_handshake_state_new(station->netdev);
handshake_state_set_event_func(hs, station_handshake_event, station);
if (security == SECURITY_PSK || security == SECURITY_8021X) { if (security == SECURITY_PSK || security == SECURITY_8021X) {
const struct l_settings *settings = iwd_get_config(); const struct l_settings *settings = iwd_get_config();
struct ie_rsn_info bss_info; struct ie_rsn_info bss_info;
uint8_t rsne_buf[256]; uint8_t rsne_buf[256];
struct ie_rsn_info info; struct ie_rsn_info info;
const char *ssid;
uint32_t mfp_setting; uint32_t mfp_setting;
memset(&info, 0, sizeof(info)); memset(&info, 0, sizeof(info));
@ -508,9 +502,6 @@ static struct handshake_state *station_handshake_setup(struct station *station,
if (bss_info.mfpr && !info.mfpc) if (bss_info.mfpr && !info.mfpc)
goto not_supported; goto not_supported;
ssid = network_get_ssid(network);
handshake_state_set_ssid(hs, (void *) ssid, strlen(ssid));
/* RSN takes priority */ /* RSN takes priority */
if (bss->rsne) { if (bss->rsne) {
ie_build_rsne(&info, rsne_buf); ie_build_rsne(&info, rsne_buf);
@ -522,18 +513,6 @@ static struct handshake_state *station_handshake_setup(struct station *station,
handshake_state_set_supplicant_wpa(hs, rsne_buf); handshake_state_set_supplicant_wpa(hs, rsne_buf);
} }
if (security == SECURITY_PSK) {
/* SAE will generate/set the PMK */
if (info.akm_suites == IE_RSN_AKM_SUITE_SAE_SHA256)
handshake_state_set_passphrase(hs,
network_get_passphrase(network));
else
handshake_state_set_pmk(hs,
network_get_psk(network), 32);
} else
handshake_state_set_8021x_config(hs,
network_get_settings(network));
if (info.akm_suites & (IE_RSN_AKM_SUITE_FT_OVER_8021X | if (info.akm_suites & (IE_RSN_AKM_SUITE_FT_OVER_8021X |
IE_RSN_AKM_SUITE_FT_USING_PSK | IE_RSN_AKM_SUITE_FT_USING_PSK |
IE_RSN_AKM_SUITE_FT_OVER_SAE_SHA256)) IE_RSN_AKM_SUITE_FT_OVER_SAE_SHA256))
@ -555,6 +534,43 @@ static struct handshake_state *station_handshake_setup(struct station *station,
handshake_state_set_mde(hs, mde); handshake_state_set_mde(hs, mde);
} }
return 0;
not_supported:
return -ENOTSUP;
}
static struct handshake_state *station_handshake_setup(struct station *station,
struct network *network,
struct scan_bss *bss)
{
enum security security = network_get_security(network);
struct wiphy *wiphy = station->wiphy;
struct handshake_state *hs;
const char *ssid;
hs = netdev_handshake_state_new(station->netdev);
handshake_state_set_event_func(hs, station_handshake_event, station);
if (station_build_handshake_rsn(hs, wiphy, network, bss) < 0)
goto not_supported;
ssid = network_get_ssid(network);
handshake_state_set_ssid(hs, (void *) ssid, strlen(ssid));
if (security == SECURITY_PSK) {
/* SAE will generate/set the PMK */
if (IE_AKM_IS_SAE(hs->akm_suite))
handshake_state_set_passphrase(hs,
network_get_passphrase(network));
else
handshake_state_set_pmk(hs,
network_get_psk(network), 32);
} else
handshake_state_set_8021x_config(hs,
network_get_settings(network));
return hs; return hs;
not_supported: not_supported:
@ -955,16 +971,14 @@ static void station_transition_start(struct station *station,
/* Can we use Fast Transition? */ /* Can we use Fast Transition? */
if (hs->mde && bss->mde_present && l_get_le16(bss->mde) == mdid) { if (hs->mde && bss->mde_present && l_get_le16(bss->mde) == mdid) {
/* /* Rebuild handshake RSN for target AP */
* There's no need to regenerate the RSNE because neither if (station_build_handshake_rsn(hs, station->wiphy,
* the AKM nor cipher suite can change: station->connected_network, bss) < 0) {
* l_error("rebuilding handshake rsne failed");
* 12.5.2: "If the FTO selects a pairwise cipher suite in station_roam_failed(station);
* the RSNE that is different from the ones used in the return;
* Initial mobility domain association, then the AP shall }
* reject the Authentication Request with status code 19
* (i.e., Invalid Pairwise Cipher)."
*/
if (netdev_fast_transition(station->netdev, bss, if (netdev_fast_transition(station->netdev, bss,
station_fast_transition_cb) < 0) { station_fast_transition_cb) < 0) {
station_roam_failed(station); station_roam_failed(station);