]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
FT: PMK-R0 derivation using SHA384-based AKM
authorJouni Malinen <j@w1.fi>
Mon, 4 Jun 2018 12:16:54 +0000 (15:16 +0300)
committerJouni Malinen <j@w1.fi>
Tue, 5 Jun 2018 16:29:53 +0000 (19:29 +0300)
Signed-off-by: Jouni Malinen <j@w1.fi>
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 ff00b2813c2c0ed26197e83623a7ec9921a70dd6..c7e8ec7a38a6c569d413885078edea994b909c16 100644 (file)
@@ -2126,17 +2126,21 @@ int fils_auth_pmk_to_ptk(struct wpa_state_machine *sm, const u8 *pmk,
        if (fils_ft_len) {
                struct wpa_authenticator *wpa_auth = sm->wpa_auth;
                struct wpa_auth_config *conf = &wpa_auth->conf;
-               u8 pmk_r0[PMK_LEN], pmk_r0_name[WPA_PMK_NAME_LEN];
+               u8 pmk_r0[PMK_LEN_MAX], pmk_r0_name[WPA_PMK_NAME_LEN];
+               int use_sha384 = wpa_key_mgmt_sha384(sm->wpa_key_mgmt);
+               size_t pmk_r0_len = use_sha384 ? SHA384_MAC_LEN : PMK_LEN;
 
                if (wpa_derive_pmk_r0(fils_ft, fils_ft_len,
                                      conf->ssid, conf->ssid_len,
                                      conf->mobility_domain,
                                      conf->r0_key_holder,
                                      conf->r0_key_holder_len,
-                                     sm->addr, pmk_r0, pmk_r0_name) < 0)
+                                     sm->addr, pmk_r0, pmk_r0_name,
+                                     use_sha384) < 0)
                        return -1;
 
-               wpa_hexdump_key(MSG_DEBUG, "FILS+FT: PMK-R0", pmk_r0, PMK_LEN);
+               wpa_hexdump_key(MSG_DEBUG, "FILS+FT: PMK-R0",
+                               pmk_r0, pmk_r0_len);
                wpa_hexdump(MSG_DEBUG, "FILS+FT: PMKR0Name",
                            pmk_r0_name, WPA_PMK_NAME_LEN);
                wpa_ft_store_pmk_fils(sm, pmk_r0, pmk_r0_name);
index 52e5779d94f7dcda524a24a55425680894b10732..d6735a124e12ba2cff33b11f16c1fb4d40778167 100644 (file)
@@ -1980,7 +1980,8 @@ int wpa_ft_store_pmk_fils(struct wpa_state_machine *sm,
        const u8 *identity, *radius_cui;
        size_t identity_len, radius_cui_len;
        int session_timeout;
-       size_t pmk_r0_len = PMK_LEN;
+       size_t pmk_r0_len = wpa_key_mgmt_sha384(sm->wpa_key_mgmt) ?
+               SHA384_MAC_LEN : PMK_LEN;
 
        if (wpa_ft_get_vlan(sm->wpa_auth, sm->addr, &vlan) < 0) {
                wpa_printf(MSG_DEBUG, "FT: vlan not available for STA " MACSTR,
@@ -2004,7 +2005,8 @@ int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, const u8 *pmk,
                           struct wpa_ptk *ptk)
 {
        u8 pmk_r0[PMK_LEN_MAX], pmk_r0_name[WPA_PMK_NAME_LEN];
-       size_t pmk_r0_len = PMK_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;
        u8 pmk_r1[PMK_LEN_MAX];
        u8 ptk_name[WPA_PMK_NAME_LEN];
@@ -2040,7 +2042,8 @@ int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, const u8 *pmk,
 
        if (wpa_derive_pmk_r0(sm->xxkey, sm->xxkey_len, ssid, ssid_len, mdid,
                              r0kh, r0kh_len, sm->addr,
-                             pmk_r0, pmk_r0_name) < 0)
+                             pmk_r0, pmk_r0_name,
+                             wpa_key_mgmt_sha384(sm->wpa_key_mgmt)) < 0)
                return -1;
        wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R0", pmk_r0, pmk_r0_len);
        wpa_hexdump(MSG_DEBUG, "FT: PMKR0Name", pmk_r0_name, WPA_PMK_NAME_LEN);
@@ -2512,7 +2515,7 @@ 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 ||
+                                     pmk_r0, pmk_r0_name, 0) < 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 9a79e0ce12c4423362989292685a1c83884ec131..02f539511c91097feb02f3fdd6234557a6b42660 100644 (file)
@@ -1420,24 +1420,36 @@ int wpa_parse_wpa_ie_wpa(const u8 *wpa_ie, size_t wpa_ie_len,
 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)
+                     const u8 *s0kh_id, u8 *pmk_r0, u8 *pmk_r0_name,
+                     int use_sha384)
 {
        u8 buf[1 + SSID_MAX_LEN + MOBILITY_DOMAIN_ID_LEN + 1 +
               FT_R0KH_ID_MAX_LEN + ETH_ALEN];
-       u8 *pos, r0_key_data[48], hash[32];
+       u8 *pos, r0_key_data[64], hash[32];
        const u8 *addr[2];
        size_t len[2];
+       size_t q = use_sha384 ? 48 : 32;
+       size_t r0_key_data_len = q + 16;
 
        /*
         * R0-Key-Data = KDF-384(XXKey, "FT-R0",
         *                       SSIDlength || SSID || MDID || R0KHlength ||
         *                       R0KH-ID || S0KH-ID)
-        * XXKey is either the second 256 bits of MSK or PSK.
-        * PMK-R0 = L(R0-Key-Data, 0, 256)
-        * PMK-R0Name-Salt = L(R0-Key-Data, 256, 128)
+        * XXKey is either the second 256 bits of MSK or PSK; or the first
+        * 384 bits of MSK for FT-EAP-SHA384.
+        * 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
         */
        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_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);
+       wpa_hexdump_ascii(MSG_DEBUG, "FT: R0KH-ID", r0kh_id, r0kh_id_len);
+       wpa_printf(MSG_DEBUG, "FT: S0KH-ID: " MACSTR, MAC2STR(s0kh_id));
        pos = buf;
        *pos++ = ssid_len;
        os_memcpy(pos, ssid, ssid_len);
@@ -1450,22 +1462,46 @@ int wpa_derive_pmk_r0(const u8 *xxkey, size_t xxkey_len,
        os_memcpy(pos, s0kh_id, ETH_ALEN);
        pos += ETH_ALEN;
 
-       if (sha256_prf(xxkey, xxkey_len, "FT-R0", buf, pos - buf,
-                      r0_key_data, sizeof(r0_key_data)) < 0)
-               return -1;
-       os_memcpy(pmk_r0, r0_key_data, PMK_LEN);
+#ifdef CONFIG_SHA384
+       if (use_sha384) {
+               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;
+       }
+#endif /* CONFIG_SHA384 */
+       if (!use_sha384) {
+               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;
+       }
+       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);
 
        /*
         * PMKR0Name = Truncate-128(SHA-256("FT-R0N" || PMK-R0Name-Salt)
         */
        addr[0] = (const u8 *) "FT-R0N";
        len[0] = 6;
-       addr[1] = r0_key_data + PMK_LEN;
+       addr[1] = &r0_key_data[q];
        len[1] = 16;
 
        if (sha256_vector(2, addr, len, hash) < 0)
                return -1;
        os_memcpy(pmk_r0_name, hash, WPA_PMK_NAME_LEN);
+       os_memset(r0_key_data, 0, sizeof(r0_key_data));
        return 0;
 }
 
index 3843167f00bdf7aa45247d75c2ecec5ff7fc18ac..bb0765acfb9cf573b83f184e9f0d22c1742bb2c3 100644 (file)
@@ -364,7 +364,8 @@ int wpa_ft_mic(const u8 *kck, size_t kck_len, const u8 *sta_addr,
 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);
+                     const u8 *s0kh_id, u8 *pmk_r0, u8 *pmk_r0_name,
+                     int use_sha384);
 int wpa_derive_pmk_r1_name(const u8 *pmk_r0_name, const u8 *r1kh_id,
                           const u8 *s1kh_id, u8 *pmk_r1_name);
 int wpa_derive_pmk_r1(const u8 *pmk_r0, size_t pmk_r0_len,
index 226cafaf6d9a065ac17200cc8adc2ff8393d713f..4dd209b38fa8d1577721dbd613b08b15301ae809 100644 (file)
@@ -3747,6 +3747,7 @@ static int fils_ft_build_assoc_req_rsne(struct wpa_sm *sm, struct wpabuf *buf)
        struct rsn_ie_hdr *rsnie;
        u16 capab;
        u8 *pos;
+       int use_sha384 = wpa_key_mgmt_sha384(sm->key_mgmt);
 
        /* RSNIE[PMKR0Name/PMKR1Name] */
        rsnie = wpabuf_put(buf, sizeof(*rsnie));
@@ -3814,11 +3815,13 @@ 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) < 0) {
+                             sm->pmk_r0, sm->pmk_r0_name, use_sha384) < 0) {
                wpa_printf(MSG_WARNING, "FILS+FT: Could not derive PMK-R0");
                return -1;
        }
-       wpa_hexdump_key(MSG_DEBUG, "FILS+FT: PMK-R0", sm->pmk_r0, PMK_LEN);
+       sm->pmk_r0_len = use_sha384 ? SHA384_MAC_LEN : PMK_LEN;
+       wpa_hexdump_key(MSG_DEBUG, "FILS+FT: PMK-R0",
+                       sm->pmk_r0, sm->pmk_r0_len);
        wpa_hexdump(MSG_DEBUG, "FILS+FT: PMKR0Name",
                    sm->pmk_r0_name, WPA_PMK_NAME_LEN);
        wpa_printf(MSG_DEBUG, "FILS+FT: R1KH-ID: " MACSTR,
index da1ce39f0d19581f389532ef59608f792f15ddbe..696571222df437a6462be9b987a77c60a4f92be9 100644 (file)
@@ -10,6 +10,7 @@
 
 #include "common.h"
 #include "crypto/aes_wrap.h"
+#include "crypto/sha384.h"
 #include "crypto/random.h"
 #include "common/ieee802_11_defs.h"
 #include "common/ieee802_11_common.h"
@@ -23,6 +24,7 @@ int wpa_derive_ptk_ft(struct wpa_sm *sm, const unsigned char *src_addr,
 {
        u8 ptk_name[WPA_PMK_NAME_LEN];
        const u8 *anonce = key->key_nonce;
+       int use_sha384 = wpa_key_mgmt_sha384(sm->key_mgmt);
 
        if (sm->xxkey_len == 0) {
                wpa_printf(MSG_DEBUG, "FT: XXKey not available for key "
@@ -30,11 +32,11 @@ int wpa_derive_ptk_ft(struct wpa_sm *sm, const unsigned char *src_addr,
                return -1;
        }
 
-       sm->pmk_r0_len = PMK_LEN;
+       sm->pmk_r0_len = use_sha384 ? SHA384_MAC_LEN : PMK_LEN;
        if (wpa_derive_pmk_r0(sm->xxkey, sm->xxkey_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) < 0)
+                             sm->pmk_r0, sm->pmk_r0_name, use_sha384) < 0)
                return -1;
        wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R0", sm->pmk_r0, sm->pmk_r0_len);
        wpa_hexdump(MSG_DEBUG, "FT: PMKR0Name",
index 069e63476bed5e43b444158e944f99245599b094..9c52fbac41dc5dfc15c79035ca61c6eaa8abe2cd 100644 (file)
@@ -109,7 +109,7 @@ static int try_pmk(struct wlantest *wt, struct wlantest_bss *bss,
                wpa_derive_pmk_r0(pmk->pmk, PMK_LEN,
                                  bss->ssid, bss->ssid_len, bss->mdid,
                                  bss->r0kh_id, bss->r0kh_id_len,
-                                 sta->addr, pmk_r0, pmk_r0_name);
+                                 sta->addr, pmk_r0, pmk_r0_name, 0);
                wpa_hexdump(MSG_DEBUG, "FT: PMK-R0", pmk_r0, PMK_LEN);
                wpa_hexdump(MSG_DEBUG, "FT: PMKR0Name", pmk_r0_name,
                            WPA_PMK_NAME_LEN);