Add support to send multi AKM connect request when driver's SME in use
Add support to configure SAE, PSK, and PSK-SHA256 AKMs in connect request when driver's SME in use. This is needed for implementing WPA3-Personal transition mode correctly with any driver that handles roaming internally. Send additional AKMs configured in network block to driver based on the maximum number of AKMs allowed by driver in connect request. Keep first AKM in the list AKMs in the connect request as AKM selected by wpa_supplicant to maintain backwards compatibility. Signed-off-by: Veerendranath Jakkam <quic_vjakkam@quicinc.com>
This commit is contained in:
parent
0ce1545dcb
commit
5de45546d5
6 changed files with 217 additions and 34 deletions
|
@ -181,6 +181,13 @@ static inline int wpa_key_mgmt_cckm(int akm)
|
|||
return akm == WPA_KEY_MGMT_CCKM;
|
||||
}
|
||||
|
||||
static inline int wpa_key_mgmt_cross_akm(int akm)
|
||||
{
|
||||
return !!(akm & (WPA_KEY_MGMT_PSK |
|
||||
WPA_KEY_MGMT_PSK_SHA256 |
|
||||
WPA_KEY_MGMT_SAE |
|
||||
WPA_KEY_MGMT_SAE_EXT_KEY));
|
||||
}
|
||||
|
||||
#define WPA_PROTO_WPA BIT(0)
|
||||
#define WPA_PROTO_RSN BIT(1)
|
||||
|
|
|
@ -999,6 +999,17 @@ struct wpa_driver_associate_params {
|
|||
*/
|
||||
unsigned int key_mgmt_suite;
|
||||
|
||||
/**
|
||||
* allowed_key_mgmts - Bitfield of allowed key management suites
|
||||
* (WPA_KEY_MGMT_*) other than @key_mgmt_suite for the current
|
||||
* connection
|
||||
*
|
||||
* SME in the driver may choose key_mgmt from this list for the initial
|
||||
* connection or roaming. The driver which doesn't support this
|
||||
* ignores this parameter.
|
||||
*/
|
||||
unsigned int allowed_key_mgmts;
|
||||
|
||||
/**
|
||||
* auth_alg - Allowed authentication algorithms
|
||||
* Bit field of WPA_AUTH_ALG_*
|
||||
|
|
|
@ -6137,6 +6137,17 @@ static int nl80211_put_fils_connect_params(struct wpa_driver_nl80211_data *drv,
|
|||
}
|
||||
|
||||
|
||||
static unsigned int num_bits_set(u32 val)
|
||||
{
|
||||
unsigned int c;
|
||||
|
||||
for (c = 0; val; c++)
|
||||
val &= val - 1;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
static int nl80211_connect_common(struct wpa_driver_nl80211_data *drv,
|
||||
struct wpa_driver_associate_params *params,
|
||||
struct nl_msg *msg)
|
||||
|
@ -6268,77 +6279,111 @@ static int nl80211_connect_common(struct wpa_driver_nl80211_data *drv,
|
|||
params->key_mgmt_suite == WPA_KEY_MGMT_FT_FILS_SHA384 ||
|
||||
params->key_mgmt_suite == WPA_KEY_MGMT_OWE ||
|
||||
params->key_mgmt_suite == WPA_KEY_MGMT_DPP) {
|
||||
int mgmt = RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X;
|
||||
u32 *mgmt;
|
||||
unsigned int akm_count = 1, i;
|
||||
|
||||
/*
|
||||
* Make sure the driver has capability to handle default AKM in
|
||||
* key_mgmt_suite plus allowed AKMs in allowed_key_mgmts.
|
||||
*/
|
||||
if (drv->capa.max_num_akms <=
|
||||
num_bits_set(params->allowed_key_mgmts)) {
|
||||
wpa_printf(MSG_INFO,
|
||||
"nl80211: Not enough support for the allowed AKMs (max_num_akms=%u <= num_bits_set=%u)",
|
||||
drv->capa.max_num_akms,
|
||||
num_bits_set(params->allowed_key_mgmts));
|
||||
return -1;
|
||||
}
|
||||
|
||||
mgmt = os_malloc(sizeof(u32) * drv->capa.max_num_akms);
|
||||
if (!mgmt)
|
||||
return -1;
|
||||
|
||||
mgmt[0] = RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X;
|
||||
|
||||
switch (params->key_mgmt_suite) {
|
||||
case WPA_KEY_MGMT_CCKM:
|
||||
mgmt = RSN_AUTH_KEY_MGMT_CCKM;
|
||||
mgmt[0] = RSN_AUTH_KEY_MGMT_CCKM;
|
||||
break;
|
||||
case WPA_KEY_MGMT_IEEE8021X:
|
||||
mgmt = RSN_AUTH_KEY_MGMT_UNSPEC_802_1X;
|
||||
mgmt[0] = RSN_AUTH_KEY_MGMT_UNSPEC_802_1X;
|
||||
break;
|
||||
case WPA_KEY_MGMT_FT_IEEE8021X:
|
||||
mgmt = RSN_AUTH_KEY_MGMT_FT_802_1X;
|
||||
mgmt[0] = RSN_AUTH_KEY_MGMT_FT_802_1X;
|
||||
break;
|
||||
case WPA_KEY_MGMT_FT_PSK:
|
||||
mgmt = RSN_AUTH_KEY_MGMT_FT_PSK;
|
||||
mgmt[0] = RSN_AUTH_KEY_MGMT_FT_PSK;
|
||||
break;
|
||||
case WPA_KEY_MGMT_IEEE8021X_SHA256:
|
||||
mgmt = RSN_AUTH_KEY_MGMT_802_1X_SHA256;
|
||||
mgmt[0] = RSN_AUTH_KEY_MGMT_802_1X_SHA256;
|
||||
break;
|
||||
case WPA_KEY_MGMT_PSK_SHA256:
|
||||
mgmt = RSN_AUTH_KEY_MGMT_PSK_SHA256;
|
||||
mgmt[0] = RSN_AUTH_KEY_MGMT_PSK_SHA256;
|
||||
break;
|
||||
case WPA_KEY_MGMT_OSEN:
|
||||
mgmt = RSN_AUTH_KEY_MGMT_OSEN;
|
||||
mgmt[0] = RSN_AUTH_KEY_MGMT_OSEN;
|
||||
break;
|
||||
case WPA_KEY_MGMT_SAE:
|
||||
mgmt = RSN_AUTH_KEY_MGMT_SAE;
|
||||
mgmt[0] = RSN_AUTH_KEY_MGMT_SAE;
|
||||
break;
|
||||
case WPA_KEY_MGMT_SAE_EXT_KEY:
|
||||
mgmt = RSN_AUTH_KEY_MGMT_SAE_EXT_KEY;
|
||||
mgmt[0] = RSN_AUTH_KEY_MGMT_SAE_EXT_KEY;
|
||||
break;
|
||||
case WPA_KEY_MGMT_FT_SAE:
|
||||
mgmt = RSN_AUTH_KEY_MGMT_FT_SAE;
|
||||
mgmt[0] = RSN_AUTH_KEY_MGMT_FT_SAE;
|
||||
break;
|
||||
case WPA_KEY_MGMT_FT_SAE_EXT_KEY:
|
||||
mgmt = RSN_AUTH_KEY_MGMT_FT_SAE_EXT_KEY;
|
||||
mgmt[0] = RSN_AUTH_KEY_MGMT_FT_SAE_EXT_KEY;
|
||||
break;
|
||||
case WPA_KEY_MGMT_IEEE8021X_SUITE_B:
|
||||
mgmt = RSN_AUTH_KEY_MGMT_802_1X_SUITE_B;
|
||||
mgmt[0] = RSN_AUTH_KEY_MGMT_802_1X_SUITE_B;
|
||||
break;
|
||||
case WPA_KEY_MGMT_IEEE8021X_SUITE_B_192:
|
||||
mgmt = RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192;
|
||||
mgmt[0] = RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192;
|
||||
break;
|
||||
case WPA_KEY_MGMT_FT_IEEE8021X_SHA384:
|
||||
mgmt = RSN_AUTH_KEY_MGMT_FT_802_1X_SHA384;
|
||||
mgmt[0] = RSN_AUTH_KEY_MGMT_FT_802_1X_SHA384;
|
||||
break;
|
||||
case WPA_KEY_MGMT_FILS_SHA256:
|
||||
mgmt = RSN_AUTH_KEY_MGMT_FILS_SHA256;
|
||||
mgmt[0] = RSN_AUTH_KEY_MGMT_FILS_SHA256;
|
||||
break;
|
||||
case WPA_KEY_MGMT_FILS_SHA384:
|
||||
mgmt = RSN_AUTH_KEY_MGMT_FILS_SHA384;
|
||||
mgmt[0] = RSN_AUTH_KEY_MGMT_FILS_SHA384;
|
||||
break;
|
||||
case WPA_KEY_MGMT_FT_FILS_SHA256:
|
||||
mgmt = RSN_AUTH_KEY_MGMT_FT_FILS_SHA256;
|
||||
mgmt[0] = RSN_AUTH_KEY_MGMT_FT_FILS_SHA256;
|
||||
break;
|
||||
case WPA_KEY_MGMT_FT_FILS_SHA384:
|
||||
mgmt = RSN_AUTH_KEY_MGMT_FT_FILS_SHA384;
|
||||
mgmt[0] = RSN_AUTH_KEY_MGMT_FT_FILS_SHA384;
|
||||
break;
|
||||
case WPA_KEY_MGMT_OWE:
|
||||
mgmt = RSN_AUTH_KEY_MGMT_OWE;
|
||||
mgmt[0] = RSN_AUTH_KEY_MGMT_OWE;
|
||||
break;
|
||||
case WPA_KEY_MGMT_DPP:
|
||||
mgmt = RSN_AUTH_KEY_MGMT_DPP;
|
||||
mgmt[0] = RSN_AUTH_KEY_MGMT_DPP;
|
||||
break;
|
||||
case WPA_KEY_MGMT_PSK:
|
||||
default:
|
||||
mgmt = RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X;
|
||||
mgmt[0] = RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X;
|
||||
break;
|
||||
}
|
||||
wpa_printf(MSG_DEBUG, " * akm=0x%x", mgmt);
|
||||
if (nla_put_u32(msg, NL80211_ATTR_AKM_SUITES, mgmt))
|
||||
|
||||
if (drv->capa.max_num_akms > 1) {
|
||||
akm_count += wpa_key_mgmt_to_suites(
|
||||
params->allowed_key_mgmts, &mgmt[1],
|
||||
drv->capa.max_num_akms - 1);
|
||||
}
|
||||
|
||||
for (i = 0; i < akm_count; i++)
|
||||
wpa_printf(MSG_DEBUG, " * akm[%d]=0x%x", i, mgmt[i]);
|
||||
|
||||
if (nla_put(msg, NL80211_ATTR_AKM_SUITES,
|
||||
akm_count * sizeof(u32), mgmt)) {
|
||||
os_free(mgmt);
|
||||
return -1;
|
||||
}
|
||||
|
||||
os_free(mgmt);
|
||||
}
|
||||
|
||||
if (params->req_handshake_offload &&
|
||||
|
@ -6403,7 +6448,8 @@ static int nl80211_connect_common(struct wpa_driver_nl80211_data *drv,
|
|||
nl80211_put_fils_connect_params(drv, params, msg) != 0)
|
||||
return -1;
|
||||
|
||||
if (wpa_key_mgmt_sae(params->key_mgmt_suite) &&
|
||||
if ((wpa_key_mgmt_sae(params->key_mgmt_suite) ||
|
||||
wpa_key_mgmt_sae(params->allowed_key_mgmts)) &&
|
||||
(!(drv->capa.flags & WPA_DRIVER_FLAGS_SME)) &&
|
||||
nla_put_flag(msg, NL80211_ATTR_EXTERNAL_AUTH_SUPPORT))
|
||||
return -1;
|
||||
|
@ -6424,9 +6470,8 @@ static int wpa_driver_nl80211_try_connect(
|
|||
|
||||
#ifdef CONFIG_DRIVER_NL80211_QCA
|
||||
if (params->req_key_mgmt_offload && params->psk &&
|
||||
(params->key_mgmt_suite == WPA_KEY_MGMT_PSK ||
|
||||
params->key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
|
||||
params->key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
|
||||
(wpa_key_mgmt_wpa_psk_no_sae(params->key_mgmt_suite) ||
|
||||
wpa_key_mgmt_wpa_psk_no_sae(params->allowed_key_mgmts))) {
|
||||
wpa_printf(MSG_DEBUG, "nl80211: Key management set PSK");
|
||||
ret = issue_key_mgmt_set_key(drv, params->psk, 32);
|
||||
if (ret)
|
||||
|
@ -6453,7 +6498,8 @@ static int wpa_driver_nl80211_try_connect(
|
|||
goto fail;
|
||||
|
||||
#ifdef CONFIG_SAE
|
||||
if (wpa_key_mgmt_sae(params->key_mgmt_suite) &&
|
||||
if ((wpa_key_mgmt_sae(params->key_mgmt_suite) ||
|
||||
wpa_key_mgmt_sae(params->allowed_key_mgmts)) &&
|
||||
nl80211_put_sae_pwe(msg, params->sae_pwe) < 0)
|
||||
goto fail;
|
||||
#endif /* CONFIG_SAE */
|
||||
|
@ -6561,7 +6607,8 @@ static int wpa_driver_nl80211_associate(
|
|||
|
||||
if (wpa_driver_nl80211_set_mode(priv, nlmode) < 0)
|
||||
return -1;
|
||||
if (wpa_key_mgmt_sae(params->key_mgmt_suite))
|
||||
if (wpa_key_mgmt_sae(params->key_mgmt_suite) ||
|
||||
wpa_key_mgmt_sae(params->allowed_key_mgmts))
|
||||
bss->use_nl_connect = 1;
|
||||
else
|
||||
bss->use_nl_connect = 0;
|
||||
|
|
|
@ -337,6 +337,7 @@ void wpa_supplicant_mark_disassoc(struct wpa_supplicant *wpa_s)
|
|||
wpa_s->current_ssid = NULL;
|
||||
eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
|
||||
wpa_s->key_mgmt = 0;
|
||||
wpa_s->allowed_key_mgmts = 0;
|
||||
|
||||
wpas_rrm_reset(wpa_s);
|
||||
wpa_s->wnmsleep_used = 0;
|
||||
|
|
|
@ -1119,6 +1119,7 @@ void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
|
|||
wpa_s->group_cipher = 0;
|
||||
wpa_s->mgmt_group_cipher = 0;
|
||||
wpa_s->key_mgmt = 0;
|
||||
wpa_s->allowed_key_mgmts = 0;
|
||||
if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
|
||||
wpa_supplicant_set_state(wpa_s, new_state);
|
||||
|
||||
|
@ -1339,6 +1340,111 @@ void wpas_set_mgmt_group_cipher(struct wpa_supplicant *wpa_s,
|
|||
}
|
||||
|
||||
|
||||
static void wpas_update_allowed_key_mgmt(struct wpa_supplicant *wpa_s,
|
||||
struct wpa_ssid *ssid)
|
||||
{
|
||||
int akm_count = wpa_s->max_num_akms;
|
||||
u8 capab = 0;
|
||||
|
||||
if (akm_count < 2)
|
||||
return;
|
||||
|
||||
akm_count--;
|
||||
wpa_s->allowed_key_mgmts = 0;
|
||||
switch (wpa_s->key_mgmt) {
|
||||
case WPA_KEY_MGMT_PSK:
|
||||
if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) {
|
||||
akm_count--;
|
||||
wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE;
|
||||
}
|
||||
if (!akm_count)
|
||||
break;
|
||||
if (ssid->key_mgmt & WPA_KEY_MGMT_SAE_EXT_KEY) {
|
||||
akm_count--;
|
||||
wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE_EXT_KEY;
|
||||
}
|
||||
if (!akm_count)
|
||||
break;
|
||||
if (ssid->key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
|
||||
wpa_s->allowed_key_mgmts |=
|
||||
WPA_KEY_MGMT_PSK_SHA256;
|
||||
break;
|
||||
case WPA_KEY_MGMT_PSK_SHA256:
|
||||
if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) {
|
||||
akm_count--;
|
||||
wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE;
|
||||
}
|
||||
if (!akm_count)
|
||||
break;
|
||||
if (ssid->key_mgmt & WPA_KEY_MGMT_SAE_EXT_KEY) {
|
||||
akm_count--;
|
||||
wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE_EXT_KEY;
|
||||
}
|
||||
if (!akm_count)
|
||||
break;
|
||||
if (ssid->key_mgmt & WPA_KEY_MGMT_PSK)
|
||||
wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_PSK;
|
||||
break;
|
||||
case WPA_KEY_MGMT_SAE:
|
||||
if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) {
|
||||
akm_count--;
|
||||
wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_PSK;
|
||||
}
|
||||
if (!akm_count)
|
||||
break;
|
||||
if (ssid->key_mgmt & WPA_KEY_MGMT_SAE_EXT_KEY) {
|
||||
akm_count--;
|
||||
wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE_EXT_KEY;
|
||||
}
|
||||
if (!akm_count)
|
||||
break;
|
||||
if (ssid->key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
|
||||
wpa_s->allowed_key_mgmts |=
|
||||
WPA_KEY_MGMT_PSK_SHA256;
|
||||
break;
|
||||
case WPA_KEY_MGMT_SAE_EXT_KEY:
|
||||
if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) {
|
||||
akm_count--;
|
||||
wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_SAE;
|
||||
}
|
||||
if (!akm_count)
|
||||
break;
|
||||
if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) {
|
||||
akm_count--;
|
||||
wpa_s->allowed_key_mgmts |= WPA_KEY_MGMT_PSK;
|
||||
}
|
||||
if (!akm_count)
|
||||
break;
|
||||
if (ssid->key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
|
||||
wpa_s->allowed_key_mgmts |=
|
||||
WPA_KEY_MGMT_PSK_SHA256;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (wpa_s->conf->sae_pwe)
|
||||
capab |= BIT(WLAN_RSNX_CAPAB_SAE_H2E);
|
||||
#ifdef CONFIG_SAE_PK
|
||||
if (ssid->sae_pk)
|
||||
capab |= BIT(WLAN_RSNX_CAPAB_SAE_PK);
|
||||
#endif /* CONFIG_SAE_PK */
|
||||
|
||||
if (!((wpa_s->allowed_key_mgmts &
|
||||
(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_SAE_EXT_KEY)) && capab))
|
||||
return;
|
||||
|
||||
if (!wpa_s->rsnxe_len) {
|
||||
wpa_s->rsnxe_len = 3;
|
||||
wpa_s->rsnxe[0] = WLAN_EID_RSNX;
|
||||
wpa_s->rsnxe[1] = 1;
|
||||
wpa_s->rsnxe[2] = 0;
|
||||
}
|
||||
|
||||
wpa_s->rsnxe[2] |= capab;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* wpa_supplicant_set_suites - Set authentication and encryption parameters
|
||||
* @wpa_s: Pointer to wpa_supplicant data
|
||||
|
@ -1902,6 +2008,10 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
|
|||
wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DENY_PTK0_REKEY, 0);
|
||||
}
|
||||
|
||||
if (wpa_key_mgmt_cross_akm(wpa_s->key_mgmt) &&
|
||||
!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME))
|
||||
wpas_update_allowed_key_mgmt(wpa_s, ssid);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -3903,6 +4013,7 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
|
|||
params.group_suite = cipher_group;
|
||||
params.mgmt_group_suite = cipher_group_mgmt;
|
||||
params.key_mgmt_suite = wpa_s->key_mgmt;
|
||||
params.allowed_key_mgmts = wpa_s->allowed_key_mgmts;
|
||||
params.wpa_proto = wpa_s->wpa_proto;
|
||||
wpa_s->auth_alg = params.auth_alg;
|
||||
params.mode = ssid->mode;
|
||||
|
@ -3922,7 +4033,9 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
|
|||
|
||||
if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) &&
|
||||
(params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
|
||||
params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
|
||||
params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK ||
|
||||
(params.allowed_key_mgmts &
|
||||
(WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_FT_PSK)))) {
|
||||
params.passphrase = ssid->passphrase;
|
||||
if (ssid->psk_set)
|
||||
params.psk = ssid->psk;
|
||||
|
@ -3946,9 +4059,8 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
|
|||
else
|
||||
params.req_key_mgmt_offload = 1;
|
||||
|
||||
if ((params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
|
||||
params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
|
||||
params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK) &&
|
||||
if ((wpa_key_mgmt_wpa_psk_no_sae(params.key_mgmt_suite) ||
|
||||
wpa_key_mgmt_wpa_psk_no_sae(params.allowed_key_mgmts)) &&
|
||||
ssid->psk_set)
|
||||
params.psk = ssid->psk;
|
||||
}
|
||||
|
|
|
@ -747,6 +747,11 @@ struct wpa_supplicant {
|
|||
int key_mgmt;
|
||||
int wpa_proto;
|
||||
int mgmt_group_cipher;
|
||||
/*
|
||||
* Allowed key management suites for roaming/initial connection
|
||||
* when the driver's SME is in use.
|
||||
*/
|
||||
int allowed_key_mgmts;
|
||||
|
||||
void *drv_priv; /* private data used by driver_ops */
|
||||
void *global_drv_priv;
|
||||
|
|
Loading…
Reference in a new issue