]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
FT: Extend PMK-R0 derivation for FT-SAE-EXT-KEY
authorJouni Malinen <quic_jouni@quicinc.com>
Sun, 16 Oct 2022 13:38:27 +0000 (16:38 +0300)
committerJouni Malinen <j@w1.fi>
Sun, 16 Oct 2022 14:43:11 +0000 (17:43 +0300)
Provide AKM to the helper function to cover the SHA512-based derivation
case.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
src/ap/wpa_auth.c
src/ap/wpa_auth_ft.c
src/common/wpa_common.c
src/common/wpa_common.h
src/rsn_supp/wpa.c
src/rsn_supp/wpa_ft.c
wlantest/rx_eapol.c

index 0806ff0fbea872cd1728fa0763f04e96650aad0f..736c2feb6b1040e815843371176da778448bb615 100644 (file)
@@ -2459,7 +2459,6 @@ int fils_auth_pmk_to_ptk(struct wpa_state_machine *sm, const u8 *pmk,
                struct wpa_authenticator *wpa_auth = sm->wpa_auth;
                struct wpa_auth_config *conf = &wpa_auth->conf;
                u8 pmk_r0[PMK_LEN_MAX], pmk_r0_name[WPA_PMK_NAME_LEN];
-               int use_sha384 = wpa_key_mgmt_sha384(sm->wpa_key_mgmt);
 
                if (wpa_derive_pmk_r0(fils_ft, fils_ft_len,
                                      conf->ssid, conf->ssid_len,
@@ -2467,7 +2466,7 @@ int fils_auth_pmk_to_ptk(struct wpa_state_machine *sm, const u8 *pmk,
                                      conf->r0_key_holder,
                                      conf->r0_key_holder_len,
                                      sm->addr, pmk_r0, pmk_r0_name,
-                                     use_sha384) < 0)
+                                     sm->wpa_key_mgmt) < 0)
                        return -1;
 
                wpa_ft_store_pmk_fils(sm, pmk_r0, pmk_r0_name);
index 27a2ba3cf91a9e114a406e822532ec12f2ad2a7e..9ad7bbc1928e681893df36d532d6e4d4ec20232f 100644 (file)
@@ -2108,9 +2108,7 @@ int wpa_ft_store_pmk_fils(struct wpa_state_machine *sm,
 int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, struct wpa_ptk *ptk)
 {
        u8 pmk_r0[PMK_LEN_MAX], pmk_r0_name[WPA_PMK_NAME_LEN];
-       size_t pmk_r0_len = wpa_key_mgmt_sha384(sm->wpa_key_mgmt) ?
-               SHA384_MAC_LEN : PMK_LEN;
-       size_t pmk_r1_len = pmk_r0_len;
+       size_t pmk_r0_len, pmk_r1_len;
        u8 pmk_r1[PMK_LEN_MAX];
        u8 ptk_name[WPA_PMK_NAME_LEN];
        const u8 *mdid = sm->wpa_auth->conf.mobility_domain;
@@ -2128,6 +2126,17 @@ int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, struct wpa_ptk *ptk)
        const u8 *mpmk;
        size_t mpmk_len;
 
+       if (sm->wpa_key_mgmt == WPA_KEY_MGMT_FT_SAE_EXT_KEY &&
+           (sm->xxkey_len == SHA256_MAC_LEN ||
+            sm->xxkey_len == SHA384_MAC_LEN ||
+            sm->xxkey_len == SHA512_MAC_LEN))
+               pmk_r0_len = sm->xxkey_len;
+       else if (wpa_key_mgmt_sha384(sm->wpa_key_mgmt))
+               pmk_r0_len = SHA384_MAC_LEN;
+       else
+               pmk_r0_len = PMK_LEN;
+       pmk_r1_len = pmk_r0_len;
+
        if (sm->xxkey_len > 0) {
                mpmk = sm->xxkey;
                mpmk_len = sm->xxkey_len;
@@ -2154,7 +2163,7 @@ int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, struct wpa_ptk *ptk)
        if (wpa_derive_pmk_r0(mpmk, mpmk_len, ssid, ssid_len, mdid,
                              r0kh, r0kh_len, sm->addr,
                              pmk_r0, pmk_r0_name,
-                             wpa_key_mgmt_sha384(sm->wpa_key_mgmt)) < 0)
+                             sm->wpa_key_mgmt) < 0)
                return -1;
        if (!psk_local || !wpa_key_mgmt_ft_psk(sm->wpa_key_mgmt))
                wpa_ft_store_pmk_r0(sm->wpa_auth, sm->addr, pmk_r0, pmk_r0_len,
@@ -2955,7 +2964,8 @@ static int wpa_ft_psk_pmk_r1(struct wpa_state_machine *sm,
 
                if (wpa_derive_pmk_r0(pmk, PMK_LEN, ssid, ssid_len, mdid, r0kh,
                                      r0kh_len, sm->addr,
-                                     pmk_r0, pmk_r0_name, 0) < 0 ||
+                                     pmk_r0, pmk_r0_name,
+                                     WPA_KEY_MGMT_FT_PSK) < 0 ||
                    wpa_derive_pmk_r1(pmk_r0, PMK_LEN, pmk_r0_name, r1kh,
                                      sm->addr, pmk_r1, pmk_r1_name) < 0 ||
                    os_memcmp_const(pmk_r1_name, req_pmk_r1_name,
index 11620ccfc693972f904391a022df6413a204b565..38bca41a0b629103f8b956c771e4ca539813f1e5 100644 (file)
@@ -2059,30 +2059,40 @@ int wpa_derive_pmk_r0(const u8 *xxkey, size_t xxkey_len,
                      const u8 *ssid, size_t ssid_len,
                      const u8 *mdid, const u8 *r0kh_id, size_t r0kh_id_len,
                      const u8 *s0kh_id, u8 *pmk_r0, u8 *pmk_r0_name,
-                     int use_sha384)
+                     int key_mgmt)
 {
        u8 buf[1 + SSID_MAX_LEN + MOBILITY_DOMAIN_ID_LEN + 1 +
               FT_R0KH_ID_MAX_LEN + ETH_ALEN];
-       u8 *pos, r0_key_data[64], hash[48];
+       u8 *pos, r0_key_data[64], hash[64];
        const u8 *addr[2];
        size_t len[2];
-       size_t q = use_sha384 ? 48 : 32;
-       size_t r0_key_data_len = q + 16;
+       size_t q, r0_key_data_len;
+       int res;
+
+       if (key_mgmt == WPA_KEY_MGMT_FT_SAE_EXT_KEY &&
+           (xxkey_len == SHA256_MAC_LEN || xxkey_len == SHA384_MAC_LEN ||
+            xxkey_len == SHA512_MAC_LEN))
+               q = xxkey_len;
+       else if (wpa_key_mgmt_sha384(key_mgmt))
+               q = SHA384_MAC_LEN;
+       else
+               q = SHA256_MAC_LEN;
+       r0_key_data_len = q + 16;
 
        /*
-        * R0-Key-Data = KDF-384(XXKey, "FT-R0",
+        * R0-Key-Data = KDF-Hash-Length(XXKey, "FT-R0",
         *                       SSIDlength || SSID || MDID || R0KHlength ||
         *                       R0KH-ID || S0KH-ID)
         * XXKey is either the second 256 bits of MSK or PSK; or the first
-        * 384 bits of MSK for FT-EAP-SHA384.
+        * 384 bits of MSK for FT-EAP-SHA384; or PMK from SAE.
         * PMK-R0 = L(R0-Key-Data, 0, Q)
         * PMK-R0Name-Salt = L(R0-Key-Data, Q, 128)
-        * Q = 384 for FT-EAP-SHA384; otherwise, 256
+        * Q = 384 for FT-EAP-SHA384; the length of the digest generated by H()
+        * for FT-SAE-EXT-KEY; or otherwise, 256
         */
        if (ssid_len > SSID_MAX_LEN || r0kh_id_len > FT_R0KH_ID_MAX_LEN)
                return -1;
-       wpa_printf(MSG_DEBUG, "FT: Derive PMK-R0 using KDF-%s",
-                  use_sha384 ? "SHA384" : "SHA256");
+       wpa_printf(MSG_DEBUG, "FT: Derive PMK-R0 using KDF-SHA%zu", q * 8);
        wpa_hexdump_key(MSG_DEBUG, "FT: XXKey", xxkey, xxkey_len);
        wpa_hexdump_ascii(MSG_DEBUG, "FT: SSID", ssid, ssid_len);
        wpa_hexdump(MSG_DEBUG, "FT: MDID", mdid, MOBILITY_DOMAIN_ID_LEN);
@@ -2100,30 +2110,43 @@ int wpa_derive_pmk_r0(const u8 *xxkey, size_t xxkey_len,
        os_memcpy(pos, s0kh_id, ETH_ALEN);
        pos += ETH_ALEN;
 
+       res = -1;
+#ifdef CONFIG_SHA512
+       if (q == SHA512_MAC_LEN) {
+               if (xxkey_len != SHA512_MAC_LEN) {
+                       wpa_printf(MSG_ERROR,
+                                  "FT: Unexpected XXKey length %d (expected %d)",
+                                  (int) xxkey_len, SHA512_MAC_LEN);
+                       return -1;
+               }
+               res = sha512_prf(xxkey, xxkey_len, "FT-R0", buf, pos - buf,
+                                r0_key_data, r0_key_data_len);
+       }
+#endif /* CONFIG_SHA512 */
 #ifdef CONFIG_SHA384
-       if (use_sha384) {
+       if (q == SHA384_MAC_LEN) {
                if (xxkey_len != SHA384_MAC_LEN) {
                        wpa_printf(MSG_ERROR,
                                   "FT: Unexpected XXKey length %d (expected %d)",
                                   (int) xxkey_len, SHA384_MAC_LEN);
                        return -1;
                }
-               if (sha384_prf(xxkey, xxkey_len, "FT-R0", buf, pos - buf,
-                              r0_key_data, r0_key_data_len) < 0)
-                       return -1;
+               res = sha384_prf(xxkey, xxkey_len, "FT-R0", buf, pos - buf,
+                                r0_key_data, r0_key_data_len);
        }
 #endif /* CONFIG_SHA384 */
-       if (!use_sha384) {
+       if (q == SHA256_MAC_LEN) {
                if (xxkey_len != PMK_LEN) {
                        wpa_printf(MSG_ERROR,
                                   "FT: Unexpected XXKey length %d (expected %d)",
                                   (int) xxkey_len, PMK_LEN);
                        return -1;
                }
-               if (sha256_prf(xxkey, xxkey_len, "FT-R0", buf, pos - buf,
-                              r0_key_data, r0_key_data_len) < 0)
-                       return -1;
+               res = sha256_prf(xxkey, xxkey_len, "FT-R0", buf, pos - buf,
+                                r0_key_data, r0_key_data_len);
        }
+       if (res < 0)
+               return res;
        os_memcpy(pmk_r0, r0_key_data, q);
        wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R0", pmk_r0, q);
        wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R0Name-Salt", &r0_key_data[q], 16);
@@ -2136,12 +2159,23 @@ int wpa_derive_pmk_r0(const u8 *xxkey, size_t xxkey_len,
        addr[1] = &r0_key_data[q];
        len[1] = 16;
 
+       res = -1;
+#ifdef CONFIG_SHA512
+       if (q == SHA512_MAC_LEN)
+               res = sha512_vector(2, addr, len, hash);
+#endif /* CONFIG_SHA512 */
 #ifdef CONFIG_SHA384
-       if (use_sha384 && sha384_vector(2, addr, len, hash) < 0)
-               return -1;
+       if (q == SHA384_MAC_LEN)
+               res = sha384_vector(2, addr, len, hash);
 #endif /* CONFIG_SHA384 */
-       if (!use_sha384 && sha256_vector(2, addr, len, hash) < 0)
-               return -1;
+       if (q == SHA256_MAC_LEN)
+               res = sha256_vector(2, addr, len, hash);
+       if (res < 0) {
+               wpa_printf(MSG_DEBUG,
+                          "FT: Failed to derive PMKR0Name (PMK-R0 len %zu)",
+                          q);
+               return res;
+       }
        os_memcpy(pmk_r0_name, hash, WPA_PMK_NAME_LEN);
        wpa_hexdump(MSG_DEBUG, "FT: PMKR0Name", pmk_r0_name, WPA_PMK_NAME_LEN);
        forced_memzero(r0_key_data, sizeof(r0_key_data));
index 561f926ae642fe59786befd3544620b94074705a..7374d8b7b3fd85cbfb8e066e76f44a9b9f380b98 100644 (file)
@@ -475,7 +475,7 @@ int wpa_derive_pmk_r0(const u8 *xxkey, size_t xxkey_len,
                      const u8 *ssid, size_t ssid_len,
                      const u8 *mdid, const u8 *r0kh_id, size_t r0kh_id_len,
                      const u8 *s0kh_id, u8 *pmk_r0, u8 *pmk_r0_name,
-                     int use_sha384);
+                     int key_mgmt);
 int wpa_derive_pmk_r1_name(const u8 *pmk_r0_name, const u8 *r1kh_id,
                           const u8 *s1kh_id, u8 *pmk_r1_name,
                           size_t pmk_r1_len);
index 10bef1a4a79d776ef73ce2419f518da53345c2de..5f305b897233a96d4946a083417bf39eb3c60373 100644 (file)
@@ -4610,11 +4610,14 @@ static int fils_ft_build_assoc_req_rsne(struct wpa_sm *sm, struct wpabuf *buf)
        if (wpa_derive_pmk_r0(sm->fils_ft, sm->fils_ft_len, sm->ssid,
                              sm->ssid_len, sm->mobility_domain,
                              sm->r0kh_id, sm->r0kh_id_len, sm->own_addr,
-                             sm->pmk_r0, sm->pmk_r0_name, use_sha384) < 0) {
+                             sm->pmk_r0, sm->pmk_r0_name, sm->key_mgmt) < 0) {
                wpa_printf(MSG_WARNING, "FILS+FT: Could not derive PMK-R0");
                return -1;
        }
-       sm->pmk_r0_len = use_sha384 ? SHA384_MAC_LEN : PMK_LEN;
+       if (wpa_key_mgmt_sae_ext_key(sm->key_mgmt))
+               sm->pmk_r0_len = sm->fils_ft_len;
+       else
+               sm->pmk_r0_len = use_sha384 ? SHA384_MAC_LEN : PMK_LEN;
        wpa_printf(MSG_DEBUG, "FILS+FT: R1KH-ID: " MACSTR,
                   MAC2STR(sm->r1kh_id));
        pos = wpabuf_put(buf, WPA_PMK_NAME_LEN);
index 372d6872bc9cbb1c5f1b000a4138448cf813feb5..beae5f10661479316ade88975a7fdde79925c4a6 100644 (file)
@@ -55,11 +55,14 @@ int wpa_derive_ptk_ft(struct wpa_sm *sm, const unsigned char *src_addr,
                return -1;
        }
 
-       sm->pmk_r0_len = use_sha384 ? SHA384_MAC_LEN : PMK_LEN;
+       if (wpa_key_mgmt_sae_ext_key(sm->key_mgmt))
+               sm->pmk_r0_len = mpmk_len;
+       else
+               sm->pmk_r0_len = use_sha384 ? SHA384_MAC_LEN : PMK_LEN;
        if (wpa_derive_pmk_r0(mpmk, mpmk_len, sm->ssid,
                              sm->ssid_len, sm->mobility_domain,
                              sm->r0kh_id, sm->r0kh_id_len, sm->own_addr,
-                             sm->pmk_r0, sm->pmk_r0_name, use_sha384) < 0)
+                             sm->pmk_r0, sm->pmk_r0_name, sm->key_mgmt) < 0)
                return -1;
        sm->pmk_r1_len = sm->pmk_r0_len;
        if (wpa_derive_pmk_r1(sm->pmk_r0, sm->pmk_r0_len, sm->pmk_r0_name,
index e96c487fee430e76dcb4f7eba38aef8d8c298576..6607aeec40d762c04176907b56911f5129dae88f 100644 (file)
@@ -192,9 +192,13 @@ static int try_pmk(struct wlantest *wt, struct wlantest_bss *bss,
                                      bss->ssid, bss->ssid_len, bss->mdid,
                                      bss->r0kh_id, bss->r0kh_id_len,
                                      sa, sta->pmk_r0, sta->pmk_r0_name,
-                                     use_sha384) < 0)
+                                     sta->key_mgmt) < 0)
                        return -1;
-               sta->pmk_r0_len = use_sha384 ? PMK_LEN_SUITE_B_192 : PMK_LEN;
+               if (wpa_key_mgmt_sae_ext_key(sta->key_mgmt))
+                       sta->pmk_r0_len = pmk->pmk_len;
+               else
+                       sta->pmk_r0_len = use_sha384 ? PMK_LEN_SUITE_B_192 :
+                               PMK_LEN;
                if (wpa_derive_pmk_r1(sta->pmk_r0, sta->pmk_r0_len,
                                      sta->pmk_r0_name,
                                      bss->r1kh_id, sa,