FILS: Add FILS SK auth PFS support in STA mode
This adds an option to configure wpa_supplicant to use the perfect forward secrecy option in FILS shared key authentication. A new build option CONFIG_FILS_SK_PFS=y can be used to include this functionality. A new runtime network profile parameter fils_dh_group is used to enable this by specifying which DH group to use. For example, fils_dh_group=19 would use FILS SK PFS with a 256-bit random ECP group. Signed-off-by: Jouni Malinen <j@w1.fi>
This commit is contained in:
parent
1764559eef
commit
76e20f4fa7
12 changed files with 170 additions and 28 deletions
|
@ -2461,6 +2461,9 @@ void wpa_sm_deinit(struct wpa_sm *sm)
|
||||||
#ifdef CONFIG_TESTING_OPTIONS
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
wpabuf_free(sm->test_assoc_ie);
|
wpabuf_free(sm->test_assoc_ie);
|
||||||
#endif /* CONFIG_TESTING_OPTIONS */
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
|
#ifdef CONFIG_FILS
|
||||||
|
crypto_ecdh_deinit(sm->fils_ecdh);
|
||||||
|
#endif /* CONFIG_FILS */
|
||||||
#ifdef CONFIG_OWE
|
#ifdef CONFIG_OWE
|
||||||
crypto_ecdh_deinit(sm->owe_ecdh);
|
crypto_ecdh_deinit(sm->owe_ecdh);
|
||||||
#endif /* CONFIG_OWE */
|
#endif /* CONFIG_OWE */
|
||||||
|
@ -3265,10 +3268,11 @@ void wpa_sm_set_test_assoc_ie(struct wpa_sm *sm, struct wpabuf *buf)
|
||||||
|
|
||||||
#ifdef CONFIG_FILS
|
#ifdef CONFIG_FILS
|
||||||
|
|
||||||
struct wpabuf * fils_build_auth(struct wpa_sm *sm)
|
struct wpabuf * fils_build_auth(struct wpa_sm *sm, int dh_group)
|
||||||
{
|
{
|
||||||
struct wpabuf *buf = NULL;
|
struct wpabuf *buf = NULL;
|
||||||
struct wpabuf *erp_msg;
|
struct wpabuf *erp_msg;
|
||||||
|
struct wpabuf *pub = NULL;
|
||||||
|
|
||||||
erp_msg = eapol_sm_build_erp_reauth_start(sm->eapol);
|
erp_msg = eapol_sm_build_erp_reauth_start(sm->eapol);
|
||||||
if (!erp_msg && !sm->cur_pmksa) {
|
if (!erp_msg && !sm->cur_pmksa) {
|
||||||
|
@ -3296,7 +3300,28 @@ struct wpabuf * fils_build_auth(struct wpa_sm *sm)
|
||||||
wpa_hexdump(MSG_DEBUG, "FILS: Generated FILS Session",
|
wpa_hexdump(MSG_DEBUG, "FILS: Generated FILS Session",
|
||||||
sm->fils_session, FILS_SESSION_LEN);
|
sm->fils_session, FILS_SESSION_LEN);
|
||||||
|
|
||||||
buf = wpabuf_alloc(1000 + sm->assoc_wpa_ie_len);
|
#ifdef CONFIG_FILS_SK_PFS
|
||||||
|
sm->fils_dh_group = dh_group;
|
||||||
|
if (dh_group) {
|
||||||
|
crypto_ecdh_deinit(sm->fils_ecdh);
|
||||||
|
sm->fils_ecdh = crypto_ecdh_init(dh_group);
|
||||||
|
if (!sm->fils_ecdh) {
|
||||||
|
wpa_printf(MSG_INFO,
|
||||||
|
"FILS: Could not initialize ECDH with group %d",
|
||||||
|
dh_group);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
pub = crypto_ecdh_get_pubkey(sm->fils_ecdh, 1);
|
||||||
|
if (!pub)
|
||||||
|
goto fail;
|
||||||
|
wpa_hexdump_buf(MSG_DEBUG, "FILS: Element (DH public key)",
|
||||||
|
pub);
|
||||||
|
sm->fils_dh_elem_len = wpabuf_len(pub);
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_FILS_SK_PFS */
|
||||||
|
|
||||||
|
buf = wpabuf_alloc(1000 + sm->assoc_wpa_ie_len +
|
||||||
|
(pub ? wpabuf_len(pub) : 0));
|
||||||
if (!buf)
|
if (!buf)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
|
@ -3308,8 +3333,15 @@ struct wpabuf * fils_build_auth(struct wpa_sm *sm)
|
||||||
/* Status Code */
|
/* Status Code */
|
||||||
wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS);
|
wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS);
|
||||||
|
|
||||||
/* TODO: Finite Cyclic Group when using PK or PFS */
|
/* TODO: FILS PK */
|
||||||
/* TODO: Element when using PK or PFS */
|
#ifdef CONFIG_FILS_SK_PFS
|
||||||
|
if (dh_group) {
|
||||||
|
/* Finite Cyclic Group */
|
||||||
|
wpabuf_put_le16(buf, dh_group);
|
||||||
|
/* Element */
|
||||||
|
wpabuf_put_buf(buf, pub);
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_FILS_SK_PFS */
|
||||||
|
|
||||||
/* RSNE */
|
/* RSNE */
|
||||||
wpa_hexdump(MSG_DEBUG, "FILS: RSNE in FILS Authentication frame",
|
wpa_hexdump(MSG_DEBUG, "FILS: RSNE in FILS Authentication frame",
|
||||||
|
@ -3354,6 +3386,7 @@ struct wpabuf * fils_build_auth(struct wpa_sm *sm)
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
wpabuf_free(erp_msg);
|
wpabuf_free(erp_msg);
|
||||||
|
wpabuf_free(pub);
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3368,6 +3401,7 @@ int fils_process_auth(struct wpa_sm *sm, const u8 *bssid, const u8 *data,
|
||||||
u8 ick[FILS_ICK_MAX_LEN];
|
u8 ick[FILS_ICK_MAX_LEN];
|
||||||
size_t ick_len;
|
size_t ick_len;
|
||||||
int res;
|
int res;
|
||||||
|
struct wpabuf *dh_ss = NULL;
|
||||||
|
|
||||||
os_memcpy(sm->bssid, bssid, ETH_ALEN);
|
os_memcpy(sm->bssid, bssid, ETH_ALEN);
|
||||||
|
|
||||||
|
@ -3376,13 +3410,53 @@ int fils_process_auth(struct wpa_sm *sm, const u8 *bssid, const u8 *data,
|
||||||
pos = data;
|
pos = data;
|
||||||
end = data + len;
|
end = data + len;
|
||||||
|
|
||||||
/* TODO: Finite Cyclic Group when using PK or PFS */
|
/* TODO: FILS PK */
|
||||||
/* TODO: Element when using PK or PFS */
|
#ifdef CONFIG_FILS_SK_PFS
|
||||||
|
if (sm->fils_dh_group) {
|
||||||
|
u16 group;
|
||||||
|
|
||||||
|
/* Using FILS PFS */
|
||||||
|
|
||||||
|
/* Finite Cyclic Group */
|
||||||
|
if (end - pos < 2) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"FILS: No room for Finite Cyclic Group");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
group = WPA_GET_LE16(pos);
|
||||||
|
pos += 2;
|
||||||
|
if (group != sm->fils_dh_group) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"FILS: Unexpected change in Finite Cyclic Group: %u (expected %u)",
|
||||||
|
group, sm->fils_dh_group);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Element */
|
||||||
|
if ((size_t) (end - pos) < sm->fils_dh_elem_len) {
|
||||||
|
wpa_printf(MSG_DEBUG, "FILS: No room for Element");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sm->fils_ecdh) {
|
||||||
|
wpa_printf(MSG_DEBUG, "FILS: No ECDH state available");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
dh_ss = crypto_ecdh_set_peerkey(sm->fils_ecdh, 1, pos,
|
||||||
|
sm->fils_dh_elem_len);
|
||||||
|
if (!dh_ss) {
|
||||||
|
wpa_printf(MSG_DEBUG, "FILS: ECDH operation failed");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
wpa_hexdump_buf_key(MSG_DEBUG, "FILS: DH_SS", dh_ss);
|
||||||
|
pos += sm->fils_dh_elem_len;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_FILS_SK_PFS */
|
||||||
|
|
||||||
wpa_hexdump(MSG_DEBUG, "FILS: Remaining IEs", pos, end - pos);
|
wpa_hexdump(MSG_DEBUG, "FILS: Remaining IEs", pos, end - pos);
|
||||||
if (ieee802_11_parse_elems(pos, end - pos, &elems, 1) == ParseFailed) {
|
if (ieee802_11_parse_elems(pos, end - pos, &elems, 1) == ParseFailed) {
|
||||||
wpa_printf(MSG_DEBUG, "FILS: Could not parse elements");
|
wpa_printf(MSG_DEBUG, "FILS: Could not parse elements");
|
||||||
return -1;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* RSNE */
|
/* RSNE */
|
||||||
|
@ -3392,12 +3466,12 @@ int fils_process_auth(struct wpa_sm *sm, const u8 *bssid, const u8 *data,
|
||||||
wpa_parse_wpa_ie_rsn(elems.rsn_ie - 2, elems.rsn_ie_len + 2,
|
wpa_parse_wpa_ie_rsn(elems.rsn_ie - 2, elems.rsn_ie_len + 2,
|
||||||
&rsn) < 0) {
|
&rsn) < 0) {
|
||||||
wpa_printf(MSG_DEBUG, "FILS: No RSN element");
|
wpa_printf(MSG_DEBUG, "FILS: No RSN element");
|
||||||
return -1;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!elems.fils_nonce) {
|
if (!elems.fils_nonce) {
|
||||||
wpa_printf(MSG_DEBUG, "FILS: No FILS Nonce field");
|
wpa_printf(MSG_DEBUG, "FILS: No FILS Nonce field");
|
||||||
return -1;
|
goto fail;
|
||||||
}
|
}
|
||||||
os_memcpy(sm->fils_anonce, elems.fils_nonce, FILS_NONCE_LEN);
|
os_memcpy(sm->fils_anonce, elems.fils_nonce, FILS_NONCE_LEN);
|
||||||
wpa_hexdump(MSG_DEBUG, "FILS: ANonce", sm->fils_anonce, FILS_NONCE_LEN);
|
wpa_hexdump(MSG_DEBUG, "FILS: ANonce", sm->fils_anonce, FILS_NONCE_LEN);
|
||||||
|
@ -3412,7 +3486,7 @@ int fils_process_auth(struct wpa_sm *sm, const u8 *bssid, const u8 *data,
|
||||||
|
|
||||||
if (rsn.num_pmkid != 1) {
|
if (rsn.num_pmkid != 1) {
|
||||||
wpa_printf(MSG_DEBUG, "FILS: Invalid PMKID selection");
|
wpa_printf(MSG_DEBUG, "FILS: Invalid PMKID selection");
|
||||||
return -1;
|
goto fail;
|
||||||
}
|
}
|
||||||
wpa_hexdump(MSG_DEBUG, "FILS: PMKID", rsn.pmkid, PMKID_LEN);
|
wpa_hexdump(MSG_DEBUG, "FILS: PMKID", rsn.pmkid, PMKID_LEN);
|
||||||
if (os_memcmp(sm->cur_pmksa->pmkid, rsn.pmkid, PMKID_LEN) != 0)
|
if (os_memcmp(sm->cur_pmksa->pmkid, rsn.pmkid, PMKID_LEN) != 0)
|
||||||
|
@ -3420,7 +3494,7 @@ int fils_process_auth(struct wpa_sm *sm, const u8 *bssid, const u8 *data,
|
||||||
wpa_printf(MSG_DEBUG, "FILS: PMKID mismatch");
|
wpa_printf(MSG_DEBUG, "FILS: PMKID mismatch");
|
||||||
wpa_hexdump(MSG_DEBUG, "FILS: Expected PMKID",
|
wpa_hexdump(MSG_DEBUG, "FILS: Expected PMKID",
|
||||||
sm->cur_pmksa->pmkid, PMKID_LEN);
|
sm->cur_pmksa->pmkid, PMKID_LEN);
|
||||||
return -1;
|
goto fail;
|
||||||
}
|
}
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
"FILS: Matching PMKID - continue using PMKSA caching");
|
"FILS: Matching PMKID - continue using PMKSA caching");
|
||||||
|
@ -3435,7 +3509,7 @@ int fils_process_auth(struct wpa_sm *sm, const u8 *bssid, const u8 *data,
|
||||||
/* FILS Session */
|
/* FILS Session */
|
||||||
if (!elems.fils_session) {
|
if (!elems.fils_session) {
|
||||||
wpa_printf(MSG_DEBUG, "FILS: No FILS Session element");
|
wpa_printf(MSG_DEBUG, "FILS: No FILS Session element");
|
||||||
return -1;
|
goto fail;
|
||||||
}
|
}
|
||||||
wpa_hexdump(MSG_DEBUG, "FILS: FILS Session", elems.fils_session,
|
wpa_hexdump(MSG_DEBUG, "FILS: FILS Session", elems.fils_session,
|
||||||
FILS_SESSION_LEN);
|
FILS_SESSION_LEN);
|
||||||
|
@ -3444,7 +3518,7 @@ int fils_process_auth(struct wpa_sm *sm, const u8 *bssid, const u8 *data,
|
||||||
wpa_printf(MSG_DEBUG, "FILS: Session mismatch");
|
wpa_printf(MSG_DEBUG, "FILS: Session mismatch");
|
||||||
wpa_hexdump(MSG_DEBUG, "FILS: Expected FILS Session",
|
wpa_hexdump(MSG_DEBUG, "FILS: Expected FILS Session",
|
||||||
sm->fils_session, FILS_SESSION_LEN);
|
sm->fils_session, FILS_SESSION_LEN);
|
||||||
return -1;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FILS Wrapped Data */
|
/* FILS Wrapped Data */
|
||||||
|
@ -3458,7 +3532,7 @@ int fils_process_auth(struct wpa_sm *sm, const u8 *bssid, const u8 *data,
|
||||||
eapol_sm_process_erp_finish(sm->eapol, elems.fils_wrapped_data,
|
eapol_sm_process_erp_finish(sm->eapol, elems.fils_wrapped_data,
|
||||||
elems.fils_wrapped_data_len);
|
elems.fils_wrapped_data_len);
|
||||||
if (eapol_sm_failed(sm->eapol))
|
if (eapol_sm_failed(sm->eapol))
|
||||||
return -1;
|
goto fail;
|
||||||
|
|
||||||
rmsk_len = ERP_MAX_KEY_LEN;
|
rmsk_len = ERP_MAX_KEY_LEN;
|
||||||
res = eapol_sm_get_key(sm->eapol, rmsk, rmsk_len);
|
res = eapol_sm_get_key(sm->eapol, rmsk, rmsk_len);
|
||||||
|
@ -3467,18 +3541,22 @@ int fils_process_auth(struct wpa_sm *sm, const u8 *bssid, const u8 *data,
|
||||||
res = eapol_sm_get_key(sm->eapol, rmsk, rmsk_len);
|
res = eapol_sm_get_key(sm->eapol, rmsk, rmsk_len);
|
||||||
}
|
}
|
||||||
if (res)
|
if (res)
|
||||||
return -1;
|
goto fail;
|
||||||
|
|
||||||
res = fils_rmsk_to_pmk(sm->key_mgmt, rmsk, rmsk_len,
|
res = fils_rmsk_to_pmk(sm->key_mgmt, rmsk, rmsk_len,
|
||||||
sm->fils_nonce, sm->fils_anonce, NULL, 0,
|
sm->fils_nonce, sm->fils_anonce,
|
||||||
|
dh_ss ? wpabuf_head(dh_ss) : NULL,
|
||||||
|
dh_ss ? wpabuf_len(dh_ss) : 0,
|
||||||
sm->pmk, &sm->pmk_len);
|
sm->pmk, &sm->pmk_len);
|
||||||
os_memset(rmsk, 0, sizeof(rmsk));
|
os_memset(rmsk, 0, sizeof(rmsk));
|
||||||
|
wpabuf_clear_free(dh_ss);
|
||||||
|
dh_ss = NULL;
|
||||||
if (res)
|
if (res)
|
||||||
return -1;
|
goto fail;
|
||||||
|
|
||||||
if (!sm->fils_erp_pmkid_set) {
|
if (!sm->fils_erp_pmkid_set) {
|
||||||
wpa_printf(MSG_DEBUG, "FILS: PMKID not available");
|
wpa_printf(MSG_DEBUG, "FILS: PMKID not available");
|
||||||
return -1;
|
goto fail;
|
||||||
}
|
}
|
||||||
wpa_hexdump(MSG_DEBUG, "FILS: PMKID", sm->fils_erp_pmkid,
|
wpa_hexdump(MSG_DEBUG, "FILS: PMKID", sm->fils_erp_pmkid,
|
||||||
PMKID_LEN);
|
PMKID_LEN);
|
||||||
|
@ -3493,7 +3571,7 @@ int fils_process_auth(struct wpa_sm *sm, const u8 *bssid, const u8 *data,
|
||||||
if (!sm->cur_pmksa) {
|
if (!sm->cur_pmksa) {
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
"FILS: No remaining options to continue FILS authentication");
|
"FILS: No remaining options to continue FILS authentication");
|
||||||
return -1;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fils_pmk_to_ptk(sm->pmk, sm->pmk_len, sm->own_addr, sm->bssid,
|
if (fils_pmk_to_ptk(sm->pmk, sm->pmk_len, sm->own_addr, sm->bssid,
|
||||||
|
@ -3501,7 +3579,7 @@ int fils_process_auth(struct wpa_sm *sm, const u8 *bssid, const u8 *data,
|
||||||
ick, &ick_len, sm->key_mgmt, sm->pairwise_cipher) <
|
ick, &ick_len, sm->key_mgmt, sm->pairwise_cipher) <
|
||||||
0) {
|
0) {
|
||||||
wpa_printf(MSG_DEBUG, "FILS: Failed to derive PTK");
|
wpa_printf(MSG_DEBUG, "FILS: Failed to derive PTK");
|
||||||
return -1;
|
goto fail;
|
||||||
}
|
}
|
||||||
sm->ptk_set = 1;
|
sm->ptk_set = 1;
|
||||||
sm->tptk_set = 0;
|
sm->tptk_set = 0;
|
||||||
|
@ -3509,12 +3587,15 @@ int fils_process_auth(struct wpa_sm *sm, const u8 *bssid, const u8 *data,
|
||||||
|
|
||||||
res = fils_key_auth_sk(ick, ick_len, sm->fils_nonce,
|
res = fils_key_auth_sk(ick, ick_len, sm->fils_nonce,
|
||||||
sm->fils_anonce, sm->own_addr, sm->bssid,
|
sm->fils_anonce, sm->own_addr, sm->bssid,
|
||||||
NULL, 0, NULL, 0, /* TODO: SK+PFS */
|
NULL, 0, NULL, 0, /* TODO: PK */
|
||||||
sm->key_mgmt, sm->fils_key_auth_sta,
|
sm->key_mgmt, sm->fils_key_auth_sta,
|
||||||
sm->fils_key_auth_ap,
|
sm->fils_key_auth_ap,
|
||||||
&sm->fils_key_auth_len);
|
&sm->fils_key_auth_len);
|
||||||
os_memset(ick, 0, sizeof(ick));
|
os_memset(ick, 0, sizeof(ick));
|
||||||
return res;
|
return res;
|
||||||
|
fail:
|
||||||
|
wpabuf_clear_free(dh_ss);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -435,7 +435,7 @@ extern unsigned int tdls_testing;
|
||||||
int wpa_wnmsleep_install_key(struct wpa_sm *sm, u8 subelem_id, u8 *buf);
|
int wpa_wnmsleep_install_key(struct wpa_sm *sm, u8 subelem_id, u8 *buf);
|
||||||
void wpa_sm_set_test_assoc_ie(struct wpa_sm *sm, struct wpabuf *buf);
|
void wpa_sm_set_test_assoc_ie(struct wpa_sm *sm, struct wpabuf *buf);
|
||||||
|
|
||||||
struct wpabuf * fils_build_auth(struct wpa_sm *sm);
|
struct wpabuf * fils_build_auth(struct wpa_sm *sm, int dh_group);
|
||||||
int fils_process_auth(struct wpa_sm *sm, const u8 *bssid, const u8 *data,
|
int fils_process_auth(struct wpa_sm *sm, const u8 *bssid, const u8 *data,
|
||||||
size_t len);
|
size_t len);
|
||||||
struct wpabuf * fils_build_assoc_req(struct wpa_sm *sm, const u8 **kek,
|
struct wpabuf * fils_build_assoc_req(struct wpa_sm *sm, const u8 **kek,
|
||||||
|
|
|
@ -151,6 +151,9 @@ struct wpa_sm {
|
||||||
unsigned int fils_cache_id_set:1;
|
unsigned int fils_cache_id_set:1;
|
||||||
u8 fils_erp_pmkid[PMKID_LEN];
|
u8 fils_erp_pmkid[PMKID_LEN];
|
||||||
u8 fils_cache_id[FILS_CACHE_ID_LEN];
|
u8 fils_cache_id[FILS_CACHE_ID_LEN];
|
||||||
|
struct crypto_ecdh *fils_ecdh;
|
||||||
|
int fils_dh_group;
|
||||||
|
size_t fils_dh_elem_len;
|
||||||
#endif /* CONFIG_FILS */
|
#endif /* CONFIG_FILS */
|
||||||
|
|
||||||
#ifdef CONFIG_OWE
|
#ifdef CONFIG_OWE
|
||||||
|
|
|
@ -253,6 +253,10 @@ ifdef CONFIG_FILS
|
||||||
L_CFLAGS += -DCONFIG_FILS
|
L_CFLAGS += -DCONFIG_FILS
|
||||||
NEED_SHA384=y
|
NEED_SHA384=y
|
||||||
NEED_AES_SIV=y
|
NEED_AES_SIV=y
|
||||||
|
ifdef CONFIG_FILS_SK_PFS
|
||||||
|
L_CFLAGS += -DCONFIG_FILS_SK_PFS
|
||||||
|
NEED_ECC=y
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifdef CONFIG_WNM
|
ifdef CONFIG_WNM
|
||||||
|
|
|
@ -286,6 +286,10 @@ ifdef CONFIG_FILS
|
||||||
CFLAGS += -DCONFIG_FILS
|
CFLAGS += -DCONFIG_FILS
|
||||||
NEED_SHA384=y
|
NEED_SHA384=y
|
||||||
NEED_AES_SIV=y
|
NEED_AES_SIV=y
|
||||||
|
ifdef CONFIG_FILS_SK_PFS
|
||||||
|
CFLAGS += -DCONFIG_FILS_SK_PFS
|
||||||
|
NEED_ECC=y
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifdef CONFIG_WNM
|
ifdef CONFIG_WNM
|
||||||
|
|
|
@ -2147,6 +2147,7 @@ static const struct parse_data ssid_fields[] = {
|
||||||
{ INT_RANGE(mac_addr, 0, 2) },
|
{ INT_RANGE(mac_addr, 0, 2) },
|
||||||
{ INT_RANGE(pbss, 0, 2) },
|
{ INT_RANGE(pbss, 0, 2) },
|
||||||
{ INT_RANGE(wps_disabled, 0, 1) },
|
{ INT_RANGE(wps_disabled, 0, 1) },
|
||||||
|
{ INT_RANGE(fils_dh_group, 0, 65535) },
|
||||||
};
|
};
|
||||||
|
|
||||||
#undef OFFSET
|
#undef OFFSET
|
||||||
|
|
|
@ -800,6 +800,7 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid)
|
||||||
INT(vht_center_freq2);
|
INT(vht_center_freq2);
|
||||||
INT(pbss);
|
INT(pbss);
|
||||||
INT(wps_disabled);
|
INT(wps_disabled);
|
||||||
|
INT(fils_dh_group);
|
||||||
#ifdef CONFIG_IEEE80211W
|
#ifdef CONFIG_IEEE80211W
|
||||||
write_int(f, "ieee80211w", ssid->ieee80211w,
|
write_int(f, "ieee80211w", ssid->ieee80211w,
|
||||||
MGMT_FRAME_PROTECTION_DEFAULT);
|
MGMT_FRAME_PROTECTION_DEFAULT);
|
||||||
|
|
|
@ -814,6 +814,14 @@ struct wpa_ssid {
|
||||||
* 1 = WPS disabled
|
* 1 = WPS disabled
|
||||||
*/
|
*/
|
||||||
int wps_disabled;
|
int wps_disabled;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fils_dh_group - FILS DH Group
|
||||||
|
*
|
||||||
|
* 0 = PFS disabled with FILS shared key authentication
|
||||||
|
* 1-65535 DH Group to use for FILS PFS
|
||||||
|
*/
|
||||||
|
int fils_dh_group;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* CONFIG_SSID_H */
|
#endif /* CONFIG_SSID_H */
|
||||||
|
|
|
@ -558,6 +558,8 @@ CONFIG_PEERKEY=y
|
||||||
# Note: This is an experimental and not yet complete implementation. This
|
# Note: This is an experimental and not yet complete implementation. This
|
||||||
# should not be enabled for production use.
|
# should not be enabled for production use.
|
||||||
#CONFIG_FILS=y
|
#CONFIG_FILS=y
|
||||||
|
# FILS shared key authentication with PFS
|
||||||
|
#CONFIG_FILS_SK_PFS=y
|
||||||
|
|
||||||
# Support RSN on IBSS networks
|
# Support RSN on IBSS networks
|
||||||
# This is needed to be able to use mode=1 network profile with proto=RSN and
|
# This is needed to be able to use mode=1 network profile with proto=RSN and
|
||||||
|
|
|
@ -2214,7 +2214,8 @@ static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s,
|
||||||
|
|
||||||
#ifdef CONFIG_FILS
|
#ifdef CONFIG_FILS
|
||||||
#ifdef CONFIG_SME
|
#ifdef CONFIG_SME
|
||||||
if (wpa_s->sme.auth_alg == WPA_AUTH_ALG_FILS &&
|
if ((wpa_s->sme.auth_alg == WPA_AUTH_ALG_FILS ||
|
||||||
|
wpa_s->sme.auth_alg == WPA_AUTH_ALG_FILS_SK_PFS) &&
|
||||||
(!data->assoc_info.resp_frame ||
|
(!data->assoc_info.resp_frame ||
|
||||||
fils_process_assoc_resp(wpa_s->wpa,
|
fils_process_assoc_resp(wpa_s->wpa,
|
||||||
data->assoc_info.resp_frame,
|
data->assoc_info.resp_frame,
|
||||||
|
|
|
@ -563,12 +563,23 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s,
|
||||||
0)
|
0)
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
"SME: Try to use FILS with PMKSA caching");
|
"SME: Try to use FILS with PMKSA caching");
|
||||||
resp = fils_build_auth(wpa_s->wpa);
|
resp = fils_build_auth(wpa_s->wpa, ssid->fils_dh_group);
|
||||||
if (resp) {
|
if (resp) {
|
||||||
params.auth_alg = WPA_AUTH_ALG_FILS;
|
int auth_alg;
|
||||||
|
|
||||||
|
if (ssid->fils_dh_group)
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"SME: Try to use FILS SK authentication with PFS (DH Group %u)",
|
||||||
|
ssid->fils_dh_group);
|
||||||
|
else
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"SME: Try to use FILS SK authentication without PFS");
|
||||||
|
auth_alg = ssid->fils_dh_group ?
|
||||||
|
WPA_AUTH_ALG_FILS_SK_PFS : WPA_AUTH_ALG_FILS;
|
||||||
|
params.auth_alg = auth_alg;
|
||||||
params.auth_data = wpabuf_head(resp);
|
params.auth_data = wpabuf_head(resp);
|
||||||
params.auth_data_len = wpabuf_len(resp);
|
params.auth_data_len = wpabuf_len(resp);
|
||||||
wpa_s->sme.auth_alg = WPA_AUTH_ALG_FILS;
|
wpa_s->sme.auth_alg = auth_alg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_FILS */
|
#endif /* CONFIG_FILS */
|
||||||
|
@ -968,7 +979,27 @@ void sme_event_auth(struct wpa_supplicant *wpa_s, union wpa_event_data *data)
|
||||||
#endif /* CONFIG_IEEE80211R */
|
#endif /* CONFIG_IEEE80211R */
|
||||||
|
|
||||||
#ifdef CONFIG_FILS
|
#ifdef CONFIG_FILS
|
||||||
if (data->auth.auth_type == WLAN_AUTH_FILS_SK) {
|
if (data->auth.auth_type == WLAN_AUTH_FILS_SK ||
|
||||||
|
data->auth.auth_type == WLAN_AUTH_FILS_SK_PFS) {
|
||||||
|
u16 expect_auth_type;
|
||||||
|
|
||||||
|
expect_auth_type = wpa_s->sme.auth_alg ==
|
||||||
|
WPA_AUTH_ALG_FILS_SK_PFS ? WLAN_AUTH_FILS_SK_PFS :
|
||||||
|
WLAN_AUTH_FILS_SK;
|
||||||
|
if (data->auth.auth_type != expect_auth_type) {
|
||||||
|
wpa_dbg(wpa_s, MSG_DEBUG,
|
||||||
|
"SME: FILS Authentication response used different auth alg (%u; expected %u)",
|
||||||
|
data->auth.auth_type, expect_auth_type);
|
||||||
|
wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DISCONNECTED "bssid="
|
||||||
|
MACSTR
|
||||||
|
" reason=%d locally_generated=1",
|
||||||
|
MAC2STR(wpa_s->pending_bssid),
|
||||||
|
WLAN_REASON_DEAUTH_LEAVING);
|
||||||
|
wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
|
||||||
|
wpa_supplicant_mark_disassoc(wpa_s);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (fils_process_auth(wpa_s->wpa, wpa_s->pending_bssid,
|
if (fils_process_auth(wpa_s->wpa, wpa_s->pending_bssid,
|
||||||
data->auth.ies, data->auth.ies_len) < 0) {
|
data->auth.ies, data->auth.ies_len) < 0) {
|
||||||
wpa_dbg(wpa_s, MSG_DEBUG,
|
wpa_dbg(wpa_s, MSG_DEBUG,
|
||||||
|
@ -1010,7 +1041,8 @@ void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode,
|
||||||
os_memset(¶ms, 0, sizeof(params));
|
os_memset(¶ms, 0, sizeof(params));
|
||||||
|
|
||||||
#ifdef CONFIG_FILS
|
#ifdef CONFIG_FILS
|
||||||
if (auth_type == WLAN_AUTH_FILS_SK) {
|
if (auth_type == WLAN_AUTH_FILS_SK ||
|
||||||
|
auth_type == WLAN_AUTH_FILS_SK_PFS) {
|
||||||
struct wpabuf *buf;
|
struct wpabuf *buf;
|
||||||
const u8 *snonce, *anonce;
|
const u8 *snonce, *anonce;
|
||||||
const unsigned int max_hlp = 20;
|
const unsigned int max_hlp = 20;
|
||||||
|
|
|
@ -1248,6 +1248,11 @@ fast_reauth=1
|
||||||
# 1 = WPS disabled
|
# 1 = WPS disabled
|
||||||
#wps_disabled=0
|
#wps_disabled=0
|
||||||
|
|
||||||
|
# FILS DH Group
|
||||||
|
# 0 = PFS disabled with FILS shared key authentication (default)
|
||||||
|
# 1-65535 = DH Group to use for FILS PFS
|
||||||
|
#fils_dh_group=0
|
||||||
|
|
||||||
# MAC address policy
|
# MAC address policy
|
||||||
# 0 = use permanent MAC address
|
# 0 = use permanent MAC address
|
||||||
# 1 = use random MAC address for each ESS connection
|
# 1 = use random MAC address for each ESS connection
|
||||||
|
|
Loading…
Reference in a new issue