mirror of
https://git.kernel.org/pub/scm/network/wireless/iwd.git
synced 2024-11-22 23:09:34 +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:
parent
8064cb599a
commit
a553771ffe
16
src/netdev.c
16
src/netdev.c
@ -2292,6 +2292,8 @@ static void netdev_sae_complete(uint16_t status, void *user_data)
|
||||
{
|
||||
struct netdev *netdev = user_data;
|
||||
struct l_genl_msg *msg;
|
||||
struct iovec iov[3];
|
||||
int iov_elems = 0;
|
||||
|
||||
if (status != 0) {
|
||||
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);
|
||||
|
||||
l_genl_msg_append_attr(msg, NL80211_ATTR_IE,
|
||||
netdev->handshake->supplicant_ie[1] + 2,
|
||||
netdev->handshake->supplicant_ie);
|
||||
iov[iov_elems].iov_base = netdev->handshake->supplicant_ie;
|
||||
iov[iov_elems].iov_len = netdev->handshake->supplicant_ie[1] + 2;
|
||||
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->connect_cmd_id = l_genl_family_send(nl80211, msg,
|
||||
|
@ -431,25 +431,19 @@ static void station_handshake_event(struct handshake_state *hs,
|
||||
}
|
||||
}
|
||||
|
||||
static struct handshake_state *station_handshake_setup(struct station *station,
|
||||
struct network *network,
|
||||
struct scan_bss *bss)
|
||||
static int station_build_handshake_rsn(struct handshake_state *hs,
|
||||
struct wiphy *wiphy,
|
||||
struct network *network,
|
||||
struct scan_bss *bss)
|
||||
{
|
||||
enum security security = network_get_security(network);
|
||||
struct wiphy *wiphy = station->wiphy;
|
||||
struct handshake_state *hs;
|
||||
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) {
|
||||
const struct l_settings *settings = iwd_get_config();
|
||||
struct ie_rsn_info bss_info;
|
||||
uint8_t rsne_buf[256];
|
||||
struct ie_rsn_info info;
|
||||
const char *ssid;
|
||||
uint32_t mfp_setting;
|
||||
|
||||
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)
|
||||
goto not_supported;
|
||||
|
||||
ssid = network_get_ssid(network);
|
||||
handshake_state_set_ssid(hs, (void *) ssid, strlen(ssid));
|
||||
|
||||
/* RSN takes priority */
|
||||
if (bss->rsne) {
|
||||
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);
|
||||
}
|
||||
|
||||
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 |
|
||||
IE_RSN_AKM_SUITE_FT_USING_PSK |
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
not_supported:
|
||||
@ -955,16 +971,14 @@ static void station_transition_start(struct station *station,
|
||||
|
||||
/* Can we use Fast Transition? */
|
||||
if (hs->mde && bss->mde_present && l_get_le16(bss->mde) == mdid) {
|
||||
/*
|
||||
* There's no need to regenerate the RSNE because neither
|
||||
* the AKM nor cipher suite can change:
|
||||
*
|
||||
* 12.5.2: "If the FTO selects a pairwise cipher suite in
|
||||
* the RSNE that is different from the ones used in the
|
||||
* Initial mobility domain association, then the AP shall
|
||||
* reject the Authentication Request with status code 19
|
||||
* (i.e., Invalid Pairwise Cipher)."
|
||||
*/
|
||||
/* Rebuild handshake RSN for target AP */
|
||||
if (station_build_handshake_rsn(hs, station->wiphy,
|
||||
station->connected_network, bss) < 0) {
|
||||
l_error("rebuilding handshake rsne failed");
|
||||
station_roam_failed(station);
|
||||
return;
|
||||
}
|
||||
|
||||
if (netdev_fast_transition(station->netdev, bss,
|
||||
station_fast_transition_cb) < 0) {
|
||||
station_roam_failed(station);
|
||||
|
Loading…
Reference in New Issue
Block a user