}
+static void wpa_sm_tptk_to_ptk(struct wpa_sm *sm)
+{
+ sm->tptk_set = 0;
+ sm->ptk_set = 1;
+ os_memcpy(&sm->ptk, &sm->tptk, sizeof(sm->ptk));
+ os_memset(&sm->tptk, 0, sizeof(sm->tptk));
+
+ if (wpa_sm_pmf_enabled(sm)) {
+ os_memcpy(sm->last_kck, sm->ptk.kck, sm->ptk.kck_len);
+ sm->last_kck_len = sm->ptk.kck_len;
+ sm->last_kck_pmk_len = sm->pmk_len;
+ sm->last_kck_key_mgmt = sm->key_mgmt;
+ sm->last_kck_eapol_key_ver = sm->last_eapol_key_ver;
+ os_memcpy(sm->last_kck_aa, wpa_sm_get_auth_addr(sm), ETH_ALEN);
+ } else {
+ os_memset(sm->last_kck, 0, sizeof(sm->last_kck));
+ sm->last_kck_len = 0;
+ os_memset(sm->last_kck_aa, 0, ETH_ALEN);
+ }
+}
+
+
static int wpa_supplicant_verify_eapol_key_mic(struct wpa_sm *sm,
struct wpa_eapol_key *key,
u16 ver,
continue_fuzz:
#endif /* TEST_FUZZ */
ok = 1;
- sm->tptk_set = 0;
- sm->ptk_set = 1;
- os_memcpy(&sm->ptk, &sm->tptk, sizeof(sm->ptk));
- os_memset(&sm->tptk, 0, sizeof(sm->tptk));
+ wpa_sm_tptk_to_ptk(sm);
/*
* This assures the same TPTK in sm->tptk can never be
* copied twice to sm->ptk as the new PTK. In
WPA_PUT_BE16(pos, *key_data_len);
bin_clear_free(tmp, *key_data_len);
- if (sm->tptk_set) {
- sm->tptk_set = 0;
- sm->ptk_set = 1;
- os_memcpy(&sm->ptk, &sm->tptk, sizeof(sm->ptk));
- os_memset(&sm->tptk, 0, sizeof(sm->tptk));
- }
+ if (sm->tptk_set)
+ wpa_sm_tptk_to_ptk(sm);
os_memcpy(sm->rx_replay_counter, key->replay_counter,
WPA_REPLAY_COUNTER_LEN);
goto out;
}
+ sm->last_eapol_key_ver = ver;
+
if ((key_info & WPA_KEY_INFO_MIC) &&
wpa_supplicant_verify_eapol_key_mic(sm, key, ver, tmp, data_len))
goto out;
#ifdef CONFIG_DPP2
wpabuf_clear_free(sm->dpp_z);
#endif /* CONFIG_DPP2 */
+ os_memset(sm->last_kck, 0, sizeof(sm->last_kck));
os_free(sm);
}
if (sm)
sm->driver_bss_selection = driver_bss_selection;
}
+
+
+struct wpabuf * wpa_sm_known_sta_identification(struct wpa_sm *sm, const u8 *aa,
+ u64 timestamp)
+{
+ struct wpabuf *ie;
+ unsigned int mic_len;
+ const u8 *start;
+ u8 *mic;
+
+ if (!sm || sm->last_kck_len == 0)
+ return NULL;
+
+ if (!ether_addr_equal(aa, sm->last_kck_aa))
+ return NULL;
+
+ mic_len = wpa_mic_len(sm->last_kck_key_mgmt, sm->last_kck_pmk_len);
+
+ ie = wpabuf_alloc(3 + 8 + 1 + mic_len);
+ if (!ie)
+ return NULL;
+
+ wpabuf_put_u8(ie, WLAN_EID_EXTENSION);
+ wpabuf_put_u8(ie, 1 + 8 + 1 + mic_len);
+ wpabuf_put_u8(ie, WLAN_EID_EXT_KNOWN_STA_IDENTIFICATION);
+ start = wpabuf_put(ie, 0);
+ wpabuf_put_le64(ie, timestamp);
+ wpabuf_put_u8(ie, mic_len);
+ mic = wpabuf_put(ie, mic_len);
+ if (wpa_eapol_key_mic(sm->last_kck, sm->last_kck_len,
+ sm->last_kck_key_mgmt, sm->last_kck_eapol_key_ver,
+ start, 8, mic) < 0) {
+ wpabuf_free(ie);
+ return NULL;
+ }
+
+ return ie;
+}
wpa_s->sme.assoc_req_ie_len += wpa_s->rsnxe_len;
}
+ if (wpa_s->sme.mfp != NO_MGMT_FRAME_PROTECTION &&
+ wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_KNOWN_STA_IDENTIFICATION)) {
+ struct wpabuf *e;
+
+ e = wpa_sm_known_sta_identification(
+ wpa_s->wpa,
+ params.mld ? params.ap_mld_addr : bss->bssid,
+ bss->tsf);
+ if (e) {
+ size_t len;
+
+ len = sizeof(wpa_s->sme.assoc_req_ie) -
+ wpa_s->sme.assoc_req_ie_len;
+ if (wpabuf_len(e) <= len) {
+ wpa_printf(MSG_DEBUG,
+ "SME: Add Known STA Identification element");
+ os_memcpy(wpa_s->sme.assoc_req_ie +
+ wpa_s->sme.assoc_req_ie_len,
+ wpabuf_head(e), wpabuf_len(e));
+ wpa_s->sme.assoc_req_ie_len += wpabuf_len(e);
+ }
+ wpabuf_free(e);
+ }
+ }
+
#ifdef CONFIG_HS20
if (is_hs20_network(wpa_s, ssid, bss)) {
struct wpabuf *hs20;