]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
FT: Simplify FTE parsing for FT-SAE-EXT-KEY using MIC Length subfield
authorJouni Malinen <j@w1.fi>
Sun, 20 Nov 2022 09:43:53 +0000 (11:43 +0200)
committerJouni Malinen <j@w1.fi>
Sun, 20 Nov 2022 09:43:53 +0000 (11:43 +0200)
Commit 25b52e5f83f1 ("FT: Extend FTE parsing for FT-SAE-EXT-KEY") used
possible MIC length iteration to try to figure out the length of the MIC
field in FTE. That was the only option available at the time, but FTE is
now being extended in IEEE 802.11-REVme to explicitly indicate the
length of the MIC field for the new FT-SAE-EXT-KEY AKM to make this
easier.

Use the new design from the approved comment resolution (*) in
REVme/D2.0 ballot CID 3135 to simplify implementation. This gets rid of
the need to pass in key length and the somewhat strange need_{r0kh,r1kh}
parameters to wpa_ft_parse_ies().

(*)
https://mentor.ieee.org/802.11/dcn/22/11-22-1991-02-000m-proposed-resolutions-to-some-lb270-comments.docx

Signed-off-by: Jouni Malinen <j@w1.fi>
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_mgmt.c

index e5d3b6affeffc3cc2e67d57bf856d2f6c1e8a92f..91e4a2560172ac9a94fa8f52a43d9cf5fef44f7e 100644 (file)
@@ -814,6 +814,7 @@ int wpa_write_ftie(struct wpa_auth_config *conf, int key_mgmt, size_t key_len,
 {
        u8 *pos = buf, *ielen;
        size_t hdrlen;
+       u16 mic_control = rsnxe_used ? FTE_MIC_CTRL_RSNXE_USED : 0;
 
        if (key_mgmt == WPA_KEY_MGMT_FT_SAE_EXT_KEY &&
            key_len == SHA256_MAC_LEN)
@@ -842,7 +843,8 @@ int wpa_write_ftie(struct wpa_auth_config *conf, int key_mgmt, size_t key_len,
 
                os_memset(hdr, 0, sizeof(*hdr));
                pos += sizeof(*hdr);
-               WPA_PUT_LE16(hdr->mic_control, !!rsnxe_used);
+               mic_control |= FTE_MIC_LEN_32 << FTE_MIC_CTRL_MIC_LEN_SHIFT;
+               WPA_PUT_LE16(hdr->mic_control, mic_control);
                if (anonce)
                        os_memcpy(hdr->anonce, anonce, WPA_NONCE_LEN);
                if (snonce)
@@ -854,7 +856,8 @@ int wpa_write_ftie(struct wpa_auth_config *conf, int key_mgmt, size_t key_len,
 
                os_memset(hdr, 0, sizeof(*hdr));
                pos += sizeof(*hdr);
-               WPA_PUT_LE16(hdr->mic_control, !!rsnxe_used);
+               mic_control |= FTE_MIC_LEN_24 << FTE_MIC_CTRL_MIC_LEN_SHIFT;
+               WPA_PUT_LE16(hdr->mic_control, mic_control);
                if (anonce)
                        os_memcpy(hdr->anonce, anonce, WPA_NONCE_LEN);
                if (snonce)
@@ -864,7 +867,8 @@ int wpa_write_ftie(struct wpa_auth_config *conf, int key_mgmt, size_t key_len,
 
                os_memset(hdr, 0, sizeof(*hdr));
                pos += sizeof(*hdr);
-               WPA_PUT_LE16(hdr->mic_control, !!rsnxe_used);
+               mic_control |= FTE_MIC_LEN_16 << FTE_MIC_CTRL_MIC_LEN_SHIFT;
+               WPA_PUT_LE16(hdr->mic_control, mic_control);
                if (anonce)
                        os_memcpy(hdr->anonce, anonce, WPA_NONCE_LEN);
                if (snonce)
@@ -2788,8 +2792,8 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
                *elem_count = 3; /* Information element count */
 
        ric_start = pos;
-       if (wpa_ft_parse_ies(req_ies, req_ies_len, &parse, sm->wpa_key_mgmt,
-                            key_len, false, false) == 0 && parse.ric) {
+       if (wpa_ft_parse_ies(req_ies, req_ies_len, &parse,
+                            sm->wpa_key_mgmt) == 0 && parse.ric) {
                pos = wpa_ft_process_ric(sm, pos, end, parse.ric,
                                         parse.ric_len);
                if (auth_alg == WLAN_AUTH_FT)
@@ -3165,7 +3169,7 @@ static int wpa_ft_process_auth_req(struct wpa_state_machine *sm,
        wpa_hexdump(MSG_DEBUG, "FT: Received authentication frame IEs",
                    ies, ies_len);
 
-       if (wpa_ft_parse_ies(ies, ies_len, &parse, 0, 0, false, false)) {
+       if (wpa_ft_parse_ies(ies, ies_len, &parse, 0)) {
                wpa_printf(MSG_DEBUG, "FT: Failed to parse FT IEs");
                return WLAN_STATUS_UNSPECIFIED_FAILURE;
        }
@@ -3463,8 +3467,7 @@ int wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies,
 
        wpa_hexdump(MSG_DEBUG, "FT: Reassoc Req IEs", ies, ies_len);
 
-       if (wpa_ft_parse_ies(ies, ies_len, &parse, sm->wpa_key_mgmt,
-                            sm->pmk_r1_len, true, true) < 0) {
+       if (wpa_ft_parse_ies(ies, ies_len, &parse, sm->wpa_key_mgmt) < 0) {
                wpa_printf(MSG_DEBUG, "FT: Failed to parse FT IEs");
                return WLAN_STATUS_UNSPECIFIED_FAILURE;
        }
index 9f3ebd50aefc14a609aad3717f0d1a16e7051ebf..32e37468dc7e7cea54bd7ee607c60a77911cbe58 100644 (file)
@@ -1090,19 +1090,46 @@ static int wpa_ft_parse_ftie(const u8 *ie, size_t ie_len,
 }
 
 
-static int wpa_ft_parse_fte(const u8 *ie, size_t len, size_t mic_len,
+static int wpa_ft_parse_fte(int key_mgmt, const u8 *ie, size_t len,
                            struct wpa_ft_ies *parse)
 {
+       size_t mic_len;
+       u8 mic_len_info;
        const u8 *pos = ie;
        const u8 *end = pos + len;
 
        wpa_hexdump(MSG_DEBUG, "FT: FTE-MIC Control", pos, 2);
-       parse->fte_rsnxe_used = pos[0] & 0x01;
+       parse->fte_rsnxe_used = pos[0] & FTE_MIC_CTRL_RSNXE_USED;
+       mic_len_info = (pos[0] & FTE_MIC_CTRL_MIC_LEN_MASK) >>
+               FTE_MIC_CTRL_MIC_LEN_SHIFT;
        parse->fte_elem_count = pos[1];
        pos += 2;
 
-       if (mic_len > (size_t) (end - pos))
+       if (key_mgmt == WPA_KEY_MGMT_FT_SAE_EXT_KEY) {
+               switch (mic_len_info) {
+               case FTE_MIC_LEN_16:
+                       mic_len = 16;
+                       break;
+               case FTE_MIC_LEN_24:
+                       mic_len = 24;
+                       break;
+               case FTE_MIC_LEN_32:
+                       mic_len = 32;
+                       break;
+               default:
+                       wpa_printf(MSG_DEBUG,
+                                  "FT: Unknown MIC Length subfield value %u",
+                                  mic_len_info);
+                       return -1;
+               }
+       } else {
+               mic_len = wpa_key_mgmt_sha384(key_mgmt) ? 24 : 16;
+       }
+       if (mic_len > (size_t) (end - pos)) {
+               wpa_printf(MSG_DEBUG, "FT: No room for %zu octet MIC in FTE",
+                          mic_len);
                return -1;
+       }
        wpa_hexdump(MSG_DEBUG, "FT: FTE-MIC", pos, mic_len);
        parse->fte_mic = pos;
        parse->fte_mic_len = mic_len;
@@ -1124,8 +1151,7 @@ static int wpa_ft_parse_fte(const u8 *ie, size_t len, size_t mic_len,
 
 
 int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, struct wpa_ft_ies *parse,
-                    int key_mgmt, size_t key_len, bool need_r0kh_id,
-                    bool need_r1kh_id)
+                    int key_mgmt)
 {
        const u8 *end, *pos;
        struct wpa_ie_data data;
@@ -1195,49 +1221,7 @@ int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, struct wpa_ft_ies *parse,
                        prot_ie_count = pos[1]; /* Element Count field in
                                                 * MIC Control */
 
-                       if (key_mgmt == WPA_KEY_MGMT_FT_SAE_EXT_KEY &&
-                           (key_len == SHA512_MAC_LEN || !key_len)) {
-                               wpa_printf(MSG_DEBUG,
-                                          "FT: Trying to parse FTE for FT-SAE-EXT-KEY - SHA512");
-                               if (wpa_ft_parse_fte(pos, len, 32, parse) ==
-                                   0 &&
-                                   (!need_r0kh_id || parse->r0kh_id) &&
-                                   (!need_r1kh_id || parse->r1kh_id))
-                                       break;
-                       }
-                       if (key_mgmt == WPA_KEY_MGMT_FT_SAE_EXT_KEY &&
-                           (key_len == SHA384_MAC_LEN || !key_len)) {
-                               wpa_printf(MSG_DEBUG,
-                                          "FT: Trying to parse FTE for FT-SAE-EXT-KEY - SHA384");
-                               if (wpa_ft_parse_fte(pos, len, 24, parse) ==
-                                   0 &&
-                                   (!need_r0kh_id || parse->r0kh_id) &&
-                                   (!need_r1kh_id || parse->r1kh_id))
-                                       break;
-                       }
-                       if (key_mgmt == WPA_KEY_MGMT_FT_SAE_EXT_KEY &&
-                           (key_len == SHA256_MAC_LEN || !key_len)) {
-                               wpa_printf(MSG_DEBUG,
-                                          "FT: Trying to parse FTE for FT-SAE-EXT-KEY - SHA256");
-                               if (wpa_ft_parse_fte(pos, len, 16, parse) ==
-                                   0 &&
-                                   (!need_r0kh_id || parse->r0kh_id) &&
-                                   (!need_r1kh_id || parse->r1kh_id))
-                                       break;
-                       }
-                       if (key_mgmt == WPA_KEY_MGMT_FT_SAE_EXT_KEY) {
-                               wpa_printf(MSG_DEBUG,
-                                          "FT: Failed to parse FTE for FT-SAE-EXT-KEY");
-                               return -1;
-                       }
-
-                       if (wpa_key_mgmt_sha384(key_mgmt)) {
-                               if (wpa_ft_parse_fte(pos, len, 24, parse) < 0)
-                                       return -1;
-                               break;
-                       }
-
-                       if (wpa_ft_parse_fte(pos, len, 16, parse) < 0)
+                       if (wpa_ft_parse_fte(key_mgmt, pos, len, parse) < 0)
                                return -1;
                        break;
                case WLAN_EID_TIMEOUT_INTERVAL:
index acb975ce5ab42386379a07e259bb3a98d91e1741..05b1a8a05ad8ed6e066692bc5f85a2e49d99b632 100644 (file)
@@ -186,6 +186,18 @@ WPA_CIPHER_BIP_CMAC_256)
 #define FT_R1KH_ID_LEN 6
 #define WPA_PMK_NAME_LEN 16
 
+/* FTE - MIC Control - RSNXE Used */
+#define FTE_MIC_CTRL_RSNXE_USED BIT(0)
+#define FTE_MIC_CTRL_MIC_LEN_MASK (BIT(1) | BIT(2) | BIT(3))
+#define FTE_MIC_CTRL_MIC_LEN_SHIFT 1
+
+/* FTE - MIC Length subfield values */
+enum ft_mic_len_subfield {
+       FTE_MIC_LEN_16 = 0,
+       FTE_MIC_LEN_24 = 1,
+       FTE_MIC_LEN_32 = 2,
+};
+
 
 /* IEEE 802.11, 8.5.2 EAPOL-Key frames */
 #define WPA_KEY_INFO_TYPE_MASK ((u16) (BIT(0) | BIT(1) | BIT(2)))
@@ -612,8 +624,7 @@ struct wpa_pasn_params_data {
 #define WPA_PASN_PUBKEY_UNCOMPRESSED 0x04
 
 int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, struct wpa_ft_ies *parse,
-                    int key_mgmt, size_t key_len, bool need_r0kh_id,
-                    bool need_r1kh_id);
+                    int key_mgmt);
 
 struct wpa_eapol_ie_parse {
        const u8 *wpa_ie;
index 889bb0fc5f22ea2384523eaa8dbc7487ede60850..689db834b5b627dd835474c1563d3a9081a0b4b9 100644 (file)
@@ -5196,8 +5196,7 @@ int fils_process_auth(struct wpa_sm *sm, const u8 *bssid, const u8 *data,
                }
 
                if (wpa_ft_parse_ies(pos, end - pos, &parse,
-                                    sm->key_mgmt, sm->xxkey_len, true,
-                                    true) < 0) {
+                                    sm->key_mgmt) < 0) {
                        wpa_printf(MSG_DEBUG, "FILS+FT: Failed to parse IEs");
                        goto fail;
                }
index fdf921d5d1188b8a4ed8ab138de5a1d332dec790..eca09f7f4f63b24d71a922c5adaf06da24ae016a 100644 (file)
@@ -127,8 +127,7 @@ int wpa_sm_set_ft_params(struct wpa_sm *sm, const u8 *ies, size_t ies_len)
                return 0;
        }
 
-       if (wpa_ft_parse_ies(ies, ies_len, &ft, sm->key_mgmt,
-                            sm->xxkey_len, false, false) < 0)
+       if (wpa_ft_parse_ies(ies, ies_len, &ft, sm->key_mgmt) < 0)
                return -1;
 
        if (ft.mdie_len < MOBILITY_DOMAIN_ID_LEN + 1)
@@ -217,6 +216,7 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len,
        size_t rsnxe_len;
        int rsnxe_used;
        int res;
+       u8 mic_control;
 
        sm->ft_completed = 0;
        sm->ft_reassoc_completed = 0;
@@ -348,12 +348,14 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len,
                           rsnxe_used);
        }
 #endif /* CONFIG_TESTING_OPTIONS */
+       mic_control = rsnxe_used ? FTE_MIC_CTRL_RSNXE_USED : 0;
        if (sm->key_mgmt == WPA_KEY_MGMT_FT_SAE_EXT_KEY &&
            sm->pmk_r0_len == SHA512_MAC_LEN) {
                struct rsn_ftie_sha512 *ftie;
 
                ftie = (struct rsn_ftie_sha512 *) pos;
-               ftie->mic_control[0] = !!rsnxe_used;
+               mic_control |= FTE_MIC_LEN_32 << FTE_MIC_CTRL_MIC_LEN_SHIFT;
+               ftie->mic_control[0] = mic_control;
                fte_mic = ftie->mic;
                elem_count = &ftie->mic_control[1];
                pos += sizeof(*ftie);
@@ -366,7 +368,8 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len,
                struct rsn_ftie_sha384 *ftie;
 
                ftie = (struct rsn_ftie_sha384 *) pos;
-               ftie->mic_control[0] = !!rsnxe_used;
+               mic_control |= FTE_MIC_LEN_24 << FTE_MIC_CTRL_MIC_LEN_SHIFT;
+               ftie->mic_control[0] = mic_control;
                fte_mic = ftie->mic;
                elem_count = &ftie->mic_control[1];
                pos += sizeof(*ftie);
@@ -377,7 +380,8 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len,
                struct rsn_ftie *ftie;
 
                ftie = (struct rsn_ftie *) pos;
-               ftie->mic_control[0] = !!rsnxe_used;
+               mic_control |= FTE_MIC_LEN_16 << FTE_MIC_CTRL_MIC_LEN_SHIFT;
+               ftie->mic_control[0] = mic_control;
                fte_mic = ftie->mic;
                elem_count = &ftie->mic_control[1];
                pos += sizeof(*ftie);
@@ -584,7 +588,7 @@ int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len,
        int ret;
        const u8 *bssid;
        const u8 *kck;
-       size_t kck_len, kdk_len, key_len;
+       size_t kck_len, kdk_len;
 
        wpa_hexdump(MSG_DEBUG, "FT: Response IEs", ies, ies_len);
        wpa_hexdump(MSG_DEBUG, "FT: RIC IEs", ric_ies, ric_ies_len);
@@ -610,11 +614,7 @@ int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len,
                return -1;
        }
 
-       key_len = sm->xxkey_len;
-       if (!key_len)
-               key_len = sm->pmk_r1_len;
-       if (wpa_ft_parse_ies(ies, ies_len, &parse, sm->key_mgmt,
-                            key_len, true, false) < 0) {
+       if (wpa_ft_parse_ies(ies, ies_len, &parse, sm->key_mgmt) < 0) {
                wpa_printf(MSG_DEBUG, "FT: Failed to parse IEs");
                return -1;
        }
@@ -1032,8 +1032,7 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies,
                return 0;
        }
 
-       if (wpa_ft_parse_ies(ies, ies_len, &parse, sm->key_mgmt,
-                            sm->xxkey_len, true, true) < 0) {
+       if (wpa_ft_parse_ies(ies, ies_len, &parse, sm->key_mgmt) < 0) {
                wpa_printf(MSG_DEBUG, "FT: Failed to parse IEs");
                return -1;
        }
index 2a32510f1edeed6efc6e1fe99d7915080263a84b..49813ce783e7a9e3750765d25844ae41bb56822f 100644 (file)
@@ -250,7 +250,7 @@ static void process_ft_auth(struct wlantest *wt, struct wlantest_bss *bss,
 
        if (wpa_ft_parse_ies(mgmt->u.auth.variable,
                             len - IEEE80211_HDRLEN - sizeof(mgmt->u.auth),
-                            &parse, 0, 0, false, false)) {
+                            &parse, 0)) {
                add_note(wt, MSG_INFO,
                         "Could not parse FT Authentication Response frame");
                return;
@@ -829,7 +829,7 @@ static void rx_mgmt_assoc_resp(struct wlantest *wt, const u8 *data, size_t len)
                sta->state = STATE3;
        }
 
-       if (wpa_ft_parse_ies(ies, ies_len, &parse, 0, 0, false, false) == 0) {
+       if (wpa_ft_parse_ies(ies, ies_len, &parse, 0) == 0) {
                if (parse.r0kh_id) {
                        os_memcpy(bss->r0kh_id, parse.r0kh_id,
                                  parse.r0kh_id_len);
@@ -925,8 +925,7 @@ static void rx_mgmt_reassoc_req(struct wlantest *wt, const u8 *data,
 
                use_sha384 = wpa_key_mgmt_sha384(sta->key_mgmt);
 
-               if (wpa_ft_parse_ies(ie, ie_len, &parse, sta->key_mgmt,
-                                    0, false, false) < 0) {
+               if (wpa_ft_parse_ies(ie, ie_len, &parse, sta->key_mgmt) < 0) {
                        add_note(wt, MSG_INFO, "FT: Failed to parse FT IEs");
                        return;
                }
@@ -1419,8 +1418,7 @@ static void rx_mgmt_reassoc_resp(struct wlantest *wt, const u8 *data,
 
                use_sha384 = wpa_key_mgmt_sha384(sta->key_mgmt);
 
-               if (wpa_ft_parse_ies(ies, ies_len, &parse, sta->key_mgmt,
-                                    0, false, false) < 0) {
+               if (wpa_ft_parse_ies(ies, ies_len, &parse, sta->key_mgmt) < 0) {
                        add_note(wt, MSG_INFO, "FT: Failed to parse FT IEs");
                        return;
                }
@@ -1730,7 +1728,7 @@ static void rx_mgmt_action_ft_request(struct wlantest *wt,
        ies_len = len - (24 + 2 + 2 * ETH_ALEN);
        wpa_hexdump(MSG_DEBUG, "FT Request frame body", ies, ies_len);
 
-       if (wpa_ft_parse_ies(ies, ies_len, &parse, 0, 0, false, false)) {
+       if (wpa_ft_parse_ies(ies, ies_len, &parse, 0)) {
                add_note(wt, MSG_INFO, "Could not parse FT Request frame body");
                return;
        }
@@ -1779,7 +1777,7 @@ static void rx_mgmt_action_ft_response(struct wlantest *wt,
        ies_len = len - (24 + 2 + 2 * ETH_ALEN);
        wpa_hexdump(MSG_DEBUG, "FT Response frame body", ies, ies_len);
 
-       if (wpa_ft_parse_ies(ies, ies_len, &parse, 0, 0, false, false)) {
+       if (wpa_ft_parse_ies(ies, ies_len, &parse, 0)) {
                add_note(wt, MSG_INFO,
                         "Could not parse FT Response frame body");
                return;