]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
FILS: Add DHss into FILS-Key-Data derivation when using FILS SK+PFS
authorJouni Malinen <jouni@qca.qualcomm.com>
Wed, 13 Sep 2017 18:36:05 +0000 (21:36 +0300)
committerJouni Malinen <j@w1.fi>
Wed, 13 Sep 2017 19:17:58 +0000 (22:17 +0300)
This part is missing from IEEE Std 802.11ai-2016, but the lack of DHss
here means there would not be proper PFS for the case where PMKSA
caching is used with FILS SK+PFS authentication. This was not really the
intent of the FILS design and that issue was fixed during REVmd work
with the changes proposed in
https://mentor.ieee.org/802.11/dcn/17/11-17-0906-04-000m-fils-fixes.docx
that add DHss into FILS-Key-Data (and PTK, in practice) derivation for
the PMKSA caching case so that a unique ICK, KEK, and TK are derived
even when using the same PMK.

Note: This is not backwards compatible, i.e., this breaks PMKSA caching
with FILS SK+PFS if only STA or AP side implementation is updated.

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
src/ap/ieee802_11.c
src/ap/wpa_auth.c
src/ap/wpa_auth.h
src/common/wpa_common.c
src/common/wpa_common.h
src/rsn_supp/wpa.c
wlantest/rx_mgmt.c

index 0be9b49dde11536bd307ab3102e9c87f0c9cba6d..4252fccaaca4b453c2b8f22c0b7bf02964f0b004 100644 (file)
@@ -1417,6 +1417,11 @@ prepare_auth_resp_fils(struct hostapd_data *hapd,
                }
                pmk = pmk_buf;
 
+               /* Don't use DHss in PTK derivation if PMKSA caching is not
+                * used. */
+               wpabuf_clear_free(sta->fils_dh_ss);
+               sta->fils_dh_ss = NULL;
+
                if (sta->fils_erp_pmkid_set) {
                        /* TODO: get PMKLifetime from WPA parameters */
                        unsigned int dot11RSNAConfigPMKLifetime = 43200;
@@ -1449,6 +1454,10 @@ prepare_auth_resp_fils(struct hostapd_data *hapd,
 
        if (fils_auth_pmk_to_ptk(sta->wpa_sm, pmk, pmk_len,
                                 sta->fils_snonce, fils_nonce,
+                                sta->fils_dh_ss ?
+                                wpabuf_head(sta->fils_dh_ss) : NULL,
+                                sta->fils_dh_ss ?
+                                wpabuf_len(sta->fils_dh_ss) : 0,
                                 sta->fils_g_sta, pub) < 0) {
                *resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
                wpabuf_free(data);
index 56857e855785a76149eb9168d65889419e2ce659..e5b66b397c389132f4585f292629b4c1ad7287b7 100644 (file)
@@ -2113,6 +2113,7 @@ static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce,
 
 int fils_auth_pmk_to_ptk(struct wpa_state_machine *sm, const u8 *pmk,
                         size_t pmk_len, const u8 *snonce, const u8 *anonce,
+                        const u8 *dhss, size_t dhss_len,
                         struct wpabuf *g_sta, struct wpabuf *g_ap)
 {
        u8 ick[FILS_ICK_MAX_LEN];
@@ -2122,7 +2123,8 @@ int fils_auth_pmk_to_ptk(struct wpa_state_machine *sm, const u8 *pmk,
        size_t fils_ft_len = 0;
 
        res = fils_pmk_to_ptk(pmk, pmk_len, sm->addr, sm->wpa_auth->addr,
-                             snonce, anonce, &sm->PTK, ick, &ick_len,
+                             snonce, anonce, dhss, dhss_len,
+                             &sm->PTK, ick, &ick_len,
                              sm->wpa_key_mgmt, sm->pairwise,
                              fils_ft, &fils_ft_len);
        if (res < 0)
index df4fac5cf7c59c0fa799ce4ecfa0ce0c97342822..5e8a4cc840a98f0631524ab516a231c2bb6adb12 100644 (file)
@@ -400,6 +400,7 @@ int wpa_auth_ensure_group(struct wpa_authenticator *wpa_auth, int vlan_id);
 int wpa_auth_release_group(struct wpa_authenticator *wpa_auth, int vlan_id);
 int fils_auth_pmk_to_ptk(struct wpa_state_machine *sm, const u8 *pmk,
                         size_t pmk_len, const u8 *snonce, const u8 *anonce,
+                        const u8 *dhss, size_t dhss_len,
                         struct wpabuf *g_sta, struct wpabuf *g_ap);
 int fils_decrypt_assoc(struct wpa_state_machine *sm, const u8 *fils_session,
                       const struct ieee80211_mgmt *mgmt, size_t frame_len,
index 68e7883773a32dd0c83f73d43d0ca9180317518b..4efb04604ec467dbcc46874a6ffa0901cdccd33d 100644 (file)
@@ -389,19 +389,22 @@ int fils_pmkid_erp(int akmp, const u8 *reauth, size_t reauth_len,
 
 
 int fils_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const u8 *spa, const u8 *aa,
-                   const u8 *snonce, const u8 *anonce, struct wpa_ptk *ptk,
+                   const u8 *snonce, const u8 *anonce, const u8 *dhss,
+                   size_t dhss_len, struct wpa_ptk *ptk,
                    u8 *ick, size_t *ick_len, int akmp, int cipher,
                    u8 *fils_ft, size_t *fils_ft_len)
 {
-       u8 data[2 * ETH_ALEN + 2 * FILS_NONCE_LEN];
+       u8 *data, *pos;
+       size_t data_len;
        u8 tmp[FILS_ICK_MAX_LEN + WPA_KEK_MAX_LEN + WPA_TK_MAX_LEN +
               FILS_FT_MAX_LEN];
        size_t key_data_len;
        const char *label = "FILS PTK Derivation";
+       int ret = -1;
 
        /*
         * FILS-Key-Data = PRF-X(PMK, "FILS PTK Derivation",
-        *                       SPA || AA || SNonce || ANonce)
+        *                       SPA || AA || SNonce || ANonce [ || DHss ])
         * ICK = L(FILS-Key-Data, 0, ICK_bits)
         * KEK = L(FILS-Key-Data, ICK_bits, KEK_bits)
         * TK = L(FILS-Key-Data, ICK_bits + KEK_bits, TK_bits)
@@ -409,10 +412,21 @@ int fils_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const u8 *spa, const u8 *aa,
         * FILS-FT = L(FILS-Key-Data, ICK_bits + KEK_bits + TK_bits,
         *             FILS-FT_bits)
         */
-       os_memcpy(data, spa, ETH_ALEN);
-       os_memcpy(data + ETH_ALEN, aa, ETH_ALEN);
-       os_memcpy(data + 2 * ETH_ALEN, snonce, FILS_NONCE_LEN);
-       os_memcpy(data + 2 * ETH_ALEN + FILS_NONCE_LEN, anonce, FILS_NONCE_LEN);
+       data_len = 2 * ETH_ALEN + 2 * FILS_NONCE_LEN + dhss_len;
+       data = os_malloc(data_len);
+       if (!data)
+               goto err;
+       pos = data;
+       os_memcpy(pos, spa, ETH_ALEN);
+       pos += ETH_ALEN;
+       os_memcpy(pos, aa, ETH_ALEN);
+       pos += ETH_ALEN;
+       os_memcpy(pos, snonce, FILS_NONCE_LEN);
+       pos += FILS_NONCE_LEN;
+       os_memcpy(pos, anonce, FILS_NONCE_LEN);
+       pos += FILS_NONCE_LEN;
+       if (dhss)
+               os_memcpy(pos, dhss, dhss_len);
 
        ptk->kck_len = 0;
        ptk->kek_len = wpa_kek_len(akmp, pmk_len);
@@ -422,7 +436,7 @@ int fils_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const u8 *spa, const u8 *aa,
        else if (wpa_key_mgmt_sha256(akmp))
                *ick_len = 32;
        else
-               return -1;
+               goto err;
        key_data_len = *ick_len + ptk->kek_len + ptk->tk_len;
 
        if (fils_ft && fils_ft_len) {
@@ -439,20 +453,22 @@ int fils_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const u8 *spa, const u8 *aa,
 
        if (wpa_key_mgmt_sha384(akmp)) {
                wpa_printf(MSG_DEBUG, "FILS: PTK derivation using PRF(SHA384)");
-               if (sha384_prf(pmk, pmk_len, label, data, sizeof(data),
+               if (sha384_prf(pmk, pmk_len, label, data, data_len,
                               tmp, key_data_len) < 0)
-                       return -1;
+                       goto err;
        } else {
                wpa_printf(MSG_DEBUG, "FILS: PTK derivation using PRF(SHA256)");
-               if (sha256_prf(pmk, pmk_len, label, data, sizeof(data),
+               if (sha256_prf(pmk, pmk_len, label, data, data_len,
                               tmp, key_data_len) < 0)
-                       return -1;
+                       goto err;
        }
 
        wpa_printf(MSG_DEBUG, "FILS: PTK derivation - SPA=" MACSTR
                   " AA=" MACSTR, MAC2STR(spa), MAC2STR(aa));
        wpa_hexdump(MSG_DEBUG, "FILS: SNonce", snonce, FILS_NONCE_LEN);
        wpa_hexdump(MSG_DEBUG, "FILS: ANonce", anonce, FILS_NONCE_LEN);
+       if (dhss)
+               wpa_hexdump_key(MSG_DEBUG, "FILS: DHss", dhss, dhss_len);
        wpa_hexdump_key(MSG_DEBUG, "FILS: PMK", pmk, pmk_len);
        wpa_hexdump_key(MSG_DEBUG, "FILS: FILS-Key-Data", tmp, key_data_len);
 
@@ -473,7 +489,10 @@ int fils_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const u8 *spa, const u8 *aa,
        }
 
        os_memset(tmp, 0, sizeof(tmp));
-       return 0;
+       ret = 0;
+err:
+       bin_clear_free(data, data_len);
+       return ret;
 }
 
 
index b4d6c1384b8798ac93113420c79b7a9ee2341233..2f11d2f345059f2a79b88f8cc93f1c1593060ca6 100644 (file)
@@ -347,7 +347,8 @@ int fils_rmsk_to_pmk(int akmp, const u8 *rmsk, size_t rmsk_len,
 int fils_pmkid_erp(int akmp, const u8 *reauth, size_t reauth_len,
                   u8 *pmkid);
 int fils_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const u8 *spa, const u8 *aa,
-                   const u8 *snonce, const u8 *anonce, struct wpa_ptk *ptk,
+                   const u8 *snonce, const u8 *anonce, const u8 *dhss,
+                   size_t dhss_len, struct wpa_ptk *ptk,
                    u8 *ick, size_t *ick_len, int akmp, int cipher,
                    u8 *fils_ft, size_t *fils_ft_len);
 int fils_key_auth_sk(const u8 *ick, size_t ick_len, const u8 *snonce,
index ab2302b8c1061dad1f1216eb36f2b6f72a4680da..739689d18b02f538af9e4f9e457a24c6b27a7af1 100644 (file)
@@ -3639,8 +3639,12 @@ int fils_process_auth(struct wpa_sm *sm, const u8 *bssid, const u8 *data,
                                       dh_ss ? wpabuf_len(dh_ss) : 0,
                                       sm->pmk, &sm->pmk_len);
                os_memset(rmsk, 0, sizeof(rmsk));
+
+               /* Don't use DHss in PTK derivation if PMKSA caching is not
+                * used. */
                wpabuf_clear_free(dh_ss);
                dh_ss = NULL;
+
                if (res)
                        goto fail;
 
@@ -3665,12 +3669,19 @@ int fils_process_auth(struct wpa_sm *sm, const u8 *bssid, const u8 *data,
        }
 
        if (fils_pmk_to_ptk(sm->pmk, sm->pmk_len, sm->own_addr, sm->bssid,
-                           sm->fils_nonce, sm->fils_anonce, &sm->ptk,
-                           ick, &ick_len, sm->key_mgmt, sm->pairwise_cipher,
+                           sm->fils_nonce, sm->fils_anonce,
+                           dh_ss ? wpabuf_head(dh_ss) : NULL,
+                           dh_ss ? wpabuf_len(dh_ss) : 0,
+                           &sm->ptk, ick, &ick_len,
+                           sm->key_mgmt, sm->pairwise_cipher,
                            sm->fils_ft, &sm->fils_ft_len) < 0) {
                wpa_printf(MSG_DEBUG, "FILS: Failed to derive PTK");
                goto fail;
        }
+
+       wpabuf_clear_free(dh_ss);
+       dh_ss = NULL;
+
        sm->ptk_set = 1;
        sm->tptk_set = 0;
        os_memset(&sm->tptk, 0, sizeof(sm->tptk));
index b15f561e335f0caad6c7f842f6dd9800993d6aa8..08ebd88ccce0be1e7d8f061eabd76dfe6b986218 100644 (file)
@@ -351,7 +351,8 @@ static int try_rmsk(struct wlantest *wt, struct wlantest_bss *bss,
                return -1;
 
        if (fils_pmk_to_ptk(pmk_buf, pmk_len, sta->addr, bss->bssid,
-                           sta->snonce, sta->anonce, &ptk, ick, &ick_len,
+                           sta->snonce, sta->anonce, NULL, 0,
+                           &ptk, ick, &ick_len,
                            sta->key_mgmt, sta->pairwise_cipher,
                            NULL, NULL) < 0)
                return -1;