]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
FILS+FT: AP mode processing of PMKR1Name in initial MD association
authorJouni Malinen <jouni@codeaurora.org>
Wed, 13 Mar 2019 15:24:29 +0000 (17:24 +0200)
committerJouni Malinen <j@w1.fi>
Wed, 13 Mar 2019 17:15:06 +0000 (19:15 +0200)
Derive PMKR1Name during the FILS authentication step, verify that the
station uses matching PMKR1Name in (Re)Association Request frame, and
add RSNE[PMKR1Name] into (Re)Association Response frame when going
through FT initial mobility domain association using FILS. These steps
were missed from the initial implementation, but are needed to match the
IEEE 802.11ai requirements for explicit confirmation of the FT key
hierarchy (similarly to what is done in FT 4-way handshake when FILS is
not used).

Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
src/ap/ieee802_11.c
src/ap/wpa_auth.c
src/ap/wpa_auth.h
src/ap/wpa_auth_ft.c
src/ap/wpa_auth_i.h
src/ap/wpa_auth_ie.c

index eee4683960644fc6389c601169f2cf38ebf7816b..78f01dfa5b83dfafe6212e50b2b5eb605edf9479 100644 (file)
@@ -2865,6 +2865,7 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
                                   "state machine");
                        return WLAN_STATUS_UNSPECIFIED_FAILURE;
                }
+               wpa_auth_set_auth_alg(sta->wpa_sm, sta->auth_alg);
                res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
                                          hapd->iface->freq,
                                          wpa_ie, wpa_ie_len,
index cc77acb1b1e14f6bd256e150a9aaabe0fa6adf96..1cb8113d0af2e7ae1d4c5a01b6edc14a4c460ba9 100644 (file)
@@ -2210,6 +2210,16 @@ int fils_auth_pmk_to_ptk(struct wpa_state_machine *sm, const u8 *pmk,
                            pmk_r0_name, WPA_PMK_NAME_LEN);
                wpa_ft_store_pmk_fils(sm, pmk_r0, pmk_r0_name);
                os_memset(fils_ft, 0, sizeof(fils_ft));
+
+               res = wpa_derive_pmk_r1_name(pmk_r0_name, conf->r1_key_holder,
+                                            sm->addr, sm->pmk_r1_name,
+                                            use_sha384);
+               os_memset(pmk_r0, 0, PMK_LEN_MAX);
+               if (res < 0)
+                       return -1;
+               wpa_hexdump(MSG_DEBUG, "FILS+FT: PMKR1Name", sm->pmk_r1_name,
+                           WPA_PMK_NAME_LEN);
+               sm->pmk_r1_name_valid = 1;
        }
 #endif /* CONFIG_IEEE80211R_AP */
 
@@ -4812,6 +4822,13 @@ void wpa_auth_get_fils_aead_params(struct wpa_state_machine *sm,
 #endif /* CONFIG_FILS */
 
 
+void wpa_auth_set_auth_alg(struct wpa_state_machine *sm, u16 auth_alg)
+{
+       if (sm)
+               sm->auth_alg = auth_alg;
+}
+
+
 #ifdef CONFIG_TESTING_OPTIONS
 
 int wpa_auth_resend_m1(struct wpa_state_machine *sm, int change_anonce,
index 1d57dcae7fad19bee968690096d9f2f7c64ab702..50a8d1743f532f31ecae8abd79fecd828fc45728 100644 (file)
@@ -473,6 +473,7 @@ void wpa_auth_get_fils_aead_params(struct wpa_state_machine *sm,
 u8 * wpa_auth_write_assoc_resp_owe(struct wpa_state_machine *sm,
                                   u8 *pos, size_t max_len,
                                   const u8 *req_ies, size_t req_ies_len);
+void wpa_auth_set_auth_alg(struct wpa_state_machine *sm, u16 auth_alg);
 
 int wpa_auth_resend_m1(struct wpa_state_machine *sm, int change_anonce,
                       void (*cb)(void *ctx1, void *ctx2),
index 31ca4e5d023354676d98bdc2a5fce46af4f859bc..1fb6a0d86c9a13f640b1fcc651e2d1f660c43e6d 100644 (file)
@@ -2386,10 +2386,24 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
 
        end = pos + max_len;
 
-       if (auth_alg == WLAN_AUTH_FT) {
+       if (auth_alg == WLAN_AUTH_FT ||
+           ((auth_alg == WLAN_AUTH_FILS_SK ||
+             auth_alg == WLAN_AUTH_FILS_SK_PFS ||
+             auth_alg == WLAN_AUTH_FILS_PK) &&
+            (sm->wpa_key_mgmt & (WPA_KEY_MGMT_FT_FILS_SHA256 |
+                                 WPA_KEY_MGMT_FT_FILS_SHA384)))) {
+               if (!sm->pmk_r1_name_valid) {
+                       wpa_printf(MSG_ERROR,
+                                  "FT: PMKR1Name is not valid for Assoc Resp RSNE");
+                       return NULL;
+               }
+               wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name for Assoc Resp RSNE",
+                           sm->pmk_r1_name, WPA_PMK_NAME_LEN);
                /*
                 * RSN (only present if this is a Reassociation Response and
-                * part of a fast BSS transition)
+                * part of a fast BSS transition; or if this is a
+                * (Re)Association Response frame during an FT initial mobility
+                * domain association using FILS)
                 */
                res = wpa_write_rsn_ie(conf, pos, end - pos, sm->pmk_r1_name);
                if (res < 0)
index a349304d5f5d3a97ed1c52cad7a9edcc43bffaab..a3164d26558be0da2eb667ceb08a934b09baedfb 100644 (file)
@@ -22,6 +22,7 @@ struct wpa_state_machine {
 
        u8 addr[ETH_ALEN];
        u8 p2p_dev_addr[ETH_ALEN];
+       u16 auth_alg;
 
        enum {
                WPA_PTK_INITIALIZE, WPA_PTK_DISCONNECT, WPA_PTK_DISCONNECTED,
index 4a96008c1ff18e9e6c526e0090319e412c52a28e..791c5a01b553a0e4a954278eebb95fe03b30226d 100644 (file)
@@ -852,6 +852,21 @@ int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
        else
                sm->wpa = WPA_VERSION_WPA;
 
+#if defined(CONFIG_IEEE80211R_AP) && defined(CONFIG_FILS)
+       if ((sm->wpa_key_mgmt == WPA_KEY_MGMT_FT_FILS_SHA256 ||
+            sm->wpa_key_mgmt == WPA_KEY_MGMT_FT_FILS_SHA384) &&
+           (sm->auth_alg == WLAN_AUTH_FILS_SK ||
+            sm->auth_alg == WLAN_AUTH_FILS_SK_PFS ||
+            sm->auth_alg == WLAN_AUTH_FILS_PK) &&
+           (data.num_pmkid != 1 || !data.pmkid || !sm->pmk_r1_name_valid ||
+            os_memcmp_const(data.pmkid, sm->pmk_r1_name,
+                            WPA_PMK_NAME_LEN) != 0)) {
+               wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
+                                "No PMKR1Name match for FILS+FT");
+               return WPA_INVALID_PMKID;
+       }
+#endif /* CONFIG_IEEE80211R_AP && CONFIG_FILS */
+
        sm->pmksa = NULL;
        for (i = 0; i < data.num_pmkid; i++) {
                wpa_hexdump(MSG_DEBUG, "RSN IE: STA PMKID",