diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index 9f6d24420..2c65a1d85 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -1446,8 +1446,11 @@ prepare_auth_resp_fils(struct hostapd_data *hapd, if (wpa_key_mgmt_ft(wpa_auth_sta_key_mgmt(sta->wpa_sm))) { /* FTE[R1KH-ID,R0KH-ID] when using FILS+FT */ int res; + int use_sha384 = wpa_key_mgmt_sha384( + wpa_auth_sta_key_mgmt(sta->wpa_sm)); - res = wpa_auth_write_fte(hapd->wpa_auth, wpabuf_put(data, 0), + res = wpa_auth_write_fte(hapd->wpa_auth, use_sha384, + wpabuf_put(data, 0), wpabuf_tailroom(data)); if (res < 0) { *resp = WLAN_STATUS_UNSPECIFIED_FAILURE; diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index c7e8ec7a3..126d98c9f 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -3014,7 +3014,10 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) 2 + sm->assoc_resp_ftie[1]); res = 2 + sm->assoc_resp_ftie[1]; } else { - res = wpa_write_ftie(conf, conf->r0_key_holder, + int use_sha384 = wpa_key_mgmt_sha384(sm->wpa_key_mgmt); + + res = wpa_write_ftie(conf, use_sha384, + conf->r0_key_holder, conf->r0_key_holder_len, NULL, NULL, pos, kde + kde_len - pos, @@ -4540,11 +4543,12 @@ wpa_auth_pmksa_get_fils_cache_id(struct wpa_authenticator *wpa_auth, #ifdef CONFIG_IEEE80211R_AP -int wpa_auth_write_fte(struct wpa_authenticator *wpa_auth, u8 *buf, size_t len) +int wpa_auth_write_fte(struct wpa_authenticator *wpa_auth, int use_sha384, + u8 *buf, size_t len) { struct wpa_auth_config *conf = &wpa_auth->conf; - return wpa_write_ftie(conf, conf->r0_key_holder, + return wpa_write_ftie(conf, use_sha384, conf->r0_key_holder, conf->r0_key_holder_len, NULL, NULL, buf, len, NULL, 0); } @@ -4714,7 +4718,10 @@ int wpa_auth_resend_m3(struct wpa_state_machine *sm, 2 + sm->assoc_resp_ftie[1]); res = 2 + sm->assoc_resp_ftie[1]; } else { - res = wpa_write_ftie(conf, conf->r0_key_holder, + int use_sha384 = wpa_key_mgmt_sha384(sm->wpa_key_mgmt); + + res = wpa_write_ftie(conf, use_sha384, + conf->r0_key_holder, conf->r0_key_holder_len, NULL, NULL, pos, kde + kde_len - pos, diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h index 128b6570b..fad5536f7 100644 --- a/src/ap/wpa_auth.h +++ b/src/ap/wpa_auth.h @@ -449,7 +449,8 @@ const u8 * wpa_fils_validate_fils_session(struct wpa_state_machine *sm, int wpa_fils_validate_key_confirm(struct wpa_state_machine *sm, const u8 *ies, size_t ies_len); -int wpa_auth_write_fte(struct wpa_authenticator *wpa_auth, u8 *buf, size_t len); +int wpa_auth_write_fte(struct wpa_authenticator *wpa_auth, int use_sha384, + u8 *buf, size_t len); void wpa_auth_get_fils_aead_params(struct wpa_state_machine *sm, u8 *fils_anonce, u8 *fils_snonce, u8 *fils_kek, size_t *fils_kek_len); diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c index 93ed12662..586d0a6b8 100644 --- a/src/ap/wpa_auth_ft.c +++ b/src/ap/wpa_auth_ft.c @@ -746,30 +746,44 @@ int wpa_write_mdie(struct wpa_auth_config *conf, u8 *buf, size_t len) } -int wpa_write_ftie(struct wpa_auth_config *conf, const u8 *r0kh_id, - size_t r0kh_id_len, +int wpa_write_ftie(struct wpa_auth_config *conf, int use_sha384, + const u8 *r0kh_id, size_t r0kh_id_len, const u8 *anonce, const u8 *snonce, u8 *buf, size_t len, const u8 *subelem, size_t subelem_len) { u8 *pos = buf, *ielen; - struct rsn_ftie *hdr; + size_t hdrlen = use_sha384 ? sizeof(struct rsn_ftie_sha384) : + sizeof(struct rsn_ftie); - if (len < 2 + sizeof(*hdr) + 2 + FT_R1KH_ID_LEN + 2 + r0kh_id_len + + if (len < 2 + hdrlen + 2 + FT_R1KH_ID_LEN + 2 + r0kh_id_len + subelem_len) return -1; *pos++ = WLAN_EID_FAST_BSS_TRANSITION; ielen = pos++; - hdr = (struct rsn_ftie *) pos; - os_memset(hdr, 0, sizeof(*hdr)); - pos += sizeof(*hdr); - WPA_PUT_LE16(hdr->mic_control, 0); - if (anonce) - os_memcpy(hdr->anonce, anonce, WPA_NONCE_LEN); - if (snonce) - os_memcpy(hdr->snonce, snonce, WPA_NONCE_LEN); + if (use_sha384) { + struct rsn_ftie_sha384 *hdr = (struct rsn_ftie_sha384 *) pos; + + os_memset(hdr, 0, sizeof(*hdr)); + pos += sizeof(*hdr); + WPA_PUT_LE16(hdr->mic_control, 0); + if (anonce) + os_memcpy(hdr->anonce, anonce, WPA_NONCE_LEN); + if (snonce) + os_memcpy(hdr->snonce, snonce, WPA_NONCE_LEN); + } else { + struct rsn_ftie *hdr = (struct rsn_ftie *) pos; + + os_memset(hdr, 0, sizeof(*hdr)); + pos += sizeof(*hdr); + WPA_PUT_LE16(hdr->mic_control, 0); + if (anonce) + os_memcpy(hdr->anonce, anonce, WPA_NONCE_LEN); + if (snonce) + os_memcpy(hdr->snonce, snonce, WPA_NONCE_LEN); + } /* Optional Parameters */ *pos++ = FTIE_SUBELEM_R1KH_ID; @@ -2308,10 +2322,10 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos, const u8 *req_ies, size_t req_ies_len) { u8 *end, *mdie, *ftie, *rsnie = NULL, *r0kh_id, *subelem = NULL; + u8 *fte_mic, *elem_count; size_t mdie_len, ftie_len, rsnie_len = 0, r0kh_id_len, subelem_len = 0; int res; struct wpa_auth_config *conf; - struct rsn_ftie *_ftie; struct wpa_ft_ies parse; u8 *ric_start; u8 *anonce, *snonce; @@ -2386,8 +2400,9 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos, anonce = NULL; snonce = NULL; } - res = wpa_write_ftie(conf, r0kh_id, r0kh_id_len, anonce, snonce, pos, - end - pos, subelem, subelem_len); + res = wpa_write_ftie(conf, use_sha384, r0kh_id, r0kh_id_len, + anonce, snonce, pos, end - pos, + subelem, subelem_len); os_free(subelem); if (res < 0) return pos; @@ -2395,9 +2410,20 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos, ftie_len = res; pos += res; - _ftie = (struct rsn_ftie *) (ftie + 2); + if (use_sha384) { + struct rsn_ftie_sha384 *_ftie = + (struct rsn_ftie_sha384 *) (ftie + 2); + + fte_mic = _ftie->mic; + elem_count = &_ftie->mic_control[1]; + } else { + struct rsn_ftie *_ftie = (struct rsn_ftie *) (ftie + 2); + + fte_mic = _ftie->mic; + elem_count = &_ftie->mic_control[1]; + } if (auth_alg == WLAN_AUTH_FT) - _ftie->mic_control[1] = 3; /* Information element count */ + *elem_count = 3; /* Information element count */ ric_start = pos; if (wpa_ft_parse_ies(req_ies, req_ies_len, &parse, use_sha384) == 0 @@ -2405,7 +2431,7 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos, pos = wpa_ft_process_ric(sm, pos, end, parse.ric, parse.ric_len); if (auth_alg == WLAN_AUTH_FT) - _ftie->mic_control[1] += + *elem_count += ieee802_11_ie_count(ric_start, pos - ric_start); } @@ -2424,7 +2450,7 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos, mdie, mdie_len, ftie, ftie_len, rsnie, rsnie_len, ric_start, ric_start ? pos - ric_start : 0, - _ftie->mic) < 0) + fte_mic) < 0) wpa_printf(MSG_DEBUG, "FT: Failed to calculate MIC"); os_free(sm->assoc_resp_ftie); @@ -2871,7 +2897,7 @@ pmk_r1_derived: goto fail; pos += ret; - ret = wpa_write_ftie(conf, parse.r0kh_id, parse.r0kh_id_len, + ret = wpa_write_ftie(conf, use_sha384, parse.r0kh_id, parse.r0kh_id_len, sm->ANonce, sm->SNonce, pos, end - pos, NULL, 0); if (ret < 0) goto fail; diff --git a/src/ap/wpa_auth_i.h b/src/ap/wpa_auth_i.h index 676e4bf15..b1cea1b49 100644 --- a/src/ap/wpa_auth_i.h +++ b/src/ap/wpa_auth_i.h @@ -277,8 +277,8 @@ int wpa_auth_for_each_auth(struct wpa_authenticator *wpa_auth, #ifdef CONFIG_IEEE80211R_AP int wpa_write_mdie(struct wpa_auth_config *conf, u8 *buf, size_t len); -int wpa_write_ftie(struct wpa_auth_config *conf, const u8 *r0kh_id, - size_t r0kh_id_len, +int wpa_write_ftie(struct wpa_auth_config *conf, int use_sha384, + const u8 *r0kh_id, size_t r0kh_id_len, const u8 *anonce, const u8 *snonce, u8 *buf, size_t len, const u8 *subelem, size_t subelem_len);