[wpa_supplicant] cumilative patch from commit bb945b98f
Bug: 275651698
Test: Connect to open, WPA2, WPA3 and passpoint network
Test: Establish P2P connection
Test: Basic SoftAp tests
Test: Regression test (b/275948027)
BYPASS_INCLUSIVE_LANGUAGE_REASON=Merged from opne source
bb945b98f Add 40 and 80 MHz channels 165 and 173 for 5 GHz IBSS/mesh
0059fa5ba 6 GHz: Fix secondary channel setting
744295c8b Add 6 GHz channel validation during channel switching
5349a45d3 Set interface state as inactive if mesh bringup fails
a4af79624 Handle signal termination in hostapd_cli for all cases
cf8f13ac8 Add support to send 320 MHz bandwidth through vendor subcmd
a0403c023 EHT: Validate the puncturing bitmap for ACS
af0f60e7d EHT: Calculate puncturing bitmap for ACS
f3206fbe9 EHT: Configuration option for ACS puncturing threshold
e3621867c EHT: Process puncturing bitmap from channel switch event
e277e577c nl80211: Send EHT puncturing bitmap to the driver for switch command
29a882bed EHT: Configure puncturing bitmap during channel switch
4942b19ff EHT: Send puncturing bitmap to the driver for AP bring up
f9fc2eabb EHT: Add puncturing bitmap to EHT Operation element
46a5d989d EHT: Downgrade bandwidths for VHT and HE when using puncturing
7618269ec EHT: Validate puncturing bitmap
9102fda31 EHT: Add configuration option for puncturing in AP mode
9e79439fc nl80211: Retrieve driver support for EHT puncturing
507be376c Sync with wireless-next.git include/uapi/linux/nl80211.h
591256a8c FILS: 320 MHz support in FD frame
903e3a1e6 FILS: Fix maximum NSS calculation for FD frame
ecae45ff6 FILS: Make HE a requirement for FILS discovery
4e86692ff AP: Fix 6 GHz AP setup after disable-enable
a34b8477a ml80211: Put wiphy idx to obtain correct country code
1491fc64a Define QCA vendor per-enum 64-bit pad attributes
55e31699e qca-vendor: Add QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_NF_CAL_VAL
b1f85957c Add QCA vendor commands to set and get MLO links state information
44b32a752 mesh: Add EHT support
c4cb62ca8 WPA_AUTH: MLO: Add functions to get the AA and SPA
cab963e9f AP: Split check_assoc_ies()
7a7a2256c common: Support parsing link specific association request
b39e35693 common: Add support for clearing elements
0b2fc4268 common: Split ieee8021_parse_elems()
df6561ec0 nl80211: AP MLD support for adding multi link stations
b8b4ceb8d nl80211: Properly stop and deinit MLO AP
2f8fc46ed nl80211: Provide link_id in EAPOL_RX and RX_MGMT events
821374d43 nl80211: Introduce and implement a callback to add an MLO link for AP MLD
47269be36 nl80211: Refactor i802_bss to support multiple links
eb146ee80 AP: Add some bridge port attribute settings
f628e6b30 nl80211: Make sure scan frequency debug buffer is NUL terminated
41d23254b nl80211: Fix frequencies array boundary check for scanned frequencies
a9012070a Android: Add wowlan_disconnect_on_deinit to template configuration
e2ea0fd70 EST: Write the RSA private key using the standard PRIVATE KEY format
bfd236df2 webkit2: Avoid deprecated function call
2c3202682 P2P: Filter out 6 GHz frequencies if not allowed for P2P connection
b2bf7e39e Update PMK in wpa_sm when roam+auth event indicated with authorized flag
6b9c86466 nl80211: Replace the channel flags for VHT support
6f63aca7b DPP: Allow both STA and AP configObject to be set
7292e30b7 DPP: Fix @CONF-OBJ-SEP@ parsing for multiple configs
c31600ce1 P2P: Allow GO BSSID to be specified for P2P_GROUP_ADD commands
0430756e6 P2P: Optimize join scan frequency
b3921db42 nl80211: Add frequency info in start AP command
40c139664 macsec_linux: Add support for MACsec hardware offload
6d24673ab mka: Allow configuration of MACsec hardware offload
3081a9cb6 hostapd: Output country_code and country3 when using STATUS
91ad7a309 FT: Store PTKSA entry for the correct BSSID in the FT protocol case
3f3e356fa Mark addr argument to storing PTKSA const
242c3ad99 FT: Store PTKSA from FT protocol
ba6954874 Mark wpa_auth_remove_ptksa() static
3b1ad1334 FT: Include KDK in FT specific PTK derivation on the AP
870a5bdc0 nl80211: Report guard interval and dual carrier modulation
edcad193a dbus: Add inactive time to D-Bus signal info
a678a510f dbus: Add D-Bus signal for PSK mismatch heuristics
691f729d5 P2P: Make invitation flow less aggressive
f4a7e2a07 Rework IBSS/mesh 80 MHz channel selection
f91f971bd Fix creating 6 GHz IBSS/mesh on 5/6 GHz-capable PHYs
c623cee42 Make arrays static const in ibss_mesh_select_*()
64043e615 Split ibss_mesh_setup_freq() into multiple functions
8085a7e65 wpa_supplicant: Add option to explicitly set 4addr mode
1ffc7d1c6 Apply bias towards 6 GHz in roaming
faa410292 WNM: Event report handling for BSS color collision and in-use
97405be96 Small textual improvements to wpa_supplicant man page
ec02a0e93 hostapd: Output hw_mode when using STATUS
390e24c6c EAP-TTLS server: Add Ident field to MS-CHAP-Error
4ae798a22 P2P: Pick the best driver pref freq for invitation process
6c75f1dfa Send broadcast Probe Response frames on the 6 GHz band
edfcb2f1a MLD STA: Indicate MLO support in NL80211_CMD_CONNECT
c91852044 MLD STA: Add support for SAE external authentication offload to userspace
575712450 qca-vendor: Add QCA_WLAN_VENDOR_MCC_QUOTA_TYPE_LOW_LATENCY
ba150059d FT: Store PMK-R0/PMK-R1 after EAPOL-Key msg 2/4 MIC validation
56662f36d Refine vendor subcmd QCA_NL80211_VENDOR_SUBCMD_ROAM_STATS
72b8193f4 MACsec: Remove EAP Session-Id length constraint
3915e8834 hostapd: Report error on unknown ACCEPT_ACL/DENY_ACL commands
2cff340d1 utils: Move log2pcap to python3
12de8112b Fix BSS age underflow
d31c2b43a Fix segfault in case of an invalid configuration
a32b424a3 MLD STA: Use AP MLD address in PMKSA cache attempts for driver-SME case
8c4790cef MLD STA: Store PMKSA with AP MLD address for MLO connection event
bf124a03d SAE: Update PT value at later point for SME cases, if needed
1aadcca0a P2P: Enable SAE-H2E for client when joining a 6 GHz group
37f8257c4 SAE: Extend automatic enabling of H2E on 6 GHz to additional cases
89377c6b9 OCV: Fix build without CONFIG_OCV=y
2e47ea22c P2P: Fix handling Service Discovery Response received by GO device
dc7e330e0 Set OCV capability based on Association Request frame RSNE
831be6514 WPS: Do not indicate incorrect PBC overlap based on partner link
c9fc12425 P2P: Make wpas_p2p_notif_pbc_overlap() static
Change-Id: I1eb61fc82b98b937a2ff37a30e60e28129fe143d
diff --git a/src/ap/acs.c b/src/ap/acs.c
index 8cb5813..1181c7d 100644
--- a/src/ap/acs.c
+++ b/src/ap/acs.c
@@ -326,6 +326,7 @@
dl_list_init(&chan->survey_list);
chan->flag |= HOSTAPD_CHAN_SURVEY_LIST_INITIALIZED;
chan->min_nf = 0;
+ chan->punct_bitmap = 0;
}
}
@@ -711,6 +712,62 @@
#define ACS_24GHZ_PREFER_1_6_11 0.8
#endif /* ACS_24GHZ_PREFER_1_6_11 */
+
+#ifdef CONFIG_IEEE80211BE
+static void acs_update_puncturing_bitmap(struct hostapd_iface *iface,
+ struct hostapd_hw_modes *mode, u32 bw,
+ int n_chans,
+ struct hostapd_channel_data *chan,
+ long double factor,
+ int index_primary)
+{
+ struct hostapd_config *conf = iface->conf;
+ struct hostapd_channel_data *adj_chan = NULL, *first_chan = chan;
+ int i;
+ long double threshold;
+
+ /*
+ * If threshold is 0 or user configured puncturing pattern is
+ * available then don't add additional puncturing.
+ */
+ if (!conf->punct_acs_threshold || conf->punct_bitmap)
+ return;
+
+ if (is_24ghz_mode(mode->mode) || bw < 80)
+ return;
+
+ threshold = factor * conf->punct_acs_threshold / 100;
+ for (i = 0; i < n_chans; i++) {
+ int adj_freq;
+
+ if (i == index_primary)
+ continue; /* Cannot puncture primary channel */
+
+ if (i > index_primary)
+ adj_freq = chan->freq + (i - index_primary) * 20;
+ else
+ adj_freq = chan->freq - (index_primary - i) * 20;
+
+ adj_chan = acs_find_chan(iface, adj_freq);
+ if (!adj_chan) {
+ chan->punct_bitmap = 0;
+ return;
+ }
+
+ if (i == 0)
+ first_chan = adj_chan;
+
+ if (adj_chan->interference_factor > threshold)
+ chan->punct_bitmap |= BIT(i);
+ }
+
+ if (!is_punct_bitmap_valid(bw, (chan->freq - first_chan->freq) / 20,
+ chan->punct_bitmap))
+ chan->punct_bitmap = 0;
+}
+#endif /* CONFIG_IEEE80211BE */
+
+
static void
acs_find_ideal_chan_mode(struct hostapd_iface *iface,
struct hostapd_hw_modes *mode,
@@ -734,7 +791,13 @@
/* Since in the current ACS implementation the first channel is
* always a primary channel, skip channels not available as
* primary until more sophisticated channel selection is
- * implemented. */
+ * implemented.
+ *
+ * If this implementation is changed to allow any channel in
+ * the bandwidth to be the primary one, the last parameter to
+ * acs_update_puncturing_bitmap() should be changed to the index
+ * of the primary channel
+ */
if (!chan_pri_allowed(chan))
continue;
@@ -913,8 +976,20 @@
if (acs_usable_chan(chan) &&
(!*ideal_chan || factor < *ideal_factor)) {
+ /* Reset puncturing bitmap for the previous ideal
+ * channel */
+ if (*ideal_chan)
+ (*ideal_chan)->punct_bitmap = 0;
+
*ideal_factor = factor;
*ideal_chan = chan;
+
+#ifdef CONFIG_IEEE80211BE
+ if (iface->conf->ieee80211be)
+ acs_update_puncturing_bitmap(iface, mode, bw,
+ n_chans, chan,
+ factor, 0);
+#endif /* CONFIG_IEEE80211BE */
}
/* This channel would at least be usable */
@@ -991,9 +1066,22 @@
if (ideal_chan) {
wpa_printf(MSG_DEBUG, "ACS: Ideal channel is %d (%d MHz) with total interference factor of %Lg",
ideal_chan->chan, ideal_chan->freq, ideal_factor);
+
+#ifdef CONFIG_IEEE80211BE
+ if (iface->conf->punct_acs_threshold)
+ wpa_printf(MSG_DEBUG, "ACS: RU puncturing bitmap 0x%x",
+ ideal_chan->punct_bitmap);
+#endif /* CONFIG_IEEE80211BE */
+
return ideal_chan;
}
+#ifdef CONFIG_IEEE80211BE
+ if (iface->conf->punct_acs_threshold)
+ wpa_printf(MSG_DEBUG, "ACS: RU puncturing bitmap 0x%x",
+ ideal_chan->punct_bitmap);
+#endif /* CONFIG_IEEE80211BE */
+
return rand_chan;
}
@@ -1106,6 +1194,9 @@
iface->conf->channel = ideal_chan->chan;
iface->freq = ideal_chan->freq;
+#ifdef CONFIG_IEEE80211BE
+ iface->conf->punct_bitmap = ideal_chan->punct_bitmap;
+#endif /* CONFIG_IEEE80211BE */
if (iface->conf->ieee80211ac || iface->conf->ieee80211ax) {
acs_adjust_secondary(iface);
diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
index 5dc8a8f..b5fcc38 100644
--- a/src/ap/ap_config.c
+++ b/src/ap/ap_config.c
@@ -1447,6 +1447,13 @@
#ifdef CONFIG_FILS
if (full_config && bss->fils_discovery_max_int &&
+ (!conf->ieee80211ax || bss->disable_11ax)) {
+ wpa_printf(MSG_ERROR,
+ "Currently IEEE 802.11ax support is mandatory to enable FILS discovery transmission.");
+ return -1;
+ }
+
+ if (full_config && bss->fils_discovery_max_int &&
bss->unsol_bcast_probe_resp_interval) {
wpa_printf(MSG_ERROR,
"Cannot enable both FILS discovery and unsolicited broadcast Probe Response at the same time");
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index 6dbb223..07ee31c 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -284,6 +284,7 @@
char bridge[IFNAMSIZ + 1];
char vlan_bridge[IFNAMSIZ + 1];
char wds_bridge[IFNAMSIZ + 1];
+ int bridge_hairpin; /* hairpin_mode on bridge members */
enum hostapd_logger_level logger_syslog_level, logger_stdout_level;
@@ -748,6 +749,7 @@
#endif /* CONFIG_FILS */
int multicast_to_unicast;
+ int bridge_multicast_to_unicast;
int broadcast_deauth;
@@ -845,6 +847,19 @@
u32 macsec_replay_window;
/**
+ * macsec_offload - Enable MACsec offload
+ *
+ * This setting applies only when MACsec is in use, i.e.,
+ * - macsec_policy is enabled
+ * - the key server has decided to enable MACsec
+ *
+ * 0 = MACSEC_OFFLOAD_OFF (default)
+ * 1 = MACSEC_OFFLOAD_PHY
+ * 2 = MACSEC_OFFLOAD_MAC
+ */
+ int macsec_offload;
+
+ /**
* macsec_port - MACsec port (in SCI)
*
* Port component of the SCI.
@@ -1143,6 +1158,8 @@
enum oper_chan_width eht_oper_chwidth;
u8 eht_oper_centr_freq_seg0_idx;
struct eht_phy_capabilities_info eht_phy_capab;
+ u16 punct_bitmap; /* a bitmap of disabled 20 MHz channels */
+ u8 punct_acs_threshold;
#endif /* CONFIG_IEEE80211BE */
/* EHT enable/disable config from CHAN_SWITCH */
diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
index 1ffc37f..f77f738 100644
--- a/src/ap/ap_drv_ops.c
+++ b/src/ap/ap_drv_ops.c
@@ -459,6 +459,7 @@
params.qosinfo = qosinfo;
params.support_p2p_ps = supp_p2p_ps;
params.set = set;
+ params.mld_link_id = -1;
return hapd->driver->sta_add(hapd->drv_priv, ¶ms);
}
diff --git a/src/ap/beacon.c b/src/ap/beacon.c
index dbc6b06..c25a5bb 100644
--- a/src/ap/beacon.c
+++ b/src/ap/beacon.c
@@ -533,8 +533,7 @@
static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
const struct ieee80211_mgmt *req,
int is_p2p, size_t *resp_len,
- bool bcast_probe_resp, const u8 *known_bss,
- u8 known_bss_len)
+ const u8 *known_bss, u8 known_bss_len)
{
struct ieee80211_mgmt *resp;
u8 *pos, *epos, *csa_pos;
@@ -585,6 +584,8 @@
if (hapd->iconf->ieee80211be && !hapd->conf->disable_11be) {
buflen += hostapd_eid_eht_capab_len(hapd, IEEE80211_MODE_AP);
buflen += 3 + sizeof(struct ieee80211_eht_operation);
+ if (hapd->iconf->punct_bitmap)
+ buflen += EHT_OPER_DISABLED_SUBCHAN_BITMAP_SIZE;
}
#endif /* CONFIG_IEEE80211BE */
@@ -603,9 +604,16 @@
resp->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
WLAN_FC_STYPE_PROBE_RESP);
- if (req)
+ /* Unicast the response to all requests on bands other than 6 GHz. For
+ * the 6 GHz, unicast is used only if the actual SSID is not included in
+ * the Beacon frames. Otherwise, broadcast response is used per IEEE
+ * Std 802.11ax-2021, 26.17.2.3.2. Broadcast address is also used for
+ * the Probe Response frame template for the unsolicited (i.e., not as
+ * a response to a specific request) case. */
+ if (req && (!is_6ghz_op_class(hapd->iconf->op_class) ||
+ hapd->conf->ignore_broadcast_ssid))
os_memcpy(resp->da, req->sa, ETH_ALEN);
- else if (bcast_probe_resp)
+ else
os_memset(resp->da, 0xff, ETH_ALEN);
os_memcpy(resp->sa, hapd->own_addr, ETH_ALEN);
@@ -1230,7 +1238,7 @@
" signal=%d", MAC2STR(mgmt->sa), ssi_signal);
resp = hostapd_gen_probe_resp(hapd, mgmt, elems.p2p != NULL,
- &resp_len, false, elems.mbssid_known_bss,
+ &resp_len, elems.mbssid_known_bss,
elems.mbssid_known_bss_len);
if (resp == NULL)
return;
@@ -1301,7 +1309,7 @@
"this");
/* Generate a Probe Response template for the non-P2P case */
- return hostapd_gen_probe_resp(hapd, NULL, 0, resp_len, false, NULL, 0);
+ return hostapd_gen_probe_resp(hapd, NULL, 0, resp_len, NULL, 0);
}
#endif /* NEED_AP_MLME */
@@ -1320,7 +1328,7 @@
return hostapd_gen_probe_resp(hapd, NULL, 0,
¶ms->unsol_bcast_probe_resp_tmpl_len,
- true, NULL, 0);
+ NULL, 0);
}
#endif /* CONFIG_IEEE80211AX */
@@ -1351,6 +1359,9 @@
phy_index = FD_CAP_PHY_INDEX_HE;
switch (hapd->iconf->op_class) {
+ case 137:
+ chwidth = FD_CAP_BSS_CHWIDTH_320;
+ break;
case 135:
mcs_nss_size += 4;
/* fallthrough */
@@ -1404,14 +1415,37 @@
cap_info |= phy_index << FD_CAP_PHY_INDEX_SHIFT;
cap_info |= chwidth << FD_CAP_BSS_CHWIDTH_SHIFT;
- if (mode) {
- u16 *mcs = (u16 *) mode->he_capab[IEEE80211_MODE_AP].mcs;
+ if (mode && phy_index == FD_CAP_PHY_INDEX_HE) {
+ const u8 *he_mcs = mode->he_capab[IEEE80211_MODE_AP].mcs;
int i;
- u16 nss = 0;
+ u16 nss = 0, mcs[6];
+
+ os_memset(mcs, 0xffff, 6 * sizeof(u16));
+
+ if (mcs_nss_size == 4) {
+ mcs[0] = WPA_GET_LE16(&he_mcs[0]);
+ mcs[1] = WPA_GET_LE16(&he_mcs[2]);
+ }
+
+ if (mcs_nss_size == 8) {
+ mcs[2] = WPA_GET_LE16(&he_mcs[4]);
+ mcs[3] = WPA_GET_LE16(&he_mcs[6]);
+ }
+
+ if (mcs_nss_size == 12) {
+ mcs[4] = WPA_GET_LE16(&he_mcs[8]);
+ mcs[5] = WPA_GET_LE16(&he_mcs[10]);
+ }
for (i = 0; i < HE_NSS_MAX_STREAMS; i++) {
u16 nss_mask = 0x3 << (i * 2);
+ /*
+ * If NSS values supported by RX and TX are different
+ * then choose the smaller of the two as the maximum
+ * supported NSS as that is the value supported by
+ * both RX and TX.
+ */
if (mcs_nss_size == 4 &&
(((mcs[0] & nss_mask) == nss_mask) ||
((mcs[1] & nss_mask) == nss_mask)))
@@ -1655,6 +1689,8 @@
if (hapd->iconf->ieee80211be && !hapd->conf->disable_11be) {
tail_len += hostapd_eid_eht_capab_len(hapd, IEEE80211_MODE_AP);
tail_len += 3 + sizeof(struct ieee80211_eht_operation);
+ if (hapd->iconf->punct_bitmap)
+ tail_len += EHT_OPER_DISABLED_SUBCHAN_BITMAP_SIZE;
}
#endif /* CONFIG_IEEE80211BE */
@@ -2065,6 +2101,10 @@
params.fd_frame_tmpl = hostapd_fils_discovery(hapd, ¶ms);
#endif /* CONFIG_FILS */
+#ifdef CONFIG_IEEE80211BE
+ params.punct_bitmap = iconf->punct_bitmap;
+#endif /* CONFIG_IEEE80211BE */
+
if (cmode &&
hostapd_set_freq_params(&freq, iconf->hw_mode, iface->freq,
iconf->channel, iconf->enable_edmg,
diff --git a/src/ap/ctrl_iface_ap.c b/src/ap/ctrl_iface_ap.c
index 168e5f5..6934a73 100644
--- a/src/ap/ctrl_iface_ap.c
+++ b/src/ap/ctrl_iface_ap.c
@@ -212,6 +212,26 @@
}
+static const char * hw_mode_str(enum hostapd_hw_mode mode)
+{
+ switch (mode) {
+ case HOSTAPD_MODE_IEEE80211B:
+ return "b";
+ case HOSTAPD_MODE_IEEE80211G:
+ return "g";
+ case HOSTAPD_MODE_IEEE80211A:
+ return "a";
+ case HOSTAPD_MODE_IEEE80211AD:
+ return "ad";
+ case HOSTAPD_MODE_IEEE80211ANY:
+ return "any";
+ case NUM_HOSTAPD_MODES:
+ return "invalid";
+ }
+ return "unknown";
+}
+
+
static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd,
struct sta_info *sta,
char *buf, size_t buflen)
@@ -696,6 +716,7 @@
{
struct hostapd_iface *iface = hapd->iface;
struct hostapd_hw_modes *mode = iface->current_mode;
+ struct hostapd_config *iconf = hapd->iconf;
int len = 0, ret, j;
size_t i;
@@ -730,6 +751,24 @@
return len;
len += ret;
+ if (mode) {
+ ret = os_snprintf(buf + len, buflen - len, "hw_mode=%s\n",
+ hw_mode_str(mode->mode));
+ if (os_snprintf_error(buflen - len, ret))
+ return len;
+ len += ret;
+ }
+
+ if (iconf->country[0] && iconf->country[1]) {
+ ret = os_snprintf(buf + len, buflen - len,
+ "country_code=%c%c\ncountry3=0x%X\n",
+ iconf->country[0], iconf->country[1],
+ iconf->country[2]);
+ if (os_snprintf_error(buflen - len, ret))
+ return len;
+ len += ret;
+ }
+
if (!iface->cac_started || !iface->dfs_cac_ms) {
ret = os_snprintf(buf + len, buflen - len,
"cac_time_seconds=%d\n"
@@ -941,16 +980,27 @@
} \
} while (0)
+#define SET_CSA_SETTING_EXT(str) \
+ do { \
+ const char *pos2 = os_strstr(pos, " " #str "="); \
+ if (pos2) { \
+ pos2 += sizeof(" " #str "=") - 1; \
+ settings->str = atoi(pos2); \
+ } \
+ } while (0)
+
SET_CSA_SETTING(center_freq1);
SET_CSA_SETTING(center_freq2);
SET_CSA_SETTING(bandwidth);
SET_CSA_SETTING(sec_channel_offset);
+ SET_CSA_SETTING_EXT(punct_bitmap);
settings->freq_params.ht_enabled = !!os_strstr(pos, " ht");
settings->freq_params.vht_enabled = !!os_strstr(pos, " vht");
settings->freq_params.he_enabled = !!os_strstr(pos, " he");
settings->freq_params.eht_enabled = !!os_strstr(pos, " eht");
settings->block_tx = !!os_strstr(pos, " blocktx");
#undef SET_CSA_SETTING
+#undef SET_CSA_SETTING_EXT
return 0;
}
diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
index 4c33e86..8fc128e 100644
--- a/src/ap/drv_callbacks.c
+++ b/src/ap/drv_callbacks.c
@@ -859,7 +859,7 @@
void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
int offset, int width, int cf1, int cf2,
- int finished)
+ u16 punct_bitmap, int finished)
{
#ifdef NEED_AP_MLME
int channel, chwidth, is_dfs0, is_dfs;
@@ -868,14 +868,14 @@
hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_INFO,
- "driver %s channel switch: iface->freq=%d, freq=%d, ht=%d, vht_ch=0x%x, "
- "he_ch=0x%x, eht_ch=0x%x, offset=%d, width=%d (%s), cf1=%d, cf2=%d",
+ "driver %s channel switch: iface->freq=%d, freq=%d, ht=%d, vht_ch=0x%x, he_ch=0x%x, eht_ch=0x%x, offset=%d, width=%d (%s), cf1=%d, cf2=%d, puncturing_bitmap=0x%x",
finished ? "had" : "starting",
hapd->iface->freq,
freq, ht, hapd->iconf->ch_switch_vht_config,
hapd->iconf->ch_switch_he_config,
hapd->iconf->ch_switch_eht_config, offset,
- width, channel_width_to_string(width), cf1, cf2);
+ width, channel_width_to_string(width), cf1, cf2,
+ punct_bitmap);
if (!hapd->iface->current_mode) {
hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
@@ -987,6 +987,9 @@
hostapd_set_oper_chwidth(hapd->iconf, chwidth);
hostapd_set_oper_centr_freq_seg0_idx(hapd->iconf, seg0_idx);
hostapd_set_oper_centr_freq_seg1_idx(hapd->iconf, seg1_idx);
+#ifdef CONFIG_IEEE80211BE
+ hapd->iconf->punct_bitmap = punct_bitmap;
+#endif /* CONFIG_IEEE80211BE */
if (hapd->iconf->ieee80211ac) {
hapd->iconf->vht_capab &= ~VHT_CAP_SUPP_CHAN_WIDTH_MASK;
if (chwidth == CONF_OPER_CHWIDTH_160MHZ)
@@ -1001,11 +1004,11 @@
hapd->iface->num_hw_features);
wpa_msg(hapd->msg_ctx, MSG_INFO,
- "%sfreq=%d ht_enabled=%d ch_offset=%d ch_width=%s cf1=%d cf2=%d is_dfs0=%d dfs=%d",
+ "%sfreq=%d ht_enabled=%d ch_offset=%d ch_width=%s cf1=%d cf2=%d is_dfs0=%d dfs=%d puncturing_bitmap=0x%04x",
finished ? WPA_EVENT_CHANNEL_SWITCH :
WPA_EVENT_CHANNEL_SWITCH_STARTED,
freq, ht, offset, channel_width_to_string(width),
- cf1, cf2, is_dfs0, is_dfs);
+ cf1, cf2, is_dfs0, is_dfs, punct_bitmap);
if (!finished)
return;
@@ -2028,6 +2031,7 @@
data->ch_switch.ch_width,
data->ch_switch.cf1,
data->ch_switch.cf2,
+ data->ch_switch.punct_bitmap,
event == EVENT_CH_SWITCH);
break;
case EVENT_CONNECT_FAILED_REASON:
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index 58492e5..8b3fb40 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -1435,6 +1435,22 @@
return -1;
}
+ if (conf->bridge[0]) {
+ /* Set explicitly configured bridge parameters that might have
+ * been lost if the interface has been removed out of the
+ * bridge. */
+
+ /* multicast to unicast on bridge ports */
+ if (conf->bridge_multicast_to_unicast)
+ hostapd_drv_br_port_set_attr(
+ hapd, DRV_BR_PORT_ATTR_MCAST2UCAST, 1);
+
+ /* hairpin mode */
+ if (conf->bridge_hairpin)
+ hostapd_drv_br_port_set_attr(
+ hapd, DRV_BR_PORT_ATTR_HAIRPIN_MODE, 1);
+ }
+
if (conf->proxy_arp) {
if (x_snoop_init(hapd)) {
wpa_printf(MSG_ERROR,
@@ -1749,7 +1765,7 @@
bw = center_idx_to_bw_6ghz(seg0);
/* Assign the secondary channel if absent in config for
* bandwidths > 20 MHz */
- if (bw > 20 && !iface->conf->secondary_channel) {
+ if (bw > 0 && !iface->conf->secondary_channel) {
if (((iface->conf->channel - 1) / 4) % 2)
iface->conf->secondary_channel = -1;
else
@@ -1768,6 +1784,11 @@
} else {
int ret;
+ if (iface->conf->acs) {
+ iface->freq = 0;
+ iface->conf->channel = 0;
+ }
+
ret = configured_fixed_chan_to_freq(iface);
if (ret < 0)
goto fail;
@@ -3634,6 +3655,9 @@
struct hostapd_iface *iface = hapd->iface;
struct hostapd_freq_params old_freq;
int ret;
+#ifdef CONFIG_IEEE80211BE
+ u16 old_punct_bitmap;
+#endif /* CONFIG_IEEE80211BE */
u8 chan, bandwidth;
os_memset(&old_freq, 0, sizeof(old_freq));
@@ -3679,9 +3703,16 @@
if (ret)
return ret;
+#ifdef CONFIG_IEEE80211BE
+ old_punct_bitmap = iface->conf->punct_bitmap;
+ iface->conf->punct_bitmap = settings->punct_bitmap;
+#endif /* CONFIG_IEEE80211BE */
ret = hostapd_build_beacon_data(hapd, &settings->beacon_after);
/* change back the configuration */
+#ifdef CONFIG_IEEE80211BE
+ iface->conf->punct_bitmap = old_punct_bitmap;
+#endif /* CONFIG_IEEE80211BE */
hostapd_change_config_freq(iface->bss[0], iface->conf,
&old_freq, NULL);
diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
index a88f9b6..b81da30 100644
--- a/src/ap/hostapd.h
+++ b/src/ap/hostapd.h
@@ -727,7 +727,7 @@
int ssi_signal);
void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
int offset, int width, int cf1, int cf2,
- int finished);
+ u16 punct_bitmap, int finished);
struct survey_results;
void hostapd_event_get_survey(struct hostapd_iface *iface,
struct survey_results *survey_results);
diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c
index ed5ff41..842d9f5 100644
--- a/src/ap/hw_features.c
+++ b/src/ap/hw_features.c
@@ -893,6 +893,55 @@
}
+static bool hostapd_is_usable_punct_bitmap(struct hostapd_iface *iface)
+{
+#ifdef CONFIG_IEEE80211BE
+ struct hostapd_config *conf = iface->conf;
+ u8 bw, start_chan;
+
+ if (!conf->punct_bitmap)
+ return true;
+
+ if (!conf->ieee80211be) {
+ wpa_printf(MSG_ERROR,
+ "Currently RU puncturing is supported only if ieee80211be is enabled");
+ return false;
+ }
+
+ if (iface->freq >= 2412 && iface->freq <= 2484) {
+ wpa_printf(MSG_ERROR,
+ "RU puncturing not supported in 2.4 GHz");
+ return false;
+ }
+
+ switch (conf->eht_oper_chwidth) {
+ case 0:
+ wpa_printf(MSG_ERROR,
+ "RU puncturing is supported only in 80 MHz and 160 MHz");
+ return false;
+ case 1:
+ bw = 80;
+ start_chan = conf->eht_oper_centr_freq_seg0_idx - 6;
+ break;
+ case 2:
+ bw = 160;
+ start_chan = conf->eht_oper_centr_freq_seg0_idx - 14;
+ break;
+ default:
+ return false;
+ }
+
+ if (!is_punct_bitmap_valid(bw, (conf->channel - start_chan) / 4,
+ conf->punct_bitmap)) {
+ wpa_printf(MSG_ERROR, "Invalid puncturing bitmap");
+ return false;
+ }
+#endif /* CONFIG_IEEE80211BE */
+
+ return true;
+}
+
+
static int hostapd_is_usable_chans(struct hostapd_iface *iface)
{
int secondary_freq;
@@ -915,6 +964,9 @@
if (!hostapd_is_usable_edmg(iface))
return 0;
+ if (!hostapd_is_usable_punct_bitmap(iface))
+ return 0;
+
if (!iface->conf->secondary_channel)
return 1;
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index e53f0dc..0142ee4 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -3652,40 +3652,34 @@
}
-static int check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
- const u8 *ies, size_t ies_len, int reassoc)
+static int __check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
+ const u8 *ies, size_t ies_len,
+ struct ieee802_11_elems *elems, int reassoc)
{
- struct ieee802_11_elems elems;
int resp;
const u8 *wpa_ie;
size_t wpa_ie_len;
const u8 *p2p_dev_addr = NULL;
- if (ieee802_11_parse_elems(ies, ies_len, &elems, 1) == ParseFailed) {
- hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
- HOSTAPD_LEVEL_INFO, "Station sent an invalid "
- "association request");
- return WLAN_STATUS_UNSPECIFIED_FAILURE;
- }
-
- resp = check_ssid(hapd, sta, elems.ssid, elems.ssid_len);
+ resp = check_ssid(hapd, sta, elems->ssid, elems->ssid_len);
if (resp != WLAN_STATUS_SUCCESS)
return resp;
- resp = check_wmm(hapd, sta, elems.wmm, elems.wmm_len);
+ resp = check_wmm(hapd, sta, elems->wmm, elems->wmm_len);
if (resp != WLAN_STATUS_SUCCESS)
return resp;
- resp = check_ext_capab(hapd, sta, elems.ext_capab, elems.ext_capab_len);
+ resp = check_ext_capab(hapd, sta, elems->ext_capab,
+ elems->ext_capab_len);
if (resp != WLAN_STATUS_SUCCESS)
return resp;
- resp = copy_supp_rates(hapd, sta, &elems);
+ resp = copy_supp_rates(hapd, sta, elems);
if (resp != WLAN_STATUS_SUCCESS)
return resp;
- resp = check_multi_ap(hapd, sta, elems.multi_ap, elems.multi_ap_len);
+ resp = check_multi_ap(hapd, sta, elems->multi_ap, elems->multi_ap_len);
if (resp != WLAN_STATUS_SUCCESS)
return resp;
- resp = copy_sta_ht_capab(hapd, sta, elems.ht_capabilities);
+ resp = copy_sta_ht_capab(hapd, sta, elems->ht_capabilities);
if (resp != WLAN_STATUS_SUCCESS)
return resp;
if (hapd->iconf->ieee80211n && hapd->iconf->require_ht &&
@@ -3698,11 +3692,11 @@
#ifdef CONFIG_IEEE80211AC
if (hapd->iconf->ieee80211ac) {
- resp = copy_sta_vht_capab(hapd, sta, elems.vht_capabilities);
+ resp = copy_sta_vht_capab(hapd, sta, elems->vht_capabilities);
if (resp != WLAN_STATUS_SUCCESS)
return resp;
- resp = set_sta_vht_opmode(hapd, sta, elems.vht_opmode_notif);
+ resp = set_sta_vht_opmode(hapd, sta, elems->vht_opmode_notif);
if (resp != WLAN_STATUS_SUCCESS)
return resp;
}
@@ -3715,9 +3709,9 @@
return WLAN_STATUS_ASSOC_DENIED_NO_VHT;
}
- if (hapd->conf->vendor_vht && !elems.vht_capabilities) {
- resp = copy_sta_vendor_vht(hapd, sta, elems.vendor_vht,
- elems.vendor_vht_len);
+ if (hapd->conf->vendor_vht && !elems->vht_capabilities) {
+ resp = copy_sta_vendor_vht(hapd, sta, elems->vendor_vht,
+ elems->vendor_vht_len);
if (resp != WLAN_STATUS_SUCCESS)
return resp;
}
@@ -3725,8 +3719,8 @@
#ifdef CONFIG_IEEE80211AX
if (hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax) {
resp = copy_sta_he_capab(hapd, sta, IEEE80211_MODE_AP,
- elems.he_capabilities,
- elems.he_capabilities_len);
+ elems->he_capabilities,
+ elems->he_capabilities_len);
if (resp != WLAN_STATUS_SUCCESS)
return resp;
@@ -3747,7 +3741,7 @@
return WLAN_STATUS_DENIED_HE_NOT_SUPPORTED;
}
resp = copy_sta_he_6ghz_capab(hapd, sta,
- elems.he_6ghz_band_cap);
+ elems->he_6ghz_band_cap);
if (resp != WLAN_STATUS_SUCCESS)
return resp;
}
@@ -3756,17 +3750,17 @@
#ifdef CONFIG_IEEE80211BE
if (hapd->iconf->ieee80211be && !hapd->conf->disable_11be) {
resp = copy_sta_eht_capab(hapd, sta, IEEE80211_MODE_AP,
- elems.he_capabilities,
- elems.he_capabilities_len,
- elems.eht_capabilities,
- elems.eht_capabilities_len);
+ elems->he_capabilities,
+ elems->he_capabilities_len,
+ elems->eht_capabilities,
+ elems->eht_capabilities_len);
if (resp != WLAN_STATUS_SUCCESS)
return resp;
}
#endif /* CONFIG_IEEE80211BE */
#ifdef CONFIG_P2P
- if (elems.p2p) {
+ if (elems->p2p && ies && ies_len) {
wpabuf_free(sta->p2p_ie);
sta->p2p_ie = ieee802_11_vendor_ie_concat(ies, ies_len,
P2P_IE_VENDOR_TYPE);
@@ -3778,13 +3772,13 @@
}
#endif /* CONFIG_P2P */
- if ((hapd->conf->wpa & WPA_PROTO_RSN) && elems.rsn_ie) {
- wpa_ie = elems.rsn_ie;
- wpa_ie_len = elems.rsn_ie_len;
+ if ((hapd->conf->wpa & WPA_PROTO_RSN) && elems->rsn_ie) {
+ wpa_ie = elems->rsn_ie;
+ wpa_ie_len = elems->rsn_ie_len;
} else if ((hapd->conf->wpa & WPA_PROTO_WPA) &&
- elems.wpa_ie) {
- wpa_ie = elems.wpa_ie;
- wpa_ie_len = elems.wpa_ie_len;
+ elems->wpa_ie) {
+ wpa_ie = elems->wpa_ie;
+ wpa_ie_len = elems->wpa_ie_len;
} else {
wpa_ie = NULL;
wpa_ie_len = 0;
@@ -3792,7 +3786,7 @@
#ifdef CONFIG_WPS
sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS | WLAN_STA_WPS2);
- if (hapd->conf->wps_state && elems.wps_ie) {
+ if (hapd->conf->wps_state && elems->wps_ie && ies && ies_len) {
wpa_printf(MSG_DEBUG, "STA included WPS IE in (Re)Association "
"Request - assume WPS is used");
if (check_sa_query(hapd, sta, reassoc))
@@ -3846,10 +3840,12 @@
res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
hapd->iface->freq,
wpa_ie, wpa_ie_len,
- elems.rsnxe ? elems.rsnxe - 2 : NULL,
- elems.rsnxe ? elems.rsnxe_len + 2 : 0,
- elems.mdie, elems.mdie_len,
- elems.owe_dh, elems.owe_dh_len);
+ elems->rsnxe ? elems->rsnxe - 2 :
+ NULL,
+ elems->rsnxe ? elems->rsnxe_len + 2 :
+ 0,
+ elems->mdie, elems->mdie_len,
+ elems->owe_dh, elems->owe_dh_len);
resp = wpa_res_to_status_code(res);
if (resp != WLAN_STATUS_SUCCESS)
return resp;
@@ -3906,7 +3902,7 @@
if (hapd->conf->sae_pwe == SAE_PWE_BOTH &&
sta->auth_alg == WLAN_AUTH_SAE &&
sta->sae && !sta->sae->h2e &&
- ieee802_11_rsnx_capab_len(elems.rsnxe, elems.rsnxe_len,
+ ieee802_11_rsnx_capab_len(elems->rsnxe, elems->rsnxe_len,
WLAN_RSNX_CAPAB_SAE_H2E)) {
wpa_printf(MSG_INFO, "SAE: " MACSTR
" indicates support for SAE H2E, but did not use it",
@@ -3918,9 +3914,9 @@
#ifdef CONFIG_OWE
if ((hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE) &&
wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_OWE &&
- elems.owe_dh) {
- resp = owe_process_assoc_req(hapd, sta, elems.owe_dh,
- elems.owe_dh_len);
+ elems->owe_dh) {
+ resp = owe_process_assoc_req(hapd, sta, elems->owe_dh,
+ elems->owe_dh_len);
if (resp != WLAN_STATUS_SUCCESS)
return resp;
}
@@ -3934,7 +3930,7 @@
(hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_DPP) &&
hapd->conf->dpp_netaccesskey && sta->wpa_sm &&
wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_DPP &&
- elems.owe_dh) {
+ elems->owe_dh) {
sta->dpp_pfs = dpp_pfs_init(
wpabuf_head(hapd->conf->dpp_netaccesskey),
wpabuf_len(hapd->conf->dpp_netaccesskey));
@@ -3945,8 +3941,8 @@
goto pfs_fail;
}
- if (dpp_pfs_process(sta->dpp_pfs, elems.owe_dh,
- elems.owe_dh_len) < 0) {
+ if (dpp_pfs_process(sta->dpp_pfs, elems->owe_dh,
+ elems->owe_dh_len) < 0) {
dpp_pfs_free(sta->dpp_pfs);
sta->dpp_pfs = NULL;
return WLAN_STATUS_UNSPECIFIED_FAILURE;
@@ -3969,7 +3965,7 @@
}
#ifdef CONFIG_HS20
} else if (hapd->conf->osen) {
- if (elems.osen == NULL) {
+ if (!elems->osen) {
hostapd_logger(
hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_INFO,
@@ -3987,7 +3983,7 @@
return WLAN_STATUS_UNSPECIFIED_FAILURE;
}
if (wpa_validate_osen(hapd->wpa_auth, sta->wpa_sm,
- elems.osen - 2, elems.osen_len + 2) < 0)
+ elems->osen - 2, elems->osen_len + 2) < 0)
return WLAN_STATUS_INVALID_IE;
#endif /* CONFIG_HS20 */
} else
@@ -3999,12 +3995,12 @@
#ifdef CONFIG_HS20
wpabuf_free(sta->hs20_ie);
- if (elems.hs20 && elems.hs20_len > 4) {
+ if (elems->hs20 && elems->hs20_len > 4) {
int release;
- sta->hs20_ie = wpabuf_alloc_copy(elems.hs20 + 4,
- elems.hs20_len - 4);
- release = ((elems.hs20[4] >> 4) & 0x0f) + 1;
+ sta->hs20_ie = wpabuf_alloc_copy(elems->hs20 + 4,
+ elems->hs20_len - 4);
+ release = ((elems->hs20[4] >> 4) & 0x0f) + 1;
if (release >= 2 && !wpa_auth_uses_mfp(sta->wpa_sm) &&
hapd->conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
wpa_printf(MSG_DEBUG,
@@ -4017,10 +4013,10 @@
}
wpabuf_free(sta->roaming_consortium);
- if (elems.roaming_cons_sel)
+ if (elems->roaming_cons_sel)
sta->roaming_consortium = wpabuf_alloc_copy(
- elems.roaming_cons_sel + 4,
- elems.roaming_cons_sel_len - 4);
+ elems->roaming_cons_sel + 4,
+ elems->roaming_cons_sel_len - 4);
else
sta->roaming_consortium = NULL;
#endif /* CONFIG_HS20 */
@@ -4028,16 +4024,16 @@
#ifdef CONFIG_FST
wpabuf_free(sta->mb_ies);
if (hapd->iface->fst)
- sta->mb_ies = mb_ies_by_info(&elems.mb_ies);
+ sta->mb_ies = mb_ies_by_info(&elems->mb_ies);
else
sta->mb_ies = NULL;
#endif /* CONFIG_FST */
#ifdef CONFIG_MBO
- mbo_ap_check_sta_assoc(hapd, sta, &elems);
+ mbo_ap_check_sta_assoc(hapd, sta, elems);
if (hapd->conf->mbo_enabled && (hapd->conf->wpa & 2) &&
- elems.mbo && sta->cell_capa && !(sta->flags & WLAN_STA_MFP) &&
+ elems->mbo && sta->cell_capa && !(sta->flags & WLAN_STA_MFP) &&
hapd->conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
wpa_printf(MSG_INFO,
"MBO: Reject WPA2 association without PMF");
@@ -4067,7 +4063,7 @@
&tx_seg1_idx) < 0)
return WLAN_STATUS_UNSPECIFIED_FAILURE;
- res = ocv_verify_tx_params(elems.oci, elems.oci_len, &ci,
+ res = ocv_verify_tx_params(elems->oci, elems->oci_len, &ci,
tx_chanwidth, tx_seg1_idx);
if (wpa_auth_uses_ocv(sta->wpa_sm) == 2 &&
res == OCI_NOT_FOUND) {
@@ -4086,18 +4082,18 @@
}
#endif /* CONFIG_FILS && CONFIG_OCV */
- ap_copy_sta_supp_op_classes(sta, elems.supp_op_classes,
- elems.supp_op_classes_len);
+ ap_copy_sta_supp_op_classes(sta, elems->supp_op_classes,
+ elems->supp_op_classes_len);
if ((sta->capability & WLAN_CAPABILITY_RADIO_MEASUREMENT) &&
- elems.rrm_enabled &&
- elems.rrm_enabled_len >= sizeof(sta->rrm_enabled_capa))
- os_memcpy(sta->rrm_enabled_capa, elems.rrm_enabled,
+ elems->rrm_enabled &&
+ elems->rrm_enabled_len >= sizeof(sta->rrm_enabled_capa))
+ os_memcpy(sta->rrm_enabled_capa, elems->rrm_enabled,
sizeof(sta->rrm_enabled_capa));
- if (elems.power_capab) {
- sta->min_tx_power = elems.power_capab[0];
- sta->max_tx_power = elems.power_capab[1];
+ if (elems->power_capab) {
+ sta->min_tx_power = elems->power_capab[0];
+ sta->max_tx_power = elems->power_capab[1];
sta->power_capab = 1;
} else {
sta->power_capab = 0;
@@ -4107,6 +4103,22 @@
}
+static int check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
+ const u8 *ies, size_t ies_len, int reassoc)
+{
+ struct ieee802_11_elems elems;
+
+ if (ieee802_11_parse_elems(ies, ies_len, &elems, 1) == ParseFailed) {
+ hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
+ HOSTAPD_LEVEL_INFO,
+ "Station sent an invalid association request");
+ return WLAN_STATUS_UNSPECIFIED_FAILURE;
+ }
+
+ return __check_assoc_ies(hapd, sta, ies, ies_len, &elems, reassoc);
+}
+
+
static void send_deauth(struct hostapd_data *hapd, const u8 *addr,
u16 reason_code)
{
@@ -4266,6 +4278,8 @@
if (hapd->iconf->ieee80211be && !hapd->conf->disable_11be) {
buflen += hostapd_eid_eht_capab_len(hapd, IEEE80211_MODE_AP);
buflen += 3 + sizeof(struct ieee80211_eht_operation);
+ if (hapd->iconf->punct_bitmap)
+ buflen += EHT_OPER_DISABLED_SUBCHAN_BITMAP_SIZE;
}
#endif /* CONFIG_IEEE80211BE */
@@ -5330,10 +5344,10 @@
pos = &mgmt->u.action.u.public_action.action;
end = ((const u8 *) mgmt) + len;
- gas_query_ap_rx(hapd->gas, mgmt->sa,
- mgmt->u.action.category,
- pos, end - pos, freq);
- return 1;
+ if (gas_query_ap_rx(hapd->gas, mgmt->sa,
+ mgmt->u.action.category,
+ pos, end - pos, freq) == 0)
+ return 1;
}
#endif /* CONFIG_DPP */
if (hapd->public_action_cb) {
@@ -7015,4 +7029,73 @@
return eid;
}
+
+static void punct_update_legacy_bw_80(u8 bitmap, u8 pri_chan, u8 *seg0)
+{
+ u8 first_chan = *seg0 - 6, sec_chan;
+
+ switch (bitmap) {
+ case 0x6:
+ *seg0 = 0;
+ return;
+ case 0x8:
+ case 0x4:
+ case 0x2:
+ case 0x1:
+ case 0xC:
+ case 0x3:
+ if (pri_chan < *seg0)
+ *seg0 -= 4;
+ else
+ *seg0 += 4;
+ break;
+ }
+
+ if (pri_chan < *seg0)
+ sec_chan = pri_chan + 4;
+ else
+ sec_chan = pri_chan - 4;
+
+ if (bitmap & BIT((sec_chan - first_chan) / 4))
+ *seg0 = 0;
+}
+
+
+static void punct_update_legacy_bw_160(u8 bitmap, u8 pri,
+ enum oper_chan_width *width, u8 *seg0)
+{
+ if (pri < *seg0) {
+ *seg0 -= 8;
+ if (bitmap & 0x0F) {
+ *width = 0;
+ punct_update_legacy_bw_80(bitmap & 0xF, pri, seg0);
+ }
+ } else {
+ *seg0 += 8;
+ if (bitmap & 0xF0) {
+ *width = 0;
+ punct_update_legacy_bw_80((bitmap & 0xF0) >> 4, pri,
+ seg0);
+ }
+ }
+}
+
+
+void punct_update_legacy_bw(u16 bitmap, u8 pri, enum oper_chan_width *width,
+ u8 *seg0, u8 *seg1)
+{
+ if (*width == CONF_OPER_CHWIDTH_80MHZ && (bitmap & 0xF)) {
+ *width = CONF_OPER_CHWIDTH_USE_HT;
+ punct_update_legacy_bw_80(bitmap & 0xF, pri, seg0);
+ }
+
+ if (*width == CONF_OPER_CHWIDTH_160MHZ && (bitmap & 0xFF)) {
+ *width = CONF_OPER_CHWIDTH_80MHZ;
+ *seg1 = 0;
+ punct_update_legacy_bw_160(bitmap & 0xFF, pri, width, seg0);
+ }
+
+ /* TODO: 320 MHz */
+}
+
#endif /* CONFIG_NATIVE_WINDOWS */
diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h
index 5f443fc..1e4c843 100644
--- a/src/ap/ieee802_11.h
+++ b/src/ap/ieee802_11.h
@@ -18,6 +18,7 @@
struct ieee80211_mgmt;
struct radius_sta;
enum ieee80211_op_mode;
+enum oper_chan_width;
int ieee802_11_mgmt(struct hostapd_data *hapd, const u8 *buf, size_t len,
struct hostapd_frame_info *fi);
@@ -222,5 +223,7 @@
unsigned int frame_stype, u8 elem_count,
u8 **elem_offset,
const u8 *known_bss, size_t known_bss_len);
+void punct_update_legacy_bw(u16 bitmap, u8 pri_chan,
+ enum oper_chan_width *width, u8 *seg0, u8 *seg1);
#endif /* IEEE802_11_H */
diff --git a/src/ap/ieee802_11_eht.c b/src/ap/ieee802_11_eht.c
index caaadce..6ebe0f9 100644
--- a/src/ap/ieee802_11_eht.c
+++ b/src/ap/ieee802_11_eht.c
@@ -202,6 +202,9 @@
if (!hapd->iface->current_mode)
return eid;
+ if (hapd->iconf->punct_bitmap)
+ elen += EHT_OPER_DISABLED_SUBCHAN_BITMAP_SIZE;
+
*pos++ = WLAN_EID_EXTENSION;
*pos++ = 1 + elen;
*pos++ = WLAN_EID_EXT_EHT_OPERATION;
@@ -253,6 +256,12 @@
oper->oper_info.ccfs0 = seg0 ? seg0 : hapd->iconf->channel;
oper->oper_info.ccfs1 = seg1;
+ if (hapd->iconf->punct_bitmap) {
+ oper->oper_params |= EHT_OPER_DISABLED_SUBCHAN_BITMAP_PRESENT;
+ oper->oper_info.disabled_chan_bitmap =
+ host_to_le16(hapd->iconf->punct_bitmap);
+ }
+
return pos + elen;
}
diff --git a/src/ap/ieee802_11_he.c b/src/ap/ieee802_11_he.c
index 12273c3..548a448 100644
--- a/src/ap/ieee802_11_he.c
+++ b/src/ap/ieee802_11_he.c
@@ -219,10 +219,20 @@
pos += 6; /* skip the fixed part */
if (is_6ghz_op_class(hapd->iconf->op_class)) {
+ enum oper_chan_width oper_chwidth =
+ hostapd_get_oper_chwidth(hapd->iconf);
u8 seg0 = hapd->iconf->he_oper_centr_freq_seg0_idx;
u8 seg1 = hostapd_get_oper_centr_freq_seg1_idx(hapd->iconf);
u8 control;
+#ifdef CONFIG_IEEE80211BE
+ if (hapd->iconf->punct_bitmap) {
+ punct_update_legacy_bw(hapd->iconf->punct_bitmap,
+ hapd->iconf->channel,
+ &oper_chwidth, &seg0, &seg1);
+ }
+#endif /* CONFIG_IEEE80211BE */
+
if (!seg0)
seg0 = hapd->iconf->channel;
@@ -253,7 +263,7 @@
*pos++ = control;
/* Channel Center Freq Seg0/Seg1 */
- if (hapd->iconf->he_oper_chwidth == 2) {
+ if (oper_chwidth == 2) {
/*
* Seg 0 indicates the channel center frequency index of
* the 160 MHz channel.
diff --git a/src/ap/ieee802_11_vht.c b/src/ap/ieee802_11_vht.c
index 681b6d7..db615a3 100644
--- a/src/ap/ieee802_11_vht.c
+++ b/src/ap/ieee802_11_vht.c
@@ -75,6 +75,10 @@
{
struct ieee80211_vht_operation *oper;
u8 *pos = eid;
+ enum oper_chan_width oper_chwidth =
+ hostapd_get_oper_chwidth(hapd->iconf);
+ u8 seg0 = hapd->iconf->vht_oper_centr_freq_seg0_idx;
+ u8 seg1 = hapd->iconf->vht_oper_centr_freq_seg1_idx;
if (is_6ghz_op_class(hapd->iconf->op_class))
return eid;
@@ -85,18 +89,24 @@
oper = (struct ieee80211_vht_operation *) pos;
os_memset(oper, 0, sizeof(*oper));
+#ifdef CONFIG_IEEE80211BE
+ if (hapd->iconf->punct_bitmap) {
+ punct_update_legacy_bw(hapd->iconf->punct_bitmap,
+ hapd->iconf->channel,
+ &oper_chwidth, &seg0, &seg1);
+ }
+#endif /* CONFIG_IEEE80211BE */
+
/*
* center freq = 5 GHz + (5 * index)
* So index 42 gives center freq 5.210 GHz
* which is channel 42 in 5G band
*/
- oper->vht_op_info_chan_center_freq_seg0_idx =
- hapd->iconf->vht_oper_centr_freq_seg0_idx;
- oper->vht_op_info_chan_center_freq_seg1_idx =
- hapd->iconf->vht_oper_centr_freq_seg1_idx;
+ oper->vht_op_info_chan_center_freq_seg0_idx = seg0;
+ oper->vht_op_info_chan_center_freq_seg1_idx = seg1;
- oper->vht_op_info_chwidth = hapd->iconf->vht_oper_chwidth;
- if (hapd->iconf->vht_oper_chwidth == CONF_OPER_CHWIDTH_160MHZ) {
+ oper->vht_op_info_chwidth = oper_chwidth;
+ if (oper_chwidth == CONF_OPER_CHWIDTH_160MHZ) {
/*
* Convert 160 MHz channel width to new style as interop
* workaround.
@@ -109,8 +119,7 @@
oper->vht_op_info_chan_center_freq_seg0_idx -= 8;
else
oper->vht_op_info_chan_center_freq_seg0_idx += 8;
- } else if (hapd->iconf->vht_oper_chwidth ==
- CONF_OPER_CHWIDTH_80P80MHZ) {
+ } else if (oper_chwidth == CONF_OPER_CHWIDTH_80P80MHZ) {
/*
* Convert 80+80 MHz channel width to new style as interop
* workaround.
diff --git a/src/ap/wnm_ap.c b/src/ap/wnm_ap.c
index 23a352c..153ee40 100644
--- a/src/ap/wnm_ap.c
+++ b/src/ap/wnm_ap.c
@@ -643,6 +643,133 @@
}
+
+static const char * wnm_event_type2str(enum wnm_event_report_type wtype)
+{
+#define W2S(wtype) case WNM_EVENT_TYPE_ ## wtype: return #wtype;
+ switch (wtype) {
+ W2S(TRANSITION)
+ W2S(RSNA)
+ W2S(P2P_LINK)
+ W2S(WNM_LOG)
+ W2S(BSS_COLOR_COLLISION)
+ W2S(BSS_COLOR_IN_USE)
+ }
+ return "UNKNOWN";
+#undef W2S
+}
+
+
+static void ieee802_11_rx_wnm_event_report(struct hostapd_data *hapd,
+ const u8 *addr, const u8 *buf,
+ size_t len)
+{
+ struct sta_info *sta;
+ u8 dialog_token;
+ struct wnm_event_report_element *report_ie;
+ const u8 *pos = buf, *end = buf + len;
+ const size_t fixed_field_len = 3; /* Event Token/Type/Report Status */
+#ifdef CONFIG_IEEE80211AX
+ const size_t tsf_len = 8;
+ u8 color;
+ u64 bitmap;
+#endif /* CONFIG_IEEE80211AX */
+
+ if (end - pos < 1 + 2) {
+ wpa_printf(MSG_DEBUG,
+ "WNM: Ignore too short WNM Event Report frame from "
+ MACSTR, MAC2STR(addr));
+ return;
+ }
+
+ dialog_token = *pos++;
+ report_ie = (struct wnm_event_report_element *) pos;
+
+ if (end - pos < 2 + report_ie->len ||
+ report_ie->len < fixed_field_len) {
+ wpa_printf(MSG_DEBUG,
+ "WNM: Ignore truncated WNM Event Report frame from "
+ MACSTR, MAC2STR(addr));
+ return;
+ }
+
+ if (report_ie->eid != WLAN_EID_EVENT_REPORT ||
+ report_ie->status != WNM_STATUS_SUCCESSFUL)
+ return;
+
+ wpa_printf(MSG_DEBUG, "WNM: Received WNM Event Report frame from "
+ MACSTR " dialog_token=%u event_token=%u type=%d (%s)",
+ MAC2STR(addr), dialog_token, report_ie->token,
+ report_ie->type, wnm_event_type2str(report_ie->type));
+
+ pos += 2 + fixed_field_len;
+ wpa_hexdump(MSG_MSGDUMP, "WNM: Event Report", pos, end - pos);
+
+ sta = ap_get_sta(hapd, addr);
+ if (!sta || !(sta->flags & WLAN_STA_ASSOC)) {
+ wpa_printf(MSG_DEBUG, "Station " MACSTR
+ " not found for received WNM Event Report",
+ MAC2STR(addr));
+ return;
+ }
+
+ switch (report_ie->type) {
+#ifdef CONFIG_IEEE80211AX
+ case WNM_EVENT_TYPE_BSS_COLOR_COLLISION:
+ if (!hapd->iconf->ieee80211ax || hapd->conf->disable_11ax)
+ return;
+ if (report_ie->len <
+ fixed_field_len + tsf_len + 8) {
+ wpa_printf(MSG_DEBUG,
+ "WNM: Too short BSS color collision event report from "
+ MACSTR, MAC2STR(addr));
+ return;
+ }
+ bitmap = WPA_GET_LE64(report_ie->u.bss_color_collision.color_bitmap);
+ wpa_printf(MSG_DEBUG,
+ "WNM: BSS color collision bitmap 0x%llx reported by "
+ MACSTR, (unsigned long long) bitmap, MAC2STR(addr));
+ hostapd_switch_color(hapd->iface->bss[0], bitmap);
+ break;
+ case WNM_EVENT_TYPE_BSS_COLOR_IN_USE:
+ if (!hapd->iconf->ieee80211ax || hapd->conf->disable_11ax)
+ return;
+ if (report_ie->len < fixed_field_len + tsf_len + 1) {
+ wpa_printf(MSG_DEBUG,
+ "WNM: Too short BSS color in use event report from "
+ MACSTR, MAC2STR(addr));
+ return;
+ }
+ color = report_ie->u.bss_color_in_use.color;
+ if (color > 63) {
+ wpa_printf(MSG_DEBUG,
+ "WNM: Invalid BSS color %u report from "
+ MACSTR, color, MAC2STR(addr));
+ return;
+ }
+ if (color == 0) {
+ wpa_printf(MSG_DEBUG,
+ "WNM: BSS color use report canceled by "
+ MACSTR, MAC2STR(addr));
+ /* TODO: Clear stored color from the collision bitmap
+ * if there are no other users for it. */
+ return;
+ }
+ wpa_printf(MSG_DEBUG, "WNM: BSS color %u use report by "
+ MACSTR, color, MAC2STR(addr));
+ hapd->color_collision_bitmap |= 1ULL << color;
+ break;
+#endif /* CONFIG_IEEE80211AX */
+ default:
+ wpa_printf(MSG_DEBUG,
+ "WNM Event Report type=%d (%s) not supported",
+ report_ie->type,
+ wnm_event_type2str(report_ie->type));
+ break;
+ }
+}
+
+
int ieee802_11_rx_wnm_action_ap(struct hostapd_data *hapd,
const struct ieee80211_mgmt *mgmt, size_t len)
{
@@ -658,6 +785,10 @@
plen = len - IEEE80211_HDRLEN - 2;
switch (action) {
+ case WNM_EVENT_REPORT:
+ ieee802_11_rx_wnm_event_report(hapd, mgmt->sa, payload,
+ plen);
+ return 0;
case WNM_BSS_TRANS_MGMT_QUERY:
ieee802_11_rx_bss_trans_mgmt_query(hapd, mgmt->sa, payload,
plen);
diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c
index 7aff64f..635a74a 100644
--- a/src/ap/wpa_auth.c
+++ b/src/ap/wpa_auth.c
@@ -36,7 +36,7 @@
#define STATE_MACHINE_DATA struct wpa_state_machine
#define STATE_MACHINE_DEBUG_PREFIX "WPA"
-#define STATE_MACHINE_ADDR sm->addr
+#define STATE_MACHINE_ADDR wpa_auth_get_spa(sm)
static void wpa_send_eapol_timeout(void *eloop_ctx, void *timeout_ctx);
@@ -59,7 +59,9 @@
struct wpa_group *group);
static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce,
const u8 *pmk, unsigned int pmk_len,
- struct wpa_ptk *ptk, int force_sha256);
+ struct wpa_ptk *ptk, int force_sha256,
+ u8 *pmk_r0, u8 *pmk_r1, u8 *pmk_r0_name,
+ size_t *key_len);
static void wpa_group_free(struct wpa_authenticator *wpa_auth,
struct wpa_group *group);
static void wpa_group_get(struct wpa_authenticator *wpa_auth,
@@ -80,6 +82,18 @@
static const int dot11RSNAConfigSATimeout = 60;
+static const u8 * wpa_auth_get_aa(const struct wpa_state_machine *sm)
+{
+ return sm->wpa_auth->addr;
+}
+
+
+static const u8 * wpa_auth_get_spa(const struct wpa_state_machine *sm)
+{
+ return sm->addr;
+}
+
+
static inline int wpa_auth_mic_failure_report(
struct wpa_authenticator *wpa_auth, const u8 *addr)
{
@@ -253,13 +267,14 @@
}
-void wpa_auth_remove_ptksa(struct wpa_authenticator *wpa_auth,
- const u8 *addr, int cipher)
+static void wpa_auth_remove_ptksa(struct wpa_authenticator *wpa_auth,
+ const u8 *addr, int cipher)
{
if (wpa_auth->cb->clear_ptksa)
wpa_auth->cb->clear_ptksa(wpa_auth->cb_ctx, addr, cipher);
}
+
void wpa_auth_logger(struct wpa_authenticator *wpa_auth, const u8 *addr,
logger_level level, const char *txt)
{
@@ -378,7 +393,8 @@
struct wpa_authenticator *wpa_auth = eloop_ctx;
struct wpa_state_machine *sm = timeout_ctx;
- wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, "rekeying PTK");
+ wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
+ "rekeying PTK");
wpa_request_new_ptk(sm);
wpa_sm_step(sm);
}
@@ -388,7 +404,8 @@
{
if (sm && sm->wpa_auth->conf.wpa_ptk_rekey) {
wpa_printf(MSG_DEBUG, "WPA: Start PTK rekeying timer for "
- MACSTR " (%d seconds)", MAC2STR(sm->addr),
+ MACSTR " (%d seconds)",
+ MAC2STR(wpa_auth_get_spa(sm)),
sm->wpa_auth->conf.wpa_ptk_rekey);
eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm);
eloop_register_timeout(sm->wpa_auth->conf.wpa_ptk_rekey, 0,
@@ -695,7 +712,7 @@
#ifdef CONFIG_IEEE80211R_AP
if (sm->ft_completed) {
- wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
+ wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
"FT authentication already completed - do not start 4-way handshake");
/* Go to PTKINITDONE state to allow GTK rekeying */
sm->wpa_ptk_state = WPA_PTK_PTKINITDONE;
@@ -706,7 +723,7 @@
#ifdef CONFIG_FILS
if (sm->fils_completed) {
- wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
+ wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
"FILS authentication already completed - do not start 4-way handshake");
/* Go to PTKINITDONE state to allow GTK rekeying */
sm->wpa_ptk_state = WPA_PTK_PTKINITDONE;
@@ -721,7 +738,7 @@
return wpa_sm_step(sm);
}
- wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
+ wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
"start authentication");
sm->started = 1;
@@ -755,7 +772,8 @@
MACSTR " (bit %u)",
sm->ip_addr[0], sm->ip_addr[1],
sm->ip_addr[2], sm->ip_addr[3],
- MAC2STR(sm->addr), sm->ip_addr_bit);
+ MAC2STR(wpa_auth_get_spa(sm)),
+ sm->ip_addr_bit);
bitfield_clear(sm->wpa_auth->ip_pool, sm->ip_addr_bit);
}
#endif /* CONFIG_P2P */
@@ -787,7 +805,7 @@
wpa_auth = sm->wpa_auth;
if (wpa_auth->conf.wpa_strict_rekey && sm->has_GTK) {
- wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
+ wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
"strict rekeying - force GTK rekey since STA is leaving");
if (eloop_deplete_timeout(0, 500000, wpa_rekey_gtk,
wpa_auth, NULL) == -1)
@@ -807,7 +825,7 @@
* Freeing will be completed in the end of wpa_sm_step(). */
wpa_printf(MSG_DEBUG,
"WPA: Registering pending STA state machine deinit for "
- MACSTR, MAC2STR(sm->addr));
+ MACSTR, MAC2STR(wpa_auth_get_spa(sm)));
sm->pending_deinit = 1;
} else
wpa_free_sta_sm(sm);
@@ -822,7 +840,7 @@
if (!sm->use_ext_key_id && sm->wpa_auth->conf.wpa_deny_ptk0_rekey) {
wpa_printf(MSG_INFO,
"WPA: PTK0 rekey not allowed, disconnect " MACSTR,
- MAC2STR(sm->addr));
+ MAC2STR(wpa_auth_get_spa(sm)));
sm->Disconnect = true;
/* Try to encourage the STA to reconnect */
sm->disconnect_reason =
@@ -920,18 +938,19 @@
struct wpa_state_machine *sm, int group)
{
/* Supplicant reported a Michael MIC error */
- wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
+ wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
"received EAPOL-Key Error Request (STA detected Michael MIC failure (group=%d))",
group);
if (group && wpa_auth->conf.wpa_group != WPA_CIPHER_TKIP) {
- wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
+ wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
"ignore Michael MIC failure report since group cipher is not TKIP");
} else if (!group && sm->pairwise != WPA_CIPHER_TKIP) {
- wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
+ wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
"ignore Michael MIC failure report since pairwise cipher is not TKIP");
} else {
- if (wpa_auth_mic_failure_report(wpa_auth, sm->addr) > 0)
+ if (wpa_auth_mic_failure_report(wpa_auth,
+ wpa_auth_get_spa(sm)) > 0)
return 1; /* STA entry was removed */
sm->dot11RSNAStatsTKIPRemoteMICFailures++;
wpa_auth->dot11RSNAStatsTKIPRemoteMICFailures++;
@@ -954,6 +973,10 @@
const u8 *pmk = NULL;
size_t pmk_len;
int vlan_id = 0;
+ u8 pmk_r0[PMK_LEN_MAX], pmk_r0_name[WPA_PMK_NAME_LEN];
+ u8 pmk_r1[PMK_LEN_MAX];
+ size_t key_len;
+ int ret = -1;
os_memset(&PTK, 0, sizeof(PTK));
for (;;) {
@@ -975,8 +998,8 @@
pmk_len = sm->pmk_len;
}
- if (wpa_derive_ptk(sm, sm->alt_SNonce, pmk, pmk_len, &PTK, 0) <
- 0)
+ if (wpa_derive_ptk(sm, sm->alt_SNonce, pmk, pmk_len, &PTK, 0,
+ pmk_r0, pmk_r1, pmk_r0_name, &key_len) < 0)
break;
if (wpa_verify_key_mic(sm->wpa_key_mgmt, pmk_len, &PTK,
@@ -997,7 +1020,7 @@
if (!ok) {
wpa_printf(MSG_DEBUG,
"WPA: Earlier SNonce did not result in matching MIC");
- return -1;
+ goto fail;
}
wpa_printf(MSG_DEBUG,
@@ -1006,14 +1029,26 @@
if (vlan_id && wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) &&
wpa_auth_update_vlan(sm->wpa_auth, sm->addr, vlan_id) < 0)
- return -1;
+ goto fail;
+
+#ifdef CONFIG_IEEE80211R_AP
+ if (wpa_key_mgmt_ft(sm->wpa_key_mgmt) && !sm->ft_completed) {
+ wpa_printf(MSG_DEBUG, "FT: Store PMK-R0/PMK-R1");
+ wpa_auth_ft_store_keys(sm, pmk_r0, pmk_r1, pmk_r0_name,
+ key_len);
+ }
+#endif /* CONFIG_IEEE80211R_AP */
os_memcpy(sm->SNonce, sm->alt_SNonce, WPA_NONCE_LEN);
os_memcpy(&sm->PTK, &PTK, sizeof(PTK));
forced_memzero(&PTK, sizeof(PTK));
sm->PTK_valid = true;
- return 0;
+ ret = 0;
+fail:
+ forced_memzero(pmk_r0, sizeof(pmk_r0));
+ forced_memzero(pmk_r1, sizeof(pmk_r1));
+ return ret;
}
@@ -1063,7 +1098,7 @@
key_data_length = WPA_GET_BE16(mic + mic_len);
wpa_printf(MSG_DEBUG, "WPA: Received EAPOL-Key from " MACSTR
" key_info=0x%x type=%u mic_len=%zu key_data_length=%u",
- MAC2STR(sm->addr), key_info, key->type,
+ MAC2STR(wpa_auth_get_spa(sm)), key_info, key->type,
mic_len, key_data_length);
wpa_hexdump(MSG_MSGDUMP,
"WPA: EAPOL-Key header (ending before Key MIC)",
@@ -1138,7 +1173,7 @@
if (wpa_use_cmac(sm->wpa_key_mgmt) &&
!wpa_use_akm_defined(sm->wpa_key_mgmt) &&
ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) {
- wpa_auth_logger(wpa_auth, sm->addr,
+ wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
LOGGER_WARNING,
"advertised support for AES-128-CMAC, but did not use it");
return;
@@ -1147,7 +1182,7 @@
if (!wpa_use_cmac(sm->wpa_key_mgmt) &&
!wpa_use_akm_defined(sm->wpa_key_mgmt) &&
ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
- wpa_auth_logger(wpa_auth, sm->addr,
+ wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
LOGGER_WARNING,
"did not use HMAC-SHA1-AES with CCMP/GCMP");
return;
@@ -1156,7 +1191,8 @@
if (wpa_use_akm_defined(sm->wpa_key_mgmt) &&
ver != WPA_KEY_INFO_TYPE_AKM_DEFINED) {
- wpa_auth_logger(wpa_auth, sm->addr, LOGGER_WARNING,
+ wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
+ LOGGER_WARNING,
"did not use EAPOL-Key descriptor version 0 as required for AKM-defined cases");
return;
}
@@ -1166,7 +1202,8 @@
if (sm->req_replay_counter_used &&
os_memcmp(key->replay_counter, sm->req_replay_counter,
WPA_REPLAY_COUNTER_LEN) <= 0) {
- wpa_auth_logger(wpa_auth, sm->addr, LOGGER_WARNING,
+ wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
+ LOGGER_WARNING,
"received EAPOL-Key request with replayed counter");
return;
}
@@ -1189,7 +1226,8 @@
* pending requests, so allow the SNonce to be updated
* even if we have already sent out EAPOL-Key 3/4.
*/
- wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
+ wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm),
+ LOGGER_DEBUG,
"Process SNonce update from STA based on retransmitted EAPOL-Key 1/4");
sm->update_snonce = 1;
os_memcpy(sm->alt_SNonce, sm->SNonce, WPA_NONCE_LEN);
@@ -1209,7 +1247,8 @@
* there was two EAPOL-Key 2/4 messages and they had
* different SNonce values.
*/
- wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
+ wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm),
+ LOGGER_DEBUG,
"Try to process received EAPOL-Key 4/4 based on old Replay Counter and SNonce from an earlier EAPOL-Key 1/4");
goto continue_processing;
}
@@ -1218,11 +1257,13 @@
wpa_replay_counter_valid(sm->prev_key_replay,
key->replay_counter) &&
sm->wpa_ptk_state == WPA_PTK_PTKINITNEGOTIATING) {
- wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
+ wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm),
+ LOGGER_DEBUG,
"ignore retransmitted EAPOL-Key %s - SNonce did not change",
msgtxt);
} else {
- wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
+ wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm),
+ LOGGER_DEBUG,
"received EAPOL-Key %s with unexpected replay counter",
msgtxt);
}
@@ -1242,7 +1283,7 @@
#ifdef CONFIG_FILS
if (sm->wpa == WPA_VERSION_WPA2 && mic_len == 0 &&
!(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
- wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
+ wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
"WPA: Encr Key Data bit not set even though AEAD cipher is supposed to be used - drop frame");
return;
}
@@ -1254,7 +1295,8 @@
sm->wpa_ptk_state != WPA_PTK_PTKCALCNEGOTIATING &&
(!sm->update_snonce ||
sm->wpa_ptk_state != WPA_PTK_PTKINITNEGOTIATING)) {
- wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
+ wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm),
+ LOGGER_INFO,
"received EAPOL-Key msg 2/4 in invalid state (%d) - dropped",
sm->wpa_ptk_state);
return;
@@ -1281,7 +1323,8 @@
case PAIRWISE_4:
if (sm->wpa_ptk_state != WPA_PTK_PTKINITNEGOTIATING ||
!sm->PTK_valid) {
- wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
+ wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm),
+ LOGGER_INFO,
"received EAPOL-Key msg 4/4 in invalid state (%d) - dropped",
sm->wpa_ptk_state);
return;
@@ -1290,7 +1333,8 @@
case GROUP_2:
if (sm->wpa_ptk_group_state != WPA_PTK_GROUP_REKEYNEGOTIATING
|| !sm->PTK_valid) {
- wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
+ wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm),
+ LOGGER_INFO,
"received EAPOL-Key msg 2/2 in invalid state (%d) - dropped",
sm->wpa_ptk_group_state);
return;
@@ -1300,18 +1344,18 @@
break;
}
- wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
+ wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
"received EAPOL-Key frame (%s)", msgtxt);
if (key_info & WPA_KEY_INFO_ACK) {
- wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
+ wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
"received invalid EAPOL-Key: Key Ack set");
return;
}
if (!wpa_key_mgmt_fils(sm->wpa_key_mgmt) &&
!(key_info & WPA_KEY_INFO_MIC)) {
- wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
+ wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
"received invalid EAPOL-Key: Key MIC not set");
return;
}
@@ -1319,7 +1363,7 @@
#ifdef CONFIG_FILS
if (wpa_key_mgmt_fils(sm->wpa_key_mgmt) &&
(key_info & WPA_KEY_INFO_MIC)) {
- wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
+ wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
"received invalid EAPOL-Key: Key MIC set");
return;
}
@@ -1332,7 +1376,8 @@
data, data_len) &&
(msg != PAIRWISE_4 || !sm->alt_snonce_valid ||
wpa_try_alt_snonce(sm, data, data_len))) {
- wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
+ wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
+ LOGGER_INFO,
"received EAPOL-Key with invalid MIC");
#ifdef TEST_FUZZ
wpa_printf(MSG_INFO,
@@ -1345,7 +1390,8 @@
if (!mic_len &&
wpa_aead_decrypt(sm, &sm->PTK, data, data_len,
&key_data_length) < 0) {
- wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
+ wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
+ LOGGER_INFO,
"received EAPOL-Key with invalid MIC");
#ifdef TEST_FUZZ
wpa_printf(MSG_INFO,
@@ -1369,7 +1415,8 @@
os_memcpy(sm->req_replay_counter, key->replay_counter,
WPA_REPLAY_COUNTER_LEN);
} else {
- wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
+ wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
+ LOGGER_INFO,
"received EAPOL-Key request with invalid MIC");
return;
}
@@ -1385,7 +1432,8 @@
!(key_info & WPA_KEY_INFO_KEY_TYPE)) > 0)
return; /* STA entry was removed */
} else if (key_info & WPA_KEY_INFO_KEY_TYPE) {
- wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
+ wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
+ LOGGER_INFO,
"received EAPOL-Key Request for new 4-Way Handshake");
wpa_request_new_ptk(sm);
} else if (key_data_length > 0 &&
@@ -1393,7 +1441,8 @@
&kde) == 0 &&
kde.mac_addr) {
} else {
- wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
+ wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
+ LOGGER_INFO,
"received EAPOL-Key Request for GTK rekeying");
eloop_cancel_timeout(wpa_rekey_gtk, wpa_auth, NULL);
if (wpa_auth_gtk_rekey_in_process(wpa_auth))
@@ -1504,7 +1553,8 @@
}
sm->pending_1_of_4_timeout = 0;
- wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, "EAPOL-Key timeout");
+ wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
+ "EAPOL-Key timeout");
sm->TimeoutEvt = true;
wpa_sm_step(sm);
}
@@ -1696,7 +1746,8 @@
if (key_info & WPA_KEY_INFO_MIC) {
if (!sm->PTK_valid || !mic_len) {
- wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
+ wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
+ LOGGER_DEBUG,
"PTK not valid when sending EAPOL-Key frame");
os_free(hdr);
return;
@@ -1712,7 +1763,8 @@
if (!pairwise &&
conf->corrupt_gtk_rekey_mic_probability > 0.0 &&
drand48() < conf->corrupt_gtk_rekey_mic_probability) {
- wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
+ wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
+ LOGGER_INFO,
"Corrupting group EAPOL-Key Key MIC");
key_mic[0]++;
}
@@ -1842,7 +1894,7 @@
if (!sm)
return -1;
- wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
+ wpa_auth_vlogger(sm->wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
"event %d notification", event);
switch (event) {
@@ -1902,7 +1954,7 @@
sm->wpa_auth->conf.wpa_deny_ptk0_rekey) {
wpa_printf(MSG_INFO,
"WPA: PTK0 rekey not allowed, disconnect "
- MACSTR, MAC2STR(sm->addr));
+ MACSTR, MAC2STR(wpa_auth_get_spa(sm)));
sm->Disconnect = true;
/* Try to encourage the STA to reconnect */
sm->disconnect_reason =
@@ -2149,7 +2201,8 @@
sm->disconnect_reason = WLAN_REASON_INVALID_PMKID;
return;
#endif /* CONFIG_DPP */
- } else if (wpa_auth_get_msk(sm->wpa_auth, sm->addr, msk, &len) == 0) {
+ } else if (wpa_auth_get_msk(sm->wpa_auth, wpa_auth_get_spa(sm),
+ msk, &len) == 0) {
unsigned int pmk_len;
if (wpa_key_mgmt_sha384(sm->wpa_key_mgmt))
@@ -2257,7 +2310,7 @@
return;
}
- wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
+ wpa_auth_logger(sm->wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
"sending 1/4 msg of 4-Way Handshake");
/*
* For infrastructure BSS cases, it is better for the AP not to include
@@ -2336,8 +2389,10 @@
* Calculate PMKID since no PMKSA cache entry was
* available with pre-calculated PMKID.
*/
- rsn_pmkid(sm->PMK, sm->pmk_len, sm->wpa_auth->addr,
- sm->addr, &pmkid[2 + RSN_SELECTOR_LEN],
+ rsn_pmkid(sm->PMK, sm->pmk_len,
+ wpa_auth_get_aa(sm),
+ wpa_auth_get_spa(sm),
+ &pmkid[2 + RSN_SELECTOR_LEN],
sm->wpa_key_mgmt);
wpa_hexdump(MSG_DEBUG,
"RSN: Message 1/4 PMKID derived from PMK",
@@ -2356,7 +2411,9 @@
static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce,
const u8 *pmk, unsigned int pmk_len,
- struct wpa_ptk *ptk, int force_sha256)
+ struct wpa_ptk *ptk, int force_sha256,
+ u8 *pmk_r0, u8 *pmk_r1, u8 *pmk_r0_name,
+ size_t *key_len)
{
const u8 *z = NULL;
size_t z_len = 0, kdk_len;
@@ -2377,12 +2434,15 @@
ret = wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->pmk_r1_len,
sm->SNonce, sm->ANonce,
- sm->addr, sm->wpa_auth->addr,
+ wpa_auth_get_spa(sm),
+ wpa_auth_get_aa(sm),
sm->pmk_r1_name, ptk,
ptk_name, sm->wpa_key_mgmt,
sm->pairwise, kdk_len);
} else {
- ret = wpa_auth_derive_ptk_ft(sm, ptk);
+ ret = wpa_auth_derive_ptk_ft(sm, ptk, pmk_r0, pmk_r1,
+ pmk_r0_name, key_len,
+ kdk_len);
}
if (ret) {
wpa_printf(MSG_ERROR, "FT: PTK derivation failed");
@@ -2416,9 +2476,9 @@
if (force_sha256)
akmp |= WPA_KEY_MGMT_PSK_SHA256;
ret = wpa_pmk_to_ptk(pmk, pmk_len, "Pairwise key expansion",
- sm->wpa_auth->addr, sm->addr, sm->ANonce,
- snonce, ptk, akmp, sm->pairwise, z, z_len,
- kdk_len);
+ wpa_auth_get_aa(sm), wpa_auth_get_spa(sm),
+ sm->ANonce, snonce, ptk, akmp,
+ sm->pairwise, z, z_len, kdk_len);
if (ret) {
wpa_printf(MSG_DEBUG,
"WPA: PTK derivation failed");
@@ -2459,7 +2519,8 @@
else
kdk_len = 0;
- res = fils_pmk_to_ptk(pmk, pmk_len, sm->addr, sm->wpa_auth->addr,
+ res = fils_pmk_to_ptk(pmk, pmk_len, wpa_auth_get_spa(sm),
+ wpa_auth_get_aa(sm),
snonce, anonce, dhss, dhss_len,
&sm->PTK, ick, &ick_len,
sm->wpa_key_mgmt, sm->pairwise,
@@ -2493,7 +2554,7 @@
conf->mobility_domain,
conf->r0_key_holder,
conf->r0_key_holder_len,
- sm->addr, pmk_r0, pmk_r0_name,
+ wpa_auth_get_spa(sm), pmk_r0, pmk_r0_name,
sm->wpa_key_mgmt) < 0)
return -1;
@@ -2501,7 +2562,8 @@
forced_memzero(fils_ft, sizeof(fils_ft));
res = wpa_derive_pmk_r1_name(pmk_r0_name, conf->r1_key_holder,
- sm->addr, sm->pmk_r1_name,
+ wpa_auth_get_spa(sm),
+ sm->pmk_r1_name,
fils_ft_len);
forced_memzero(pmk_r0, PMK_LEN_MAX);
if (res < 0)
@@ -2513,7 +2575,8 @@
#endif /* CONFIG_IEEE80211R_AP */
res = fils_key_auth_sk(ick, ick_len, snonce, anonce,
- sm->addr, sm->wpa_auth->addr,
+ wpa_auth_get_spa(sm),
+ wpa_auth_get_aa(sm),
g_sta ? wpabuf_head(g_sta) : NULL,
g_sta ? wpabuf_len(g_sta) : 0,
g_ap ? wpabuf_head(g_ap) : NULL,
@@ -2548,7 +2611,7 @@
key_data_len = WPA_GET_BE16(pos);
if (key_data_len < AES_BLOCK_SIZE ||
key_data_len > buf_len - sizeof(*hdr) - sizeof(*key) - 2) {
- wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_INFO,
+ wpa_auth_logger(sm->wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
"No room for AES-SIV data in the frame");
return -1;
}
@@ -2564,7 +2627,7 @@
aad_len[0] = pos - buf;
if (aes_siv_decrypt(ptk->kek, ptk->kek_len, pos, key_data_len,
1, aad, aad_len, tmp) < 0) {
- wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_INFO,
+ wpa_auth_logger(sm->wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
"Invalid AES-SIV data in the frame");
bin_clear_free(tmp, key_data_len);
return -1;
@@ -3067,6 +3130,9 @@
struct wpa_eapol_ie_parse kde;
int vlan_id = 0;
int owe_ptk_workaround = !!wpa_auth->conf.owe_ptk_workaround;
+ u8 pmk_r0[PMK_LEN_MAX], pmk_r0_name[WPA_PMK_NAME_LEN];
+ u8 pmk_r1[PMK_LEN_MAX];
+ size_t key_len;
SM_ENTRY_MA(WPA_PTK, PTKCALCNEGOTIATING, wpa_ptk);
sm->EAPOLKeyReceived = false;
@@ -3105,7 +3171,8 @@
}
if (wpa_derive_ptk(sm, sm->SNonce, pmk, pmk_len, &PTK,
- owe_ptk_workaround == 2) < 0)
+ owe_ptk_workaround == 2, pmk_r0, pmk_r1,
+ pmk_r0_name, &key_len) < 0)
break;
if (mic_len &&
@@ -3154,15 +3221,16 @@
sm->last_rx_eapol_key,
sm->last_rx_eapol_key_len);
sm->waiting_radius_psk = 1;
- return;
+ goto out;
}
if (!ok) {
- wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
+ wpa_auth_logger(sm->wpa_auth, wpa_auth_get_spa(sm),
+ LOGGER_DEBUG,
"invalid MIC in msg 2/4 of 4-Way Handshake");
if (psk_found)
wpa_auth_psk_failure_report(sm->wpa_auth, sm->addr);
- return;
+ goto out;
}
/*
@@ -3176,12 +3244,12 @@
key_data_length = WPA_GET_BE16(mic + mic_len);
if (key_data_length > sm->last_rx_eapol_key_len - sizeof(*hdr) -
sizeof(*key) - mic_len - 2)
- return;
+ goto out;
if (wpa_parse_kde_ies(key_data, key_data_length, &kde) < 0) {
- wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
+ wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
"received EAPOL-Key msg 2/4 with invalid Key Data contents");
- return;
+ goto out;
}
if (kde.rsn_ie) {
eapol_key_ie = kde.rsn_ie;
@@ -3197,7 +3265,7 @@
if (!sm->wpa_ie ||
wpa_compare_rsn_ie(ft, sm->wpa_ie, sm->wpa_ie_len,
eapol_key_ie, eapol_key_ie_len)) {
- wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
+ wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
"WPA IE from (Re)AssocReq did not match with msg 2/4");
if (sm->wpa_ie) {
wpa_hexdump(MSG_DEBUG, "WPA IE in AssocReq",
@@ -3208,14 +3276,14 @@
/* MLME-DEAUTHENTICATE.request */
wpa_sta_disconnect(wpa_auth, sm->addr,
WLAN_REASON_PREV_AUTH_NOT_VALID);
- return;
+ goto out;
}
if ((!sm->rsnxe && kde.rsnxe) ||
(sm->rsnxe && !kde.rsnxe) ||
(sm->rsnxe && kde.rsnxe &&
(sm->rsnxe_len != kde.rsnxe_len ||
os_memcmp(sm->rsnxe, kde.rsnxe, sm->rsnxe_len) != 0))) {
- wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
+ wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
"RSNXE from (Re)AssocReq did not match the one in EAPOL-Key msg 2/4");
wpa_hexdump(MSG_DEBUG, "RSNXE in AssocReq",
sm->rsnxe, sm->rsnxe_len);
@@ -3224,7 +3292,7 @@
/* MLME-DEAUTHENTICATE.request */
wpa_sta_disconnect(wpa_auth, sm->addr,
WLAN_REASON_PREV_AUTH_NOT_VALID);
- return;
+ goto out;
}
#ifdef CONFIG_OCV
if (wpa_auth_uses_ocv(sm)) {
@@ -3234,33 +3302,37 @@
enum oci_verify_result res;
if (wpa_channel_info(wpa_auth, &ci) != 0) {
- wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
+ wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
+ LOGGER_INFO,
"Failed to get channel info to validate received OCI in EAPOL-Key 2/4");
- return;
+ goto out;
}
if (get_sta_tx_parameters(sm,
channel_width_to_int(ci.chanwidth),
ci.seg1_idx, &tx_chanwidth,
&tx_seg1_idx) < 0)
- return;
+ goto out;
res = ocv_verify_tx_params(kde.oci, kde.oci_len, &ci,
tx_chanwidth, tx_seg1_idx);
if (wpa_auth_uses_ocv(sm) == 2 && res == OCI_NOT_FOUND) {
/* Work around misbehaving STAs */
- wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
+ wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm),
+ LOGGER_INFO,
"Disable OCV with a STA that does not send OCI");
wpa_auth_set_ocv(sm, 0);
} else if (res != OCI_SUCCESS) {
- wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
+ wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm),
+ LOGGER_INFO,
"OCV failed: %s", ocv_errorstr);
if (wpa_auth->conf.msg_ctx)
wpa_msg(wpa_auth->conf.msg_ctx, MSG_INFO,
OCV_FAILURE "addr=" MACSTR
" frame=eapol-key-m2 error=%s",
- MAC2STR(sm->addr), ocv_errorstr);
- return;
+ MAC2STR(wpa_auth_get_spa(sm)),
+ ocv_errorstr);
+ goto out;
}
}
#endif /* CONFIG_OCV */
@@ -3268,7 +3340,7 @@
if (ft && ft_check_msg_2_of_4(wpa_auth, sm, &kde) < 0) {
wpa_sta_disconnect(wpa_auth, sm->addr,
WLAN_REASON_PREV_AUTH_NOT_VALID);
- return;
+ goto out;
}
#endif /* CONFIG_IEEE80211R_AP */
#ifdef CONFIG_P2P
@@ -3288,7 +3360,8 @@
MACSTR " (bit %u)",
sm->ip_addr[0], sm->ip_addr[1],
sm->ip_addr[2], sm->ip_addr[3],
- MAC2STR(sm->addr), sm->ip_addr_bit);
+ MAC2STR(wpa_auth_get_spa(sm)),
+ sm->ip_addr_bit);
}
}
#endif /* CONFIG_P2P */
@@ -3306,7 +3379,7 @@
"DPP: Peer indicated it supports PFS and local configuration allows this, but PFS was not negotiated for the association");
wpa_sta_disconnect(wpa_auth, sm->addr,
WLAN_REASON_PREV_AUTH_NOT_VALID);
- return;
+ goto out;
}
}
#endif /* CONFIG_DPP2 */
@@ -3319,14 +3392,15 @@
*/
if (os_memcmp_const(sm->sup_pmk_r1_name, sm->pmk_r1_name,
WPA_PMK_NAME_LEN) != 0) {
- wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
+ wpa_auth_logger(sm->wpa_auth, wpa_auth_get_spa(sm),
+ LOGGER_DEBUG,
"PMKR1Name mismatch in FT 4-way handshake");
wpa_hexdump(MSG_DEBUG,
"FT: PMKR1Name from Supplicant",
sm->sup_pmk_r1_name, WPA_PMK_NAME_LEN);
wpa_hexdump(MSG_DEBUG, "FT: Derived PMKR1Name",
sm->pmk_r1_name, WPA_PMK_NAME_LEN);
- return;
+ goto out;
}
}
#endif /* CONFIG_IEEE80211R_AP */
@@ -3335,7 +3409,7 @@
wpa_auth_update_vlan(wpa_auth, sm->addr, vlan_id) < 0) {
wpa_sta_disconnect(wpa_auth, sm->addr,
WLAN_REASON_PREV_AUTH_NOT_VALID);
- return;
+ goto out;
}
sm->pending_1_of_4_timeout = 0;
@@ -3351,9 +3425,20 @@
sm->MICVerified = true;
+#ifdef CONFIG_IEEE80211R_AP
+ if (wpa_key_mgmt_ft(sm->wpa_key_mgmt) && !sm->ft_completed) {
+ wpa_printf(MSG_DEBUG, "FT: Store PMK-R0/PMK-R1");
+ wpa_auth_ft_store_keys(sm, pmk_r0, pmk_r1, pmk_r0_name,
+ key_len);
+ }
+#endif /* CONFIG_IEEE80211R_AP */
+
os_memcpy(&sm->PTK, &PTK, sizeof(PTK));
forced_memzero(&PTK, sizeof(PTK));
sm->PTK_valid = true;
+out:
+ forced_memzero(pmk_r0, sizeof(pmk_r0));
+ forced_memzero(pmk_r1, sizeof(pmk_r1));
}
@@ -3577,7 +3662,7 @@
wpa_ie = wpa_ie_buf;
}
#endif /* CONFIG_TESTING_OPTIONS */
- wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
+ wpa_auth_logger(sm->wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
"sending 3/4 msg of 4-Way Handshake");
if (sm->wpa == WPA_VERSION_WPA2) {
if (sm->use_ext_key_id && sm->TimeoutCtr == 1 &&
@@ -3639,7 +3724,8 @@
* by setting the Secure bit here even in the case of
* WPA if the supplicant used it first.
*/
- wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
+ wpa_auth_logger(sm->wpa_auth, wpa_auth_get_spa(sm),
+ LOGGER_DEBUG,
"STA used Secure bit in WPA msg 2/4 - set Secure for 3/4 as workaround");
secure = 1;
}
@@ -3865,14 +3951,14 @@
sm->PInitAKeys = true;
else
sm->has_GTK = true;
- wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_INFO,
+ wpa_auth_vlogger(sm->wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
"pairwise key handshake completed (%s)",
sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN");
wpa_msg(sm->wpa_auth->conf.msg_ctx, MSG_INFO, "EAPOL-4WAY-HS-COMPLETED "
MACSTR, MAC2STR(sm->addr));
#ifdef CONFIG_IEEE80211R_AP
- wpa_ft_push_pmk_r1(sm->wpa_auth, sm->addr);
+ wpa_ft_push_pmk_r1(sm->wpa_auth, wpa_auth_get_spa(sm));
#endif /* CONFIG_IEEE80211R_AP */
sm->ptkstart_without_success = 0;
@@ -3888,7 +3974,7 @@
SM_ENTER(WPA_PTK, INITIALIZE);
else if (sm->Disconnect
/* || FIX: dot11RSNAConfigSALifetime timeout */) {
- wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
+ wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
"WPA_PTK: sm->Disconnect");
SM_ENTER(WPA_PTK, DISCONNECT);
}
@@ -3937,7 +4023,8 @@
#endif /* CONFIG_DPP */
} else {
wpa_auth->dot11RSNA4WayHandshakeFailures++;
- wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
+ wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
+ LOGGER_INFO,
"INITPMK - keyAvailable = false");
SM_ENTER(WPA_PTK, DISCONNECT);
}
@@ -3956,7 +4043,8 @@
"INITPSK: No PSK yet available for STA - use RADIUS later");
SM_ENTER(WPA_PTK, PTKSTART);
} else {
- wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
+ wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
+ LOGGER_INFO,
"no PSK configured for the STA");
wpa_auth->dot11RSNA4WayHandshakeFailures++;
SM_ENTER(WPA_PTK, DISCONNECT);
@@ -3968,7 +4056,8 @@
SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING);
else if (sm->TimeoutCtr > conf->wpa_pairwise_update_count) {
wpa_auth->dot11RSNA4WayHandshakeFailures++;
- wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
+ wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm),
+ LOGGER_DEBUG,
"PTKSTART: Retry limit %u reached",
conf->wpa_pairwise_update_count);
sm->disconnect_reason =
@@ -4000,7 +4089,8 @@
(conf->wpa_disable_eapol_key_retries &&
sm->TimeoutCtr > 1)) {
wpa_auth->dot11RSNA4WayHandshakeFailures++;
- wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
+ wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm),
+ LOGGER_DEBUG,
"PTKINITNEGOTIATING: Retry limit %u reached",
conf->wpa_pairwise_update_count);
sm->disconnect_reason =
@@ -4057,7 +4147,7 @@
os_memset(rsc, 0, WPA_KEY_RSC_LEN);
if (gsm->wpa_group_state == WPA_GROUP_SETKEYSDONE)
wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, rsc);
- wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
+ wpa_auth_logger(sm->wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
"sending 1/2 msg of Group Key Handshake");
gtk = gsm->GTK[gsm->GN - 1];
@@ -4138,7 +4228,7 @@
return;
if (wpa_parse_kde_ies(key_data, key_data_length, &kde) < 0) {
- wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
+ wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
"received EAPOL-Key group msg 2/2 with invalid Key Data contents");
return;
}
@@ -4149,7 +4239,8 @@
int tx_seg1_idx;
if (wpa_channel_info(wpa_auth, &ci) != 0) {
- wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
+ wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
+ LOGGER_INFO,
"Failed to get channel info to validate received OCI in EAPOL-Key group 2/2");
return;
}
@@ -4163,13 +4254,15 @@
if (ocv_verify_tx_params(kde.oci, kde.oci_len, &ci,
tx_chanwidth, tx_seg1_idx) !=
OCI_SUCCESS) {
- wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
+ wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm),
+ LOGGER_INFO,
"OCV failed: %s", ocv_errorstr);
if (wpa_auth->conf.msg_ctx)
wpa_msg(wpa_auth->conf.msg_ctx, MSG_INFO,
OCV_FAILURE "addr=" MACSTR
" frame=eapol-key-g2 error=%s",
- MAC2STR(sm->addr), ocv_errorstr);
+ MAC2STR(wpa_auth_get_spa(sm)),
+ ocv_errorstr);
return;
}
}
@@ -4180,7 +4273,7 @@
sm->GUpdateStationKeys = false;
sm->GTimeoutCtr = 0;
/* FIX: MLME.SetProtection.Request(TA, Tx_Rx) */
- wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO,
+ wpa_auth_vlogger(wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
"group key handshake completed (%s)",
sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN");
sm->has_GTK = true;
@@ -4195,7 +4288,7 @@
sm->GUpdateStationKeys = false;
sm->Disconnect = true;
sm->disconnect_reason = WLAN_REASON_GROUP_KEY_UPDATE_TIMEOUT;
- wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_INFO,
+ wpa_auth_vlogger(sm->wpa_auth, wpa_auth_get_spa(sm), LOGGER_INFO,
"group key handshake failed (%s) after %u tries",
sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN",
sm->wpa_auth->conf.wpa_group_update_count);
@@ -4308,7 +4401,8 @@
return 0;
if (sm->wpa_ptk_state != WPA_PTK_PTKINITDONE) {
- wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
+ wpa_auth_logger(sm->wpa_auth, wpa_auth_get_spa(sm),
+ LOGGER_DEBUG,
"Not in PTKINITDONE; skip Group Key update");
sm->GUpdateStationKeys = false;
return 0;
@@ -4319,7 +4413,8 @@
* Since we clear the GKeyDoneStations before the loop, the
* station needs to be counted here anyway.
*/
- wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
+ wpa_auth_logger(sm->wpa_auth, wpa_auth_get_spa(sm),
+ LOGGER_DEBUG,
"GUpdateStationKeys was already set when marking station for GTK rekeying");
}
@@ -4553,7 +4648,7 @@
if (sm->group == ctx) {
wpa_printf(MSG_DEBUG, "WPA: Mark STA " MACSTR
" for disconnection due to fatal failure",
- MAC2STR(sm->addr));
+ MAC2STR(wpa_auth_get_spa(sm)));
sm->Disconnect = true;
}
@@ -4646,7 +4741,7 @@
if (sm->pending_deinit) {
wpa_printf(MSG_DEBUG,
"WPA: Completing pending STA state machine deinit for "
- MACSTR, MAC2STR(sm->addr));
+ MACSTR, MAC2STR(wpa_auth_get_spa(sm)));
wpa_free_sta_sm(sm);
return 1;
}
@@ -4982,7 +5077,8 @@
wpa_hexdump_key(MSG_DEBUG, "RSN: Cache PMK", pmk, pmk_len);
if (pmksa_cache_auth_add(sm->wpa_auth->pmksa, pmk, pmk_len, NULL,
sm->PTK.kck, sm->PTK.kck_len,
- sm->wpa_auth->addr, sm->addr, session_timeout,
+ wpa_auth_get_aa(sm),
+ wpa_auth_get_spa(sm), session_timeout,
eapol, sm->wpa_key_mgmt))
return 0;
@@ -5392,7 +5488,7 @@
wpa_printf(MSG_DEBUG, "WPA: Moving STA " MACSTR
" to use group state machine for VLAN ID %d",
- MAC2STR(sm->addr), vlan_id);
+ MAC2STR(wpa_auth_get_spa(sm)), vlan_id);
wpa_group_get(sm->wpa_auth, group);
wpa_group_put(sm->wpa_auth, sm->group);
@@ -5408,7 +5504,7 @@
if (!wpa_auth || !sm)
return;
wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key TX status for STA " MACSTR
- " ack=%d", MAC2STR(sm->addr), ack);
+ " ack=%d", MAC2STR(wpa_auth_get_spa(sm)), ack);
if (sm->pending_1_of_4_timeout && ack) {
/*
* Some deployed supplicant implementations update their SNonce
@@ -5606,7 +5702,7 @@
anonce = anonce_buf;
}
- wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
+ wpa_auth_logger(sm->wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
"sending 1/4 msg of 4-Way Handshake (TESTING)");
wpa_send_eapol(sm->wpa_auth, sm,
WPA_KEY_INFO_ACK | WPA_KEY_INFO_KEY_TYPE, NULL,
@@ -5648,7 +5744,7 @@
wpa_ie = wpa_ie + wpa_ie[1] + 2;
wpa_ie_len = wpa_ie[1] + 2;
}
- wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
+ wpa_auth_logger(sm->wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
"sending 3/4 msg of 4-Way Handshake (TESTING)");
if (sm->wpa == WPA_VERSION_WPA2) {
/* WPA2 send GTK in the 4-way handshake */
@@ -5673,7 +5769,8 @@
* by setting the Secure bit here even in the case of
* WPA if the supplicant used it first.
*/
- wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
+ wpa_auth_logger(sm->wpa_auth, wpa_auth_get_spa(sm),
+ LOGGER_DEBUG,
"STA used Secure bit in WPA msg 2/4 - set Secure for 3/4 as workaround");
secure = 1;
}
@@ -5810,7 +5907,7 @@
/* Send EAPOL(1, 1, 1, !Pair, G, RSC, GNonce, MIC(PTK), GTK[GN]) */
os_memset(rsc, 0, WPA_KEY_RSC_LEN);
/* Use 0 RSC */
- wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
+ wpa_auth_logger(sm->wpa_auth, wpa_auth_get_spa(sm), LOGGER_DEBUG,
"sending 1/2 msg of Group Key Handshake (TESTING)");
gtk = gsm->GTK[gsm->GN - 1];
diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c
index 88d63bb..35585cd 100644
--- a/src/ap/wpa_auth_ft.c
+++ b/src/ap/wpa_auth_ft.c
@@ -35,6 +35,9 @@
const unsigned int ftRRBseqTimeout = 10;
const unsigned int ftRRBmaxQueueLen = 100;
+/* TODO: make these configurable */
+static const int dot11RSNAConfigPMKLifetime = 43200;
+
static int wpa_ft_send_rrb_auth_resp(struct wpa_state_machine *sm,
const u8 *current_ap, const u8 *sta_addr,
@@ -2109,11 +2112,11 @@
}
-int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, struct wpa_ptk *ptk)
+int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, struct wpa_ptk *ptk,
+ u8 *pmk_r0, u8 *pmk_r1, u8 *pmk_r0_name,
+ size_t *key_len, size_t kdk_len)
{
- u8 pmk_r0[PMK_LEN_MAX], pmk_r0_name[WPA_PMK_NAME_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;
const u8 *r0kh = sm->wpa_auth->conf.r0_key_holder;
@@ -2121,12 +2124,6 @@
const u8 *r1kh = sm->wpa_auth->conf.r1_key_holder;
const u8 *ssid = sm->wpa_auth->conf.ssid;
size_t ssid_len = sm->wpa_auth->conf.ssid_len;
- int psk_local = sm->wpa_auth->conf.ft_psk_generate_local;
- int expires_in = sm->wpa_auth->conf.r0_key_lifetime;
- struct vlan_description vlan;
- const u8 *identity, *radius_cui;
- size_t identity_len, radius_cui_len;
- int session_timeout;
const u8 *mpmk;
size_t mpmk_len;
@@ -2139,7 +2136,7 @@
pmk_r0_len = SHA384_MAC_LEN;
else
pmk_r0_len = PMK_LEN;
- pmk_r1_len = pmk_r0_len;
+ *key_len = pmk_r1_len = pmk_r0_len;
if (sm->xxkey_len > 0) {
mpmk = sm->xxkey;
@@ -2153,10 +2150,39 @@
return -1;
}
+ if (wpa_derive_pmk_r0(mpmk, mpmk_len, ssid, ssid_len, mdid,
+ r0kh, r0kh_len, sm->addr,
+ pmk_r0, pmk_r0_name,
+ sm->wpa_key_mgmt) < 0 ||
+ wpa_derive_pmk_r1(pmk_r0, pmk_r0_len, pmk_r0_name, r1kh, sm->addr,
+ pmk_r1, sm->pmk_r1_name) < 0)
+ return -1;
+
+ return wpa_pmk_r1_to_ptk(pmk_r1, pmk_r1_len, sm->SNonce, sm->ANonce,
+ sm->addr, sm->wpa_auth->addr, sm->pmk_r1_name,
+ ptk, ptk_name, sm->wpa_key_mgmt, sm->pairwise,
+ kdk_len);
+}
+
+
+void wpa_auth_ft_store_keys(struct wpa_state_machine *sm, const u8 *pmk_r0,
+ const u8 *pmk_r1, const u8 *pmk_r0_name,
+ size_t key_len)
+{
+ int psk_local = sm->wpa_auth->conf.ft_psk_generate_local;
+ int expires_in = sm->wpa_auth->conf.r0_key_lifetime;
+ struct vlan_description vlan;
+ const u8 *identity, *radius_cui;
+ size_t identity_len, radius_cui_len;
+ int session_timeout;
+
+ if (psk_local && wpa_key_mgmt_ft_psk(sm->wpa_key_mgmt))
+ return;
+
if (wpa_ft_get_vlan(sm->wpa_auth, sm->addr, &vlan) < 0) {
wpa_printf(MSG_DEBUG, "FT: vlan not available for STA " MACSTR,
MAC2STR(sm->addr));
- return -1;
+ return;
}
identity_len = wpa_ft_get_identity(sm->wpa_auth, sm->addr, &identity);
@@ -2164,31 +2190,16 @@
&radius_cui);
session_timeout = wpa_ft_get_session_timeout(sm->wpa_auth, sm->addr);
- if (wpa_derive_pmk_r0(mpmk, mpmk_len, ssid, ssid_len, mdid,
- r0kh, r0kh_len, sm->addr,
- pmk_r0, pmk_r0_name,
- 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,
- pmk_r0_name,
- sm->pairwise, &vlan, expires_in,
- session_timeout, identity, identity_len,
- radius_cui, radius_cui_len);
- if (wpa_derive_pmk_r1(pmk_r0, pmk_r0_len, pmk_r0_name, r1kh, sm->addr,
- pmk_r1, sm->pmk_r1_name) < 0)
- return -1;
- if (!psk_local || !wpa_key_mgmt_ft_psk(sm->wpa_key_mgmt))
- wpa_ft_store_pmk_r1(sm->wpa_auth, sm->addr, pmk_r1, pmk_r1_len,
- sm->pmk_r1_name, sm->pairwise, &vlan,
- expires_in, session_timeout, identity,
- identity_len, radius_cui, radius_cui_len);
-
- return wpa_pmk_r1_to_ptk(pmk_r1, pmk_r1_len, sm->SNonce, sm->ANonce,
- sm->addr, sm->wpa_auth->addr, sm->pmk_r1_name,
- ptk, ptk_name, sm->wpa_key_mgmt, sm->pairwise,
- 0);
+ wpa_ft_store_pmk_r0(sm->wpa_auth, sm->addr, pmk_r0, key_len,
+ pmk_r0_name,
+ sm->pairwise, &vlan, expires_in,
+ session_timeout, identity, identity_len,
+ radius_cui, radius_cui_len);
+ wpa_ft_store_pmk_r1(sm->wpa_auth, sm->addr, pmk_r1, key_len,
+ sm->pmk_r1_name, sm->pairwise, &vlan,
+ expires_in, session_timeout, identity,
+ identity_len, radius_cui, radius_cui_len);
}
@@ -2941,6 +2952,9 @@
/* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */
sm->pairwise_set = true;
sm->tk_already_set = true;
+
+ wpa_auth_store_ptksa(sm->wpa_auth, sm->addr, sm->pairwise,
+ dot11RSNAConfigPMKLifetime, &sm->PTK);
}
diff --git a/src/ap/wpa_auth_i.h b/src/ap/wpa_auth_i.h
index 7ed3f2b..d401550 100644
--- a/src/ap/wpa_auth_i.h
+++ b/src/ap/wpa_auth_i.h
@@ -296,6 +296,9 @@
int wpa_auth_for_each_auth(struct wpa_authenticator *wpa_auth,
int (*cb)(struct wpa_authenticator *a, void *ctx),
void *cb_ctx);
+void wpa_auth_store_ptksa(struct wpa_authenticator *wpa_auth,
+ const u8 *addr, int cipher,
+ u32 life_time, const struct wpa_ptk *ptk);
#ifdef CONFIG_IEEE80211R_AP
int wpa_write_mdie(struct wpa_auth_config *conf, u8 *buf, size_t len);
@@ -304,7 +307,12 @@
const u8 *anonce, const u8 *snonce,
u8 *buf, size_t len, const u8 *subelem,
size_t subelem_len, int rsnxe_used);
-int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, struct wpa_ptk *ptk);
+int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, struct wpa_ptk *ptk,
+ u8 *pmk_r0, u8 *pmk_r1, u8 *pmk_r0_name,
+ size_t *key_len, size_t kdk_len);
+void wpa_auth_ft_store_keys(struct wpa_state_machine *sm, const u8 *pmk_r0,
+ const u8 *pmk_r1, const u8 *pmk_r0_name,
+ size_t key_len);
struct wpa_ft_pmk_cache * wpa_ft_pmk_cache_init(void);
void wpa_ft_pmk_cache_deinit(struct wpa_ft_pmk_cache *cache);
void wpa_ft_install_ptk(struct wpa_state_machine *sm, int retry);
diff --git a/src/ap/wpa_auth_kay.c b/src/ap/wpa_auth_kay.c
index e2c4e10..625f405 100644
--- a/src/ap/wpa_auth_kay.c
+++ b/src/ap/wpa_auth_kay.c
@@ -327,6 +327,7 @@
res = ieee802_1x_kay_init(kay_ctx, policy,
hapd->conf->macsec_replay_protect,
hapd->conf->macsec_replay_window,
+ hapd->conf->macsec_offload,
hapd->conf->macsec_port,
hapd->conf->mka_priority,
hapd->conf->macsec_csindex,
@@ -352,33 +353,6 @@
}
-static int ieee802_1x_auth_get_session_id(struct hostapd_data *hapd,
- struct sta_info *sta, u8 *sid,
- size_t *len)
-{
- const u8 *session_id;
- size_t id_len, need_len;
-
- session_id = ieee802_1x_get_session_id(sta->eapol_sm, &id_len);
- if (!session_id) {
- wpa_printf(MSG_DEBUG,
- "MACsec: Failed to get SessionID from EAPOL state machines");
- return -1;
- }
-
- need_len = 1 + 2 * 32 /* random size */;
- if (need_len > id_len) {
- wpa_printf(MSG_DEBUG, "EAP Session-Id not long enough");
- return -1;
- }
-
- os_memcpy(sid, session_id, need_len);
- *len = need_len;
-
- return 0;
-}
-
-
static int ieee802_1x_auth_get_msk(struct hostapd_data *hapd,
struct sta_info *sta, u8 *msk, size_t *len)
{
@@ -410,8 +384,8 @@
void * ieee802_1x_notify_create_actor_hapd(struct hostapd_data *hapd,
struct sta_info *sta)
{
- u8 *sid;
- size_t sid_len = 128;
+ const u8 *sid;
+ size_t sid_len;
struct mka_key_name *ckn;
struct mka_key *cak;
struct mka_key *msk;
@@ -425,10 +399,9 @@
MACSTR, MAC2STR(sta->addr));
msk = os_zalloc(sizeof(*msk));
- sid = os_zalloc(sid_len);
ckn = os_zalloc(sizeof(*ckn));
cak = os_zalloc(sizeof(*cak));
- if (!msk || !sid || !ckn || !cak)
+ if (!msk || !ckn || !cak)
goto fail;
msk->len = DEFAULT_KEY_LEN;
@@ -437,8 +410,8 @@
goto fail;
}
- if (ieee802_1x_auth_get_session_id(hapd, sta, sid, &sid_len))
- {
+ sid = ieee802_1x_get_session_id(sta->eapol_sm, &sid_len);
+ if (!sid) {
wpa_printf(MSG_ERROR,
"IEEE 802.1X: Could not get EAP Session Id");
goto fail;
@@ -470,7 +443,6 @@
fail:
bin_clear_free(msk, sizeof(*msk));
- os_free(sid);
os_free(ckn);
bin_clear_free(cak, sizeof(*cak));