[wpa_supplicant] Cumulative patch from commit 257b119c2
Bug: 265294868
Test: Verify Passpoint ANQP functionality and Passpoint association
Test: Connect to Passpoint, Open, WPA2, WPA3 networks and run traffic
Test: Regression test b/218404053 (Bug: TBD)
BYPASS_INCLUSIVE_LANGUAGE_REASON=Merged from Open sourcie
257b119c2 QCA vendor attribute of update roaming cached statistics info
18436f393 Enhance QCA vendor interface for Concurrent AP Policy for XR
58fba11e1 Enhance QCA vendor interface with new hang reason codes
0f3f9cdca dpp-nfc: Try to request with alternative URL in additional cases
8b36248cd Add QCA vendor command to get the monitor mode status
0dd8bcef8 QCA vendor attributes for MLO and EHT capabilities
e5602989c QCA vendor attributes to configure EHT capabilities
d9d5e55c5 DPP: Respond to GAS on the same channel it was received on
651c9e957 Add new status code strings
3a2d27552 Make MFPR value from an associated STA available as hostapdMFPR
546debd5e Force MFPR=1 to be used on the 6 GHz band
f9c6ab834 P2P: Support preferred GO band based optimization for scanning
093bedc05 P2P: Allow persistent group join retry limit to be configured via D-Bus
8717110db Do not flush PMKSA cache on restoring dedicated per-ESS MAC address
1d4027fdb Make random MAC address style parameters use common enum values
681856c35 Check both sec and usec values to see if MAC address was changed
bdbb6e003 wpa_supplicant: Handle MAC address randomization changes for same ESS
4bd1efe07 dbus: Do not bring down primary interface when removing created AP interface
f4096e7cd EHT: Update EHT Operation element to P802.11be/D2.3 in AP settings
e869fdfee wpa_supplicant: Use MLD address in SAE authentication
8c0f83ae8 SME: Accept Authentication frame from an MLD AP
23039f5e4 SME: Add support for handling association with MLD
8f89661df SME: Add support for handling authentication with MLD
694a1c687 SAE: Make sme_sae_auth() return IE offset
870edfd67 WPA3: Update transition disable bitmap based on port authorized event
8fdf3c447 Sync with wireless-next.git include/uapi/linux/nl80211.h
f9804e306 nl80211: Enforce unique address for AP iftype
87bad8afa dbus: Pass in MAC address in CreateInterface method
b0722cf75 dbus: Fix a memory leak on error path in CreateInterface method
a7f6b8518 crypto: Check if crypto_bignum_to_bin() is successful
2749a2c6b nl80211: Actually get and store TX retries
998aeca3c crypto: Clear secrets from stack in hmac_sha256_vector()
909864ab1 HS 2.0: Restore ifdef for DEFINE_STACK_OF in est.c
af0ab435a PASN: Use the assigned status code from IEEE P802.11az/D7.0
3d798ff2a PASN: Align RSNXE with IEEE P802.11az/D7.0 definitions
ab2cb379d Define all assigned BSS membership selector values
ed0a7b480 wpa_supplicant: Implement HE membership selector check
054fcfab6 hostapd: Add require_he configuration
c46351d10 DFS: Clear cac_started when AP is disabled
3df42cf3c EHT: Use HE operating channel width in MCS length calculation
23e31eb68 SAE: Support cross AKM roaming between SAE AKMs in external auth case
a17026707 PASN: Avoid clearing secure context for the PASN deauthentication event
75a9c4bd4 Add new attributes in SCS rule config QCA vendor subcommand
7d8b96dcf wpa_supplicant: Apply same restrictions for MLD as for 6 GHz BSS
7216f79b9 nl80211: Support get_sta_mlo_info for SME-in-wpa_supplicant drivers
06eb608d5 nl80211: Handle scan results with MLD connection
033a57d26 nl80211: Get MLO support capability
32b745448 wpa_supplicant: Make valid_links u16
a2c4c0b1b nl80211: Support MLD association request
a134b4dc5 nl80211: Add support for MLD authentication
e3e68668c ctrl_iface: Report RNR and ML in BSS command
5f17763ad common: Combine definitions for Multi-Link and per STA profile control
7a7ce9574 dbus: Emit more information over D-Bus
ad4fa5dd3 Add more nl80211 info to struct wpa_signal_info
090f0f8c7 mbssid: Indicate MBSSID information in RNR
a1c4adda1 mbssid: Add nl80211 support
54b1352ef mbssid: Make the AID space shared
10749c3c4 mbssid: Process Known BSSID element
15690faad mbssid: Add MBSSID Configuration element
fc2e4bac5 mbssid: Set extended capabilities
a004bf2cd mbssid: Configure parameters and element data
c5a09b051 mbssid: Add Non-Inheritance element
920b56322 mbssid: Functions for building Multiple BSSID elements
931e5d4f9 mbssid: Configure all BSSes before beacon setup
78d0b9899 mbssid: Retrieve driver capabilities
7452e5447 mbssid: Add new configuration option
bb67d5b52 AP: Add testing option to delay EAPOL Tx
1897abad9 dbus: Add D-Bus property for current MAC address
1a800a940 EAP-TEAP server: Allow tunneled EAP method sequence to be optimized
f791b5bbc EAP-TEAP peer: Process Crypto-Binding TLV before EAP Payload TLV
5a9bd8a06 EAP-TEAP: Use EAP-FAST-MSCHAPv2 in the tunnel
364b6500b EAP-FAST: Move EAP-MSCHAPv2 special MSK handling into MSCHAPv2
81dedfbd7 nl80211: Increase the scan frequencies buffer
9a2781f24 wpa_supplicant: Support throughput estimation for EHT rates
755aaeb97 wpa_supplicant: Add missing memory allocation checks
69725c4cf OpenSSL: Fix BN_rshift() argument order
e9b4ad236 OpenSSL: Apply connection flags before reading certificates
bbd5a4689 SAE: Add an enum for defining sae_pwe parameter values
3a0edb2cd SAE: Enable H2E for 6 GHz BSS
20bfd4feb AP: Enable H2E on 6 GHz when SAE is used
b43e19f3f WPS: Cross band overlap detection with multiple interfaces
e2d88f86e DPP: Expose own and peer bootstrap info ids on authentication success
043dedee8 DPP: Expose enrollee pubkey hash for identification
2d8974e31 DPP: Move DPP_EVENT_AUTH_SUCCESS to a helper
d8d2b3a33 Implement read-only mode for SSIDs from the additional config (-I)
4cb23b66d ACS: Allow selecting a better channel when using 40/80/160 MHz
472101684 ACS: introduce acs_adjust_secondary
60e2934cb ACS: Introduce acs_get_bw_center_chan()
ed8e13dec ACS: Extract bw40/80/160 freqs out of acs_usable_bwXXX_chan()
9025def55 wpa_supplicant: Add support for pregenerated MAC
5da3e1ca4 mesh: Do not allow open mode key in 6 GHz
50a9b7d3d P2P: Include only 6 GHz PSCs in full scan
0d6cd88ee DPP: Use existing TCP connection to replay duplicate Presence Announcement
6af717f73 DPP: Don't close TCP connection for duplicate Presence Announcements
46e6b72b7 Add a callback to notify added PMKSA cache entry details
af1528a12 hostapd: Add RELOAD_BSS
bc2b88b25 hostapd: Add config_id to GET_CONFIG output
b37c3fbad hostapd: Add config_id parameter
46f6a3277 Split BSS-specific hostapd_clear_old_bss() from hostapd_clear_old()
2afb9b1a5 dbus: Add dbus notify when wpa_s->key_mgmt changes
98e9d553f nl80211: Check previous MAC address for locally-generated-deauth
87ffa1bec wpa_supplicant: Convert SSID into printable form before printing
416386060 Mark authorization completed on driver indication during 4-way HS offload
da2ec9459 D-Bus: Split set_cred_properties() into two functions
f5ce680ee D-Bus: Hotspot 2.0 credentials with multiple domains
2f739c71c ctrl: Fix compilation with UDP control interface
6d4548187 RSN: Split EAPOL-Key msg 3/4 processing for WPA(v1)
5b7957b7e RSN: Split EAPOL-Key msg 1/4 processing for WPA(v1)
e5dfce38f RSN: Split EAPOL-Key group msg 1/2 processing more completely for WPA(v1)
5ab43c738 RSN: Split WPA(v1) processing of EAPOL-Key frames into a separate function
f7fd891c7 Fix a typo in driver ops poll() documentation
3268ec0ac HS20: Use required_home_ois in hs20-osu-client
58eb905ad HS20: Support credentials with multiple home OIs
0143dc1cb OpenSSL: Load OpenSSL 3.0 legacy provider but let default be loaded
fef4c6cb0 OpenSSL: Don't provide implementation of DES/RC4 for FIPS builds
1d42dafce RSN: Do not include RC4 use in FIPS builds
df5ae2aad Add more detailed description of RADIUS attributes in EAP user file
0ba266d86 dbus: Add virtual interface create/remove logic to be inline with ctrl_iface
5102d7411 wpa_passphrase: Disable terminal echo when reading from stdin
86ab28217 PASN: Fix passing own address and peer address to pasn_deauthenticate()
a9062432e wpa_cli: Fix PASN control interface commands
b6d3fd05e FT: Use SHA256 to derive PMKID for AKM 00-0F-AC:3 (FT-EAP)
ef70f814a Add a new QCA vendor attribute to configure wifi calling (wfc) state
05ec48568 WPS: Pick WPS AP based on latest received WPS IE
ca4fa867d Enable PMF automatically if OCV is enabled
c823197bd SAE: Use Challenge Failure status code in confirm message failure cases
65c8633d9 Allow a lower priority BSS to be tried after network disabling
e91ac53d5 DFS: Do not allow channel checks to go beyond the channel list
f96dfdeef PASN: Fix missing libraries for libpasn.so on Android
91d148f50 PASN: Fix is_pasn_auth_frame() for mgmt tx status frames
b6c38cee9 Skip CAC if the driver switches channel to non-DFS
080afc03d Add hostapd control interface command to stop logging to file
0fd13c90e Add QCA vendor interface for AP doze mode configuration
4e1f55a11 Roam control configuration for 6 GHz in full scan only on prior discovery
34d93b0c9 HS 2.0: Deauthenticate STA on deauth-imminent more quickly if no URL
2e40f969b nl80211: Fix wrong requested links bitmap in sta_mlo_info.req_links
b6e226496 MLD STA: Fix IGTK and BIGTK MLO KDEs validation
2050130be Add a vendor attribute for roam control configuration for full scan
12f16c27b TLS: Fix unsigned int underflow in internal TLS 1.0/1.1 implementation
802b67bce Update tls_connection_set_verify() documentation to verify_peer=2
0202b9774 DPP: Fix memory leak of intro.peer_key in station handling
f723f7f8a P2P: Check dev pointer consistently when building PD Response
30403e965 WPS: Check NDEF record length fields separately
cd0e8653a TDLS: Use stored FTE length in MIC calculation
7e85e24f3 TDLS: Use stored peer RSNE length in MIC calculation
40a42613e FT: Simplify FTE parsing for FT-SAE-EXT-KEY using MIC Length subfield
5ea7a2f54 DPP: Drop PMKSA entry if AP reject association due to invalid PMKID
4840b45a2 Fix empty pmksa_cache_get()
3abd0c471 SAE: Print rejection of peer element clearly in debug log
9ff778fa4 Check for own address (SPA) match when finding PMKSA entries
9f04a9c8d Store own MAC address (SPA) in supplicant PMKSA cache entries
309765eb6 PASN: Use separate variables for BSSID and peer address
42f0c44d8 PASN: Use peer address instead of BSSID as the destination for initiator
15583802b nl80211: Allow up to 64-byte PMK in NL80211_CMD_SET_PMKSA
bbe5f0c1e FT: Do not try to use FT protocol between mobility domains
b92f61885 Don't use default RSNE/RSNXE when the driver indicates cross SSID roaming
d7febe33f MLO: Remove unnecessary debug prints about clearing AP RSNE/RSNXE
16d913bfd Define AFC vendor commands and events
46f5cf928 OpenSSL: Fix additional HPKE corner cases
bdc35acd5 SAE: Allow loading of the password from an external database
48dd8994a Fix external passwords with 4-way handshake offloading
e5a7c852c systemd: Use interface name in description of interface-specific units
a0628f8a5 OpenSSL: Remove unused assignment from HPKE expand
3e1a04afa nl80211: Check that attribute addition succeeds in offloaded PASN case
0658a22ef GAS: Try to make buffer length determination easier for static analyzers
271ce71c7 FT: Fix PMK-R0 derivation for FT-SAE-EXT-KEY with SHA512
2f61d703a MLD STA: Group key handshake processing for GTK/IGTK/BIGTK rekeying
f0760aa6d MLD STA: Use AP MLD address as destination for 4-way handshake EAPOL-Key frames
8f2e493be MLD STA: Validation of MLO KDEs for 4-way handshake EAPOL-Key frames
f15cc834c MLD STA: Processing of EAPOL-Key msg 3/4 frame when using MLO
08512e5f3 MLD STA: Extend key configuration functions to support Link ID
a4adb2f3e MLD STA: Configure TK to the driver using AP MLD address
fa5cad61a MLD STA: Use AP MLD address in PMKSA entry
052bf8a51 MLD STA: Use AP MLD address to derive pairwise keys
e78437256 MLD STA: Add MLO KDEs for EAPOL-Key msg 2/4 and 4/4
472a0b8d6 MLD STA: Set MLO connection info to wpa_sm
cc2236299 nl80211: Get all requested MLO links information from (re)association events
1ca5c2ec2 PASN: Fix spelling of RSNE in debug messages
a43536a72 PASN: Verify explicitly that elements are present before parsing
7e3852407 PASN: Fix MIC check not to modify const data
8481c7509 PASN: Fix Authentication frame checks
f899d7f37 dbus: Apply PMK properties immediately
c6f8af507 Add option to disable SAE key_mgmt without PMF
7ad757ec0 Document crypto_ec_key_get_subject_public_key() to use compressed format
6527a7656 DPP: Stop listen mode for chirp-initiated Authentication exchange
2e7339442 P2P: Discount current operating frequency when scanning new connection
00a762c26 Do not drop connection attempt when reconnecting to the same ESS
368de263b P2P: Skip Extended Listen timeout to allow scans during group formation
cff55f348 P2P: Clone sae_pwe config to new group interface config
ae517789f P2P: Allow PSC channel to be used for 6 GHz BW40
9c830d917 P2P: Track peer 6 GHz capability more robustly
1ca403a8b Add QCA vendor subcommand to notify about primary netdev
70d89f90e A vendor roam control configuration for delaying hand off for RX
fff81a468 PASN: Change pasn_use_384() to be a non-static function
ea241cbe9 PASN: Rename struct wpas_pasn to pasn_data
6be84343a PASN: Add pairing verification wrapper function for Wi-Fi Aware
325236948 PASN: Mark wpas_pasn_start() comeback argument const
b1ed44b6a PASN: Allow extra elements to be added into PASN Authentication frames
08abcdf4e PASN: Makefile and Android.mk changes for libpasn.so
78c5bb7f5 PASN: Move responder functionality into a separate file
c7edfce79 PASN: Move initiator changes into a separate file
975b7a02c Move SAE comeback token functionality into a separate file
1711fe912 PASN: Compute MIC from RSNE and RSNXE of the frame for Wi-Fi Aware
6f80014b1 PASN: Allow custom PMKID in Authentication frames for Wi-Fi Aware
e99047da2 PASN: Add a handler func to send mgmt frames to the driver from AP
4022ffc5d PASN: Store AKMP in the PTKSA cache
c55eadede PASN: Remove hapd dependency in processing PASN Authentication frames
6dc833bc5 PASN: Remove hapd dependency for PASN and SAE comeback
1861f5716 PASN: Remove hapd dependency for pasn_derive_keys()
1fa266e99 PASN: Remove hapd dependency for SAE and FILS wrapped data
bc9fbe1b2 PASN: Common wpas_pasn structure for initiator and responder
14b5ebce7 PASN: Add a common header file for initiator and responder
af5eec3b3 PASN: Function handler to transmit Authentication frames
629bbc91b PASN: Remove dependency of wpa_ssid for initiator
e7f45ca11 PASN: Remove wpa_s dependency for wpas_pasn_start()
0be131265 PASN: Remove wpa_s dependency for wpas_pasn_build_auth_1()
086ccdc59 PASN: Remove wpa_s dependency for the functions processing RX frames
e2e87b90b PASN: Remove wpa_s dependency for wpas_pasn_auth_tx_status()
de4b73a36 PASN: Remove wpa_s dependency for FILS wrapped data
90bb73c51 PASN: Remove wpa_sm dependency to add an entry to PMKSA cache
5313e5a79 PASN: Remove unused wpa_s parameter for wpas_pasn_sae_setup_pt()
f636cbd04 PASN: Remove wpa_s dependency for SAE wrapped data functions
5535fbcfa PASN: Add wpa_pasn_reset() to eliminate need for struct wpa_supplicant
10e455c44 Enable use of PMKSA caching independent of RSN supplicant state machine
1d0ee1908 Fix the vendor ID assignment for configuring periodic sounding
b17b86da4 QCA vendor attribute to configure periodic sounding
6f3efa21c MLD STA: Fix crash caused by NULL wpa_s->current_ssid
ef5a9a009 nl80211: Fix parsing PASN peer and src addresses from vendor nl attributes
2c55c9273 More debug prints for EAPOL-Key message generation (Authenticator)
90cef4f21 MLD STA: Fully clear MLO info to avoid use of uninitialized members
496a1ced1 MLD STA: Use MLD addresses for sending non-Public Action frames
17ae98873 MLD STA: Support processing of M1 received before association event
9dafad1ea EHT: Definitions for STA Control fields of Basic Multi-Link element
1fbea7d43 EHT: Multi-Link element defragmentation
ec03b71ee common: Refactor element defragmentation
347ea8f0a EHT: Parse Multi-Link elements
73f540b6a MLD STA: Fetch MLO association Link ID info to core wpa_supplicant
ee46b7d6d nl80211: Check MLO link status info in NL80211_CMD_CONNECT
6e015cd45 RADIUS: Add Filter-Id attribute
06800f612 Add QCA vendor attributes for EHT support in external ACS
042368663 Vendor attribute to configure QoS/AC upgrade for UDP frames
e5d15e225 EHT: Allow EHT to be disabled using disable_eht=1 in wpa_supplicant
041f6cea9 SAE: Accept FT and -EXT-KEY AKMs for external auth
b72922796 P2P: Get cached scan results on iface creation to avoid scan
8392ea9e7 SAE: Fix AKM suite selector check for external authentication
ebe6a7c94 FT: Cover variable length KCK in function documentation
eda4ba081 FT: Reassociation Response frame validation for FT-SAE-EXT-KEY
0f7253d35 FT: Response processing for FT-SAE-EXT-KEY
a1eb1bb0e FT: Supplicant side FTE generation for FT-SAE-EXT-KEY
883e33594 FT: Authentication request frame processing for FT-SAE-EXT-KEY
879363bbc FT: Reassociation Request frame parsing for FT-SAE-EXT-KEY
e8f23c948 FT: Association Response frame FTE generation for FT-SAE-EXT-KEY
a76a314c1 FT: Extend PMK-R0 derivation for FT-SAE-EXT-KEY
79cd846b2 FT: Extend PTK derivation for FT-SAE-EXT-KEY
39b60f334 FT: Extend PMK-R1 derivation for FT-SAE-EXT-KEY
fb4fc704c FT: Debug print FTE subelements during parsing
25b52e5f8 FT: Extend FTE parsing for FT-SAE-EXT-KEY
4f58afee9 FT: Extend MIC derivation for FT-SAE-EXT-KEY
dcd46edf5 FT: Extend PMKR1Name derivation for FT-SAE-EXT-KEY
9fd245564 FT: Support longer SAE PMK for FT in INITPSK AP
c41bd98be FT: AP mode FTE writing to support FT-SAE-KEY-EXT
efa0f51d3 FT: Accept 512-bit PMK-R1 from RRB
eb0821c90 Add service class id attribute in SCS rule config vendor subcommand
5607abe2e WNM: Print unsupported neighbor report subelements in debug log
fcdd76fa2 Interworking: Print unsupported inner EAP-TTLS method in debug log
f8a05de66 Move default action from after switch to within
7614fcebe ACS: Filter out 6 GHz channels if HE or EHT is not enabled
1864664ca Android: Delay QCA roam+auth event until NL80211_CMD_ROAM is received
5f3cdc064 Override ieee80211w from pmf for AP mode in wpa_supplicant
2b972a35b DPP: Require PMF when profile is for SAE without PSK
8219d2b7d PASN: Fix CONFIG_PASN=y build without CONFIG_IEEE80211R=y
Change-Id: Ifd6be0d096df54c13162fdda164cd8e804a51692
Merged-In: Ifd6be0d096df54c13162fdda164cd8e804a51692
(cherry picked from commit 38ad1edd94f7b4f3c3937dd21a9b7ef52140babf)
diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c
index 21f8b5b..3a39886 100644
--- a/src/rsn_supp/wpa.c
+++ b/src/rsn_supp/wpa.c
@@ -38,6 +38,45 @@
static const u8 null_rsc[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+static void _wpa_hexdump_link(int level, u8 link_id, const char *title,
+ const void *buf, size_t len, bool key)
+{
+ char *link_title = NULL;
+
+ if (link_id >= MAX_NUM_MLD_LINKS)
+ goto out;
+
+ link_title = os_malloc(os_strlen(title) + 20);
+ if (!link_title)
+ goto out;
+
+ os_snprintf(link_title, os_strlen(title) + 20, "MLO link[%u]: %s",
+ link_id, title);
+
+out:
+ if (key)
+ wpa_hexdump_key(level, link_title ? link_title : title, buf,
+ len);
+ else
+ wpa_hexdump(level, link_title ? link_title : title, buf, len);
+ os_free(link_title);
+}
+
+
+static void wpa_hexdump_link(int level, u8 link_id, const char *title,
+ const void *buf, size_t len)
+{
+ _wpa_hexdump_link(level, link_id, title, buf, len, false);
+}
+
+
+static void wpa_hexdump_link_key(int level, u8 link_id, const char *title,
+ const void *buf, size_t len)
+{
+ _wpa_hexdump_link(level, link_id, title, buf, len, true);
+}
+
+
/**
* wpa_eapol_key_send - Send WPA/RSN EAPOL-Key message
* @sm: Pointer to WPA state machine data from wpa_sm_init()
@@ -280,7 +319,8 @@
* not have enough time to get the association information
* event before receiving this 1/4 message, so try to find a
* matching PMKSA cache entry here. */
- sm->cur_pmksa = pmksa_cache_get(sm->pmksa, src_addr, pmkid,
+ sm->cur_pmksa = pmksa_cache_get(sm->pmksa, src_addr,
+ sm->own_addr, pmkid,
NULL, 0);
if (sm->cur_pmksa) {
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
@@ -396,8 +436,8 @@
fils_cache_id);
}
if (!sm->cur_pmksa && pmkid &&
- pmksa_cache_get(sm->pmksa, src_addr, pmkid, NULL,
- 0)) {
+ pmksa_cache_get(sm->pmksa, src_addr, sm->own_addr,
+ pmkid, NULL, 0)) {
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
"RSN: the new PMK matches with the "
"PMKID");
@@ -621,7 +661,7 @@
kdk_len = 0;
ret = wpa_pmk_to_ptk(sm->pmk, sm->pmk_len, "Pairwise key expansion",
- sm->own_addr, sm->bssid, sm->snonce,
+ sm->own_addr, wpa_sm_get_auth_addr(sm), sm->snonce,
key->key_nonce, ptk, akmp,
sm->pairwise_cipher, z, z_len,
kdk_len);
@@ -685,6 +725,139 @@
}
+static u8 * rsn_add_kde(u8 *pos, u32 kde, const u8 *data, size_t data_len)
+{
+ *pos++ = WLAN_EID_VENDOR_SPECIFIC;
+ *pos++ = RSN_SELECTOR_LEN + data_len;
+ RSN_SELECTOR_PUT(pos, kde);
+ pos += RSN_SELECTOR_LEN;
+ os_memcpy(pos, data, data_len);
+ pos += data_len;
+
+ return pos;
+}
+
+
+static size_t wpa_mlo_link_kde_len(struct wpa_sm *sm)
+{
+ int i;
+ unsigned int num_links = 0;
+
+ for (i = 0; i < MAX_NUM_MLO_LINKS; i++) {
+ if (sm->mlo.assoc_link_id != i && (sm->mlo.req_links & BIT(i)))
+ num_links++;
+ }
+
+ return num_links * (RSN_SELECTOR_LEN + 1 + ETH_ALEN + 2);
+}
+
+
+static u8 * wpa_mlo_link_kde(struct wpa_sm *sm, u8 *pos)
+{
+ int i;
+ u8 hdr[1 + ETH_ALEN];
+
+ for (i = 0; i < MAX_NUM_MLO_LINKS; i++) {
+ if (sm->mlo.assoc_link_id == i || !(sm->mlo.req_links & BIT(i)))
+ continue;
+
+ wpa_printf(MSG_DEBUG,
+ "MLO: Add MLO Link %d KDE in EAPOL-Key 2/4", i);
+ hdr[0] = i & 0xF; /* LinkID; no RSNE or RSNXE */
+ os_memcpy(&hdr[1], sm->mlo.links[i].addr, ETH_ALEN);
+ pos = rsn_add_kde(pos, RSN_KEY_DATA_MLO_LINK, hdr, sizeof(hdr));
+ }
+
+ return pos;
+}
+
+
+static bool is_valid_ap_mld_mac_kde(struct wpa_sm *sm, const u8 *mac_kde)
+{
+ return mac_kde &&
+ os_memcmp(mac_kde, sm->mlo.ap_mld_addr, ETH_ALEN) == 0;
+}
+
+
+static void wpas_swap_tkip_mic_keys(struct wpa_ptk *ptk)
+{
+ u8 buf[8];
+
+ /* Supplicant: swap tx/rx Mic keys */
+ os_memcpy(buf, &ptk->tk[16], 8);
+ os_memcpy(&ptk->tk[16], &ptk->tk[24], 8);
+ os_memcpy(&ptk->tk[24], buf, 8);
+ forced_memzero(buf, sizeof(buf));
+}
+
+
+static void wpa_supplicant_process_1_of_4_wpa(struct wpa_sm *sm,
+ const unsigned char *src_addr,
+ const struct wpa_eapol_key *key,
+ u16 ver, const u8 *key_data,
+ size_t key_data_len,
+ enum frame_encryption encrypted)
+{
+ struct wpa_eapol_ie_parse ie;
+ struct wpa_ptk *ptk;
+ int res;
+
+ if (wpa_sm_get_network_ctx(sm) == NULL) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
+ "WPA: No SSID info found (msg 1 of 4)");
+ return;
+ }
+
+ wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
+ "WPA: RX message 1 of 4-Way Handshake from " MACSTR
+ " (ver=%d)", MAC2STR(src_addr), ver);
+
+ os_memset(&ie, 0, sizeof(ie));
+
+ res = wpa_supplicant_get_pmk(sm, src_addr, ie.pmkid);
+ if (res == -2) {
+ wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
+ "WPA: Do not reply to msg 1/4 - requesting full EAP authentication");
+ return;
+ }
+ if (res)
+ goto failed;
+
+ wpa_sm_set_state(sm, WPA_4WAY_HANDSHAKE);
+
+ if (sm->renew_snonce) {
+ if (random_get_bytes(sm->snonce, WPA_NONCE_LEN)) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
+ "WPA: Failed to get random data for SNonce");
+ goto failed;
+ }
+ sm->renew_snonce = 0;
+ wpa_hexdump(MSG_DEBUG, "WPA: Renewed SNonce",
+ sm->snonce, WPA_NONCE_LEN);
+ }
+
+ /* Calculate PTK which will be stored as a temporary PTK until it has
+ * been verified when processing message 3/4. */
+ ptk = &sm->tptk;
+ if (wpa_derive_ptk(sm, src_addr, key, ptk) < 0)
+ goto failed;
+ if (sm->pairwise_cipher == WPA_CIPHER_TKIP)
+ wpas_swap_tkip_mic_keys(ptk);
+ sm->tptk_set = 1;
+
+ if (wpa_supplicant_send_2_of_4(sm, wpa_sm_get_auth_addr(sm), key, ver,
+ sm->snonce, sm->assoc_wpa_ie,
+ sm->assoc_wpa_ie_len, ptk) < 0)
+ goto failed;
+
+ os_memcpy(sm->anonce, key->key_nonce, WPA_NONCE_LEN);
+ return;
+
+failed:
+ wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED);
+}
+
+
static void wpa_supplicant_process_1_of_4(struct wpa_sm *sm,
const unsigned char *src_addr,
const struct wpa_eapol_key *key,
@@ -697,6 +870,7 @@
int res;
u8 *kde, *kde_buf = NULL;
size_t kde_len;
+ size_t mlo_kde_len = 0;
if (encrypted == FRAME_NOT_ENCRYPTED && sm->tk_set &&
wpa_sm_pmf_enabled(sm)) {
@@ -724,19 +898,22 @@
os_memset(&ie, 0, sizeof(ie));
- if (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) {
- /* RSN: msg 1/4 should contain PMKID for the selected PMK */
- wpa_hexdump(MSG_DEBUG, "RSN: msg 1/4 key data",
- key_data, key_data_len);
- if (wpa_supplicant_parse_ies(key_data, key_data_len, &ie) < 0) {
- wpa_printf(MSG_DEBUG,
- "RSN: Discard EAPOL-Key msg 1/4 with invalid IEs/KDEs");
- return;
- }
- if (ie.pmkid) {
- wpa_hexdump(MSG_DEBUG, "RSN: PMKID from "
- "Authenticator", ie.pmkid, PMKID_LEN);
- }
+ /* RSN: msg 1/4 should contain PMKID for the selected PMK */
+ wpa_hexdump(MSG_DEBUG, "RSN: msg 1/4 key data", key_data, key_data_len);
+ if (wpa_supplicant_parse_ies(key_data, key_data_len, &ie) < 0) {
+ wpa_printf(MSG_DEBUG,
+ "RSN: Discard EAPOL-Key msg 1/4 with invalid IEs/KDEs");
+ return;
+ }
+ if (ie.pmkid) {
+ wpa_hexdump(MSG_DEBUG, "RSN: PMKID from Authenticator",
+ ie.pmkid, PMKID_LEN);
+ }
+
+ if (sm->mlo.valid_links && !is_valid_ap_mld_mac_kde(sm, ie.mac_addr)) {
+ wpa_printf(MSG_INFO,
+ "RSN: Discard EAPOL-Key msg 1/4 with invalid AP MLD MAC address KDE");
+ return;
}
res = wpa_supplicant_get_pmk(sm, src_addr, ie.pmkid);
@@ -766,23 +943,23 @@
ptk = &sm->tptk;
if (wpa_derive_ptk(sm, src_addr, key, ptk) < 0)
goto failed;
- if (sm->pairwise_cipher == WPA_CIPHER_TKIP) {
- u8 buf[8];
- /* Supplicant: swap tx/rx Mic keys */
- os_memcpy(buf, &ptk->tk[16], 8);
- os_memcpy(&ptk->tk[16], &ptk->tk[24], 8);
- os_memcpy(&ptk->tk[24], buf, 8);
- forced_memzero(buf, sizeof(buf));
- }
+ if (sm->pairwise_cipher == WPA_CIPHER_TKIP)
+ wpas_swap_tkip_mic_keys(ptk);
sm->tptk_set = 1;
+ /* Add MLO Link KDE and MAC KDE in M2 for ML connection */
+ if (sm->mlo.valid_links)
+ mlo_kde_len = wpa_mlo_link_kde_len(sm) +
+ RSN_SELECTOR_LEN + ETH_ALEN + 2;
+
kde = sm->assoc_wpa_ie;
kde_len = sm->assoc_wpa_ie_len;
kde_buf = os_malloc(kde_len +
2 + RSN_SELECTOR_LEN + 3 +
sm->assoc_rsnxe_len +
2 + RSN_SELECTOR_LEN + 1 +
- 2 + RSN_SELECTOR_LEN + 2);
+ 2 + RSN_SELECTOR_LEN + 2 + mlo_kde_len);
+
if (!kde_buf)
goto failed;
os_memcpy(kde_buf, kde, kde_len);
@@ -856,8 +1033,23 @@
}
#endif /* CONFIG_DPP2 */
- if (wpa_supplicant_send_2_of_4(sm, sm->bssid, key, ver, sm->snonce,
- kde, kde_len, ptk) < 0)
+ if (sm->mlo.valid_links) {
+ u8 *pos;
+
+ /* Add MAC KDE */
+ wpa_printf(MSG_DEBUG, "MLO: Add MAC KDE into EAPOL-Key 2/4");
+ pos = kde + kde_len;
+ pos = rsn_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, sm->own_addr,
+ ETH_ALEN);
+
+ /* Add MLO Link KDE */
+ wpa_printf(MSG_DEBUG, "Add MLO Link KDE(s) into EAPOL-Key 2/4");
+ pos = wpa_mlo_link_kde(sm, pos);
+ kde_len = pos - kde;
+ }
+
+ if (wpa_supplicant_send_2_of_4(sm, wpa_sm_get_auth_addr(sm), key, ver,
+ sm->snonce, kde, kde_len, ptk) < 0)
goto failed;
os_free(kde_buf);
@@ -979,13 +1171,13 @@
wpa_hexdump(MSG_DEBUG, "WPA: RSC", key_rsc, rsclen);
}
- if (wpa_sm_set_key(sm, alg, sm->bssid, sm->keyidx_active, 1, key_rsc,
- rsclen, sm->ptk.tk, keylen,
- KEY_FLAG_PAIRWISE | key_flag) < 0) {
+ if (wpa_sm_set_key(sm, -1, alg, wpa_sm_get_auth_addr(sm),
+ sm->keyidx_active, 1, key_rsc, rsclen, sm->ptk.tk,
+ keylen, KEY_FLAG_PAIRWISE | key_flag) < 0) {
wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
- "WPA: Failed to set PTK to the driver (alg=%d keylen=%d bssid="
+ "WPA: Failed to set PTK to the driver (alg=%d keylen=%d auth_addr="
MACSTR " idx=%d key_flag=0x%x)",
- alg, keylen, MAC2STR(sm->bssid),
+ alg, keylen, MAC2STR(wpa_sm_get_auth_addr(sm)),
sm->keyidx_active, key_flag);
return -1;
}
@@ -1025,14 +1217,16 @@
static int wpa_supplicant_activate_ptk(struct wpa_sm *sm)
{
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
- "WPA: Activate PTK (idx=%d bssid=" MACSTR ")",
- sm->keyidx_active, MAC2STR(sm->bssid));
+ "WPA: Activate PTK (idx=%d auth_addr=" MACSTR ")",
+ sm->keyidx_active, MAC2STR(wpa_sm_get_auth_addr(sm)));
- if (wpa_sm_set_key(sm, 0, sm->bssid, sm->keyidx_active, 0, NULL, 0,
- NULL, 0, KEY_FLAG_PAIRWISE_RX_TX_MODIFY) < 0) {
+ if (wpa_sm_set_key(sm, -1, 0, wpa_sm_get_auth_addr(sm),
+ sm->keyidx_active, 0, NULL, 0, NULL, 0,
+ KEY_FLAG_PAIRWISE_RX_TX_MODIFY) < 0) {
wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
- "WPA: Failed to activate PTK for TX (idx=%d bssid="
- MACSTR ")", sm->keyidx_active, MAC2STR(sm->bssid));
+ "WPA: Failed to activate PTK for TX (idx=%d auth_addr="
+ MACSTR ")", sm->keyidx_active,
+ MAC2STR(wpa_sm_get_auth_addr(sm)));
return -1;
}
return 0;
@@ -1107,7 +1301,7 @@
_gtk = gtk_buf;
}
if (sm->pairwise_cipher == WPA_CIPHER_NONE) {
- if (wpa_sm_set_key(sm, gd->alg, NULL,
+ if (wpa_sm_set_key(sm, -1, gd->alg, NULL,
gd->keyidx, 1, key_rsc, gd->key_rsc_len,
_gtk, gd->gtk_len,
KEY_FLAG_GROUP_RX_TX_DEFAULT) < 0) {
@@ -1117,7 +1311,7 @@
forced_memzero(gtk_buf, sizeof(gtk_buf));
return -1;
}
- } else if (wpa_sm_set_key(sm, gd->alg, broadcast_ether_addr,
+ } else if (wpa_sm_set_key(sm, -1, gd->alg, broadcast_ether_addr,
gd->keyidx, gd->tx, key_rsc, gd->key_rsc_len,
_gtk, gd->gtk_len, KEY_FLAG_GROUP_RX) < 0) {
wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
@@ -1142,6 +1336,56 @@
}
+static int wpa_supplicant_install_mlo_gtk(struct wpa_sm *sm, u8 link_id,
+ const struct wpa_gtk_data *gd,
+ const u8 *key_rsc, int wnm_sleep)
+{
+ const u8 *gtk = gd->gtk;
+
+ /* Detect possible key reinstallation */
+ if ((sm->mlo.links[link_id].gtk.gtk_len == (size_t) gd->gtk_len &&
+ os_memcmp(sm->mlo.links[link_id].gtk.gtk, gd->gtk,
+ sm->mlo.links[link_id].gtk.gtk_len) == 0) ||
+ (sm->mlo.links[link_id].gtk_wnm_sleep.gtk_len ==
+ (size_t) gd->gtk_len &&
+ os_memcmp(sm->mlo.links[link_id].gtk_wnm_sleep.gtk, gd->gtk,
+ sm->mlo.links[link_id].gtk_wnm_sleep.gtk_len) == 0)) {
+ wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
+ "RSN: Not reinstalling already in-use GTK to the driver (link_id=%d keyidx=%d tx=%d len=%d)",
+ link_id, gd->keyidx, gd->tx, gd->gtk_len);
+ return 0;
+ }
+
+ wpa_hexdump_link_key(MSG_DEBUG, link_id, "RSN: Group Key", gd->gtk,
+ gd->gtk_len);
+ wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
+ "RSN: Installing GTK to the driver (link_id=%d keyidx=%d tx=%d len=%d)",
+ link_id, gd->keyidx, gd->tx, gd->gtk_len);
+ wpa_hexdump_link(MSG_DEBUG, link_id, "RSN: RSC",
+ key_rsc, gd->key_rsc_len);
+ if (wpa_sm_set_key(sm, link_id, gd->alg, broadcast_ether_addr,
+ gd->keyidx, gd->tx, key_rsc, gd->key_rsc_len, gtk,
+ gd->gtk_len, KEY_FLAG_GROUP_RX) < 0) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
+ "RSN: Failed to set GTK to the driver (link_id=%d alg=%d keylen=%d keyidx=%d)",
+ link_id, gd->alg, gd->gtk_len, gd->keyidx);
+ return -1;
+ }
+
+ if (wnm_sleep) {
+ sm->mlo.links[link_id].gtk_wnm_sleep.gtk_len = gd->gtk_len;
+ os_memcpy(sm->mlo.links[link_id].gtk_wnm_sleep.gtk, gd->gtk,
+ sm->mlo.links[link_id].gtk_wnm_sleep.gtk_len);
+ } else {
+ sm->mlo.links[link_id].gtk.gtk_len = gd->gtk_len;
+ os_memcpy(sm->mlo.links[link_id].gtk.gtk, gd->gtk,
+ sm->mlo.links[link_id].gtk.gtk_len);
+ }
+
+ return 0;
+}
+
+
static int wpa_supplicant_gtk_tx_bit_workaround(const struct wpa_sm *sm,
int tx)
{
@@ -1190,6 +1434,84 @@
}
+static int wpa_supplicant_mlo_gtk(struct wpa_sm *sm, u8 link_id, const u8 *gtk,
+ size_t gtk_len, int key_info)
+{
+ struct wpa_gtk_data gd;
+ const u8 *key_rsc;
+ int ret;
+
+ /*
+ * MLO GTK KDE format:
+ * KeyID[bits 0-1], Tx [bit 2], Reserved [bit 3], link id [4-7]
+ * PN
+ * GTK
+ */
+ os_memset(&gd, 0, sizeof(gd));
+ wpa_hexdump_link_key(MSG_DEBUG, link_id,
+ "RSN: received GTK in pairwise handshake",
+ gtk, gtk_len);
+
+ if (gtk_len < RSN_MLO_GTK_KDE_PREFIX_LENGTH ||
+ gtk_len - RSN_MLO_GTK_KDE_PREFIX_LENGTH > sizeof(gd.gtk))
+ return -1;
+
+ gd.keyidx = gtk[0] & 0x3;
+ gtk += 1;
+ gtk_len -= 1;
+
+ key_rsc = gtk;
+
+ gtk += 6;
+ gtk_len -= 6;
+
+ os_memcpy(gd.gtk, gtk, gtk_len);
+ gd.gtk_len = gtk_len;
+
+ ret = 0;
+ if (wpa_supplicant_check_group_cipher(sm, sm->group_cipher, gtk_len,
+ gtk_len, &gd.key_rsc_len,
+ &gd.alg) ||
+ wpa_supplicant_install_mlo_gtk(sm, link_id, &gd, key_rsc, 0)) {
+ wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
+ "RSN: Failed to install GTK for MLO Link ID %u",
+ link_id);
+ ret = -1;
+ goto out;
+ }
+
+out:
+ forced_memzero(&gd, sizeof(gd));
+ return ret;
+}
+
+
+static int wpa_supplicant_pairwise_mlo_gtk(struct wpa_sm *sm,
+ const struct wpa_eapol_key *key,
+ struct wpa_eapol_ie_parse *ie,
+ int key_info)
+{
+ u8 i;
+
+ for (i = 0; i < MAX_NUM_MLO_LINKS; i++) {
+ if (!(sm->mlo.valid_links & BIT(i)))
+ continue;
+
+ if (!ie->mlo_gtk[i]) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_ERROR,
+ "MLO RSN: GTK not found for link ID %u", i);
+ return -1;
+ }
+
+ if (wpa_supplicant_mlo_gtk(sm, i, ie->mlo_gtk[i],
+ ie->mlo_gtk_len[i], key_info))
+ return -1;
+ }
+
+ return 0;
+}
+
+
static int wpa_supplicant_pairwise_gtk(struct wpa_sm *sm,
const struct wpa_eapol_key *key,
const u8 *gtk, size_t gtk_len,
@@ -1270,7 +1592,7 @@
"WPA: Invalid IGTK KeyID %d", keyidx);
return -1;
}
- if (wpa_sm_set_key(sm, wpa_cipher_to_alg(sm->mgmt_group_cipher),
+ if (wpa_sm_set_key(sm, -1, wpa_cipher_to_alg(sm->mgmt_group_cipher),
broadcast_ether_addr,
keyidx, 0, igtk->pn, sizeof(igtk->pn),
igtk->igtk, len, KEY_FLAG_GROUP_RX) < 0) {
@@ -1339,7 +1661,7 @@
"WPA: Invalid BIGTK KeyID %d", keyidx);
return -1;
}
- if (wpa_sm_set_key(sm, wpa_cipher_to_alg(sm->mgmt_group_cipher),
+ if (wpa_sm_set_key(sm, -1, wpa_cipher_to_alg(sm->mgmt_group_cipher),
broadcast_ether_addr,
keyidx, 0, bigtk->pn, sizeof(bigtk->pn),
bigtk->bigtk, len, KEY_FLAG_GROUP_RX) < 0) {
@@ -1361,6 +1683,180 @@
}
+static int wpa_supplicant_install_mlo_igtk(struct wpa_sm *sm, u8 link_id,
+ const struct rsn_mlo_igtk_kde *igtk,
+ int wnm_sleep)
+{
+ size_t len = wpa_cipher_key_len(sm->mgmt_group_cipher);
+ u16 keyidx = WPA_GET_LE16(igtk->keyid);
+
+ /* Detect possible key reinstallation */
+ if ((sm->mlo.links[link_id].igtk.igtk_len == len &&
+ os_memcmp(sm->mlo.links[link_id].igtk.igtk, igtk->igtk,
+ sm->mlo.links[link_id].igtk.igtk_len) == 0) ||
+ (sm->mlo.links[link_id].igtk_wnm_sleep.igtk_len == len &&
+ os_memcmp(sm->mlo.links[link_id].igtk_wnm_sleep.igtk, igtk->igtk,
+ sm->mlo.links[link_id].igtk_wnm_sleep.igtk_len) == 0)) {
+ wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
+ "RSN: Not reinstalling already in-use IGTK to the driver (link_id=%d keyidx=%d)",
+ link_id, keyidx);
+ return 0;
+ }
+
+ wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
+ "RSN: MLO Link %u IGTK keyid %d pn " COMPACT_MACSTR,
+ link_id, keyidx, MAC2STR(igtk->pn));
+ wpa_hexdump_link_key(MSG_DEBUG, link_id, "RSN: IGTK", igtk->igtk, len);
+ if (keyidx > 4095) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
+ "RSN: Invalid MLO Link %d IGTK KeyID %d", link_id,
+ keyidx);
+ return -1;
+ }
+ if (wpa_sm_set_key(sm, link_id,
+ wpa_cipher_to_alg(sm->mgmt_group_cipher),
+ broadcast_ether_addr, keyidx, 0, igtk->pn,
+ sizeof(igtk->pn), igtk->igtk, len,
+ KEY_FLAG_GROUP_RX) < 0) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
+ "RSN: Failed to configure MLO Link %d IGTK to the driver",
+ link_id);
+ return -1;
+ }
+
+ if (wnm_sleep) {
+ sm->mlo.links[link_id].igtk_wnm_sleep.igtk_len = len;
+ os_memcpy(sm->mlo.links[link_id].igtk_wnm_sleep.igtk,
+ igtk->igtk,
+ sm->mlo.links[link_id].igtk_wnm_sleep.igtk_len);
+ } else {
+ sm->mlo.links[link_id].igtk.igtk_len = len;
+ os_memcpy(sm->mlo.links[link_id].igtk.igtk, igtk->igtk,
+ sm->mlo.links[link_id].igtk.igtk_len);
+ }
+
+ return 0;
+}
+
+
+static int
+wpa_supplicant_install_mlo_bigtk(struct wpa_sm *sm, u8 link_id,
+ const struct rsn_mlo_bigtk_kde *bigtk,
+ int wnm_sleep)
+{
+ size_t len = wpa_cipher_key_len(sm->mgmt_group_cipher);
+ u16 keyidx = WPA_GET_LE16(bigtk->keyid);
+
+ /* Detect possible key reinstallation */
+ if ((sm->mlo.links[link_id].bigtk.bigtk_len == len &&
+ os_memcmp(sm->mlo.links[link_id].bigtk.bigtk, bigtk->bigtk,
+ sm->mlo.links[link_id].bigtk.bigtk_len) == 0) ||
+ (sm->mlo.links[link_id].bigtk_wnm_sleep.bigtk_len == len &&
+ os_memcmp(sm->mlo.links[link_id].bigtk_wnm_sleep.bigtk,
+ bigtk->bigtk,
+ sm->mlo.links[link_id].bigtk_wnm_sleep.bigtk_len) ==
+ 0)) {
+ wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
+ "RSN: Not reinstalling already in-use BIGTK to the driver (link_id=%d keyidx=%d)",
+ link_id, keyidx);
+ return 0;
+ }
+
+ wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
+ "RSN: MLO Link %u BIGTK keyid %d pn " COMPACT_MACSTR,
+ link_id, keyidx, MAC2STR(bigtk->pn));
+ wpa_hexdump_link_key(MSG_DEBUG, link_id, "RSN: BIGTK", bigtk->bigtk,
+ len);
+ if (keyidx < 6 || keyidx > 7) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
+ "RSN: Invalid MLO Link %d BIGTK KeyID %d", link_id,
+ keyidx);
+ return -1;
+ }
+ if (wpa_sm_set_key(sm, link_id,
+ wpa_cipher_to_alg(sm->mgmt_group_cipher),
+ broadcast_ether_addr, keyidx, 0, bigtk->pn,
+ sizeof(bigtk->pn), bigtk->bigtk, len,
+ KEY_FLAG_GROUP_RX) < 0) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
+ "RSN: Failed to configure MLO Link %d BIGTK to the driver",
+ link_id);
+ return -1;
+ }
+
+ if (wnm_sleep) {
+ sm->mlo.links[link_id].bigtk_wnm_sleep.bigtk_len = len;
+ os_memcpy(sm->mlo.links[link_id].bigtk_wnm_sleep.bigtk,
+ bigtk->bigtk,
+ sm->mlo.links[link_id].bigtk_wnm_sleep.bigtk_len);
+ } else {
+ sm->mlo.links[link_id].bigtk.bigtk_len = len;
+ os_memcpy(sm->mlo.links[link_id].bigtk.bigtk, bigtk->bigtk,
+ sm->mlo.links[link_id].bigtk.bigtk_len);
+ }
+
+ return 0;
+}
+
+
+static int _mlo_ieee80211w_set_keys(struct wpa_sm *sm, u8 link_id,
+ struct wpa_eapol_ie_parse *ie)
+{
+ size_t len;
+
+ if (ie->mlo_igtk[link_id]) {
+ len = wpa_cipher_key_len(sm->mgmt_group_cipher);
+ if (ie->mlo_igtk_len[link_id] !=
+ RSN_MLO_IGTK_KDE_PREFIX_LENGTH + len)
+ return -1;
+
+ if (wpa_supplicant_install_mlo_igtk(
+ sm, link_id,
+ (const struct rsn_mlo_igtk_kde *)
+ ie->mlo_igtk[link_id],
+ 0) < 0)
+ return -1;
+ }
+
+ if (ie->mlo_bigtk[link_id] && sm->beacon_prot) {
+ len = wpa_cipher_key_len(sm->mgmt_group_cipher);
+ if (ie->mlo_bigtk_len[link_id] !=
+ RSN_MLO_BIGTK_KDE_PREFIX_LENGTH + len)
+ return -1;
+
+ if (wpa_supplicant_install_mlo_bigtk(
+ sm, link_id,
+ (const struct rsn_mlo_bigtk_kde *)
+ ie->mlo_bigtk[link_id],
+ 0) < 0)
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static int mlo_ieee80211w_set_keys(struct wpa_sm *sm,
+ struct wpa_eapol_ie_parse *ie)
+{
+ u8 i;
+
+ if (!wpa_cipher_valid_mgmt_group(sm->mgmt_group_cipher) ||
+ sm->mgmt_group_cipher == WPA_CIPHER_GTK_NOT_USED)
+ return 0;
+
+ for (i = 0; i < MAX_NUM_MLO_LINKS; i++) {
+ if (!(sm->mlo.valid_links & BIT(i)))
+ continue;
+
+ if (_mlo_ieee80211w_set_keys(sm, i, ie))
+ return -1;
+ }
+
+ return 0;
+}
+
+
static int ieee80211w_set_keys(struct wpa_sm *sm,
struct wpa_eapol_ie_parse *ie)
{
@@ -1664,13 +2160,32 @@
size_t mic_len, hdrlen, rlen;
struct wpa_eapol_key *reply;
u8 *rbuf, *key_mic;
+ u8 *kde = NULL;
+ size_t kde_len = 0;
+
+ if (sm->mlo.valid_links) {
+ u8 *pos;
+
+ kde = os_malloc(RSN_SELECTOR_LEN + ETH_ALEN + 2);
+ if (!kde)
+ return -1;
+
+ /* Add MAC KDE */
+ wpa_printf(MSG_DEBUG, "MLO: Add MAC KDE into EAPOL-Key 4/4");
+ pos = kde;
+ pos = rsn_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, sm->own_addr,
+ ETH_ALEN);
+ kde_len = pos - kde;
+ }
mic_len = wpa_mic_len(sm->key_mgmt, sm->pmk_len);
hdrlen = sizeof(*reply) + mic_len + 2;
rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL,
- hdrlen, &rlen, (void *) &reply);
- if (rbuf == NULL)
+ hdrlen + kde_len, &rlen, (void *) &reply);
+ if (!rbuf) {
+ os_free(kde);
return -1;
+ }
reply->type = (sm->proto == WPA_PROTO_RSN ||
sm->proto == WPA_PROTO_OSEN) ?
@@ -1690,7 +2205,11 @@
WPA_REPLAY_COUNTER_LEN);
key_mic = (u8 *) (reply + 1);
- WPA_PUT_BE16(key_mic + mic_len, 0);
+ WPA_PUT_BE16(key_mic + mic_len, kde_len); /* Key Data length */
+ if (kde) {
+ os_memcpy(key_mic + mic_len + 2, kde, kde_len); /* Key Data */
+ os_free(kde);
+ }
wpa_dbg(sm->ctx->msg_ctx, MSG_INFO, "WPA: Sending EAPOL-Key 4/4");
return wpa_eapol_key_send(sm, ptk, ver, dst, ETH_P_EAPOL, rbuf, rlen,
@@ -1698,6 +2217,201 @@
}
+static int wpa_supplicant_validate_link_kde(struct wpa_sm *sm, u8 link_id,
+ const u8 *link_kde,
+ size_t link_kde_len)
+{
+ size_t rsne_len = 0, rsnxe_len = 0;
+ const u8 *rsne = NULL, *rsnxe = NULL;
+
+ if (!link_kde ||
+ link_kde_len < RSN_MLO_LINK_KDE_LINK_MAC_INDEX + ETH_ALEN) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
+ "RSN: MLO Link KDE is not found for link ID %d",
+ link_id);
+ return -1;
+ }
+
+ if (os_memcmp(sm->mlo.links[link_id].bssid,
+ &link_kde[RSN_MLO_LINK_KDE_LINK_MAC_INDEX],
+ ETH_ALEN) != 0) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
+ "RSN: MLO Link %u MAC address (" MACSTR
+ ") not matching association response (" MACSTR ")",
+ link_id,
+ MAC2STR(&link_kde[RSN_MLO_LINK_KDE_LINK_MAC_INDEX]),
+ MAC2STR(sm->mlo.links[link_id].bssid));
+ return -1;
+ }
+
+ if (link_kde[0] & RSN_MLO_LINK_KDE_LI_RSNE_INFO) {
+ rsne = link_kde + RSN_MLO_LINK_KDE_FIXED_LENGTH;
+ if (link_kde_len < RSN_MLO_LINK_KDE_FIXED_LENGTH + 2 ||
+ link_kde_len <
+ (size_t) (RSN_MLO_LINK_KDE_FIXED_LENGTH + 2 + rsne[1])) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
+ "RSN: No room for link %u RSNE in MLO Link KDE",
+ link_id);
+ return -1;
+ }
+
+ rsne_len = rsne[1] + 2;
+ }
+
+ if (!rsne) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
+ "RSN: RSNE not present in MLO Link %u KDE", link_id);
+ return -1;
+ }
+
+ if (link_kde[0] & RSN_MLO_LINK_KDE_LI_RSNXE_INFO) {
+ rsnxe = link_kde + RSN_MLO_LINK_KDE_FIXED_LENGTH + rsne_len;
+ if (link_kde_len <
+ (RSN_MLO_LINK_KDE_FIXED_LENGTH + rsne_len + 2) ||
+ link_kde_len <
+ (RSN_MLO_LINK_KDE_FIXED_LENGTH + rsne_len + 2 + rsnxe[1])) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
+ "RSN: No room for link %u RSNXE in MLO Link KDE",
+ link_id);
+ return -1;
+ }
+
+ rsnxe_len = rsnxe[1] + 2;
+ }
+
+ if (wpa_compare_rsn_ie(wpa_key_mgmt_ft(sm->key_mgmt),
+ sm->mlo.links[link_id].ap_rsne,
+ sm->mlo.links[link_id].ap_rsne_len,
+ rsne, rsne_len)) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
+ "RSN MLO: IE in 3/4 msg does not match with IE in Beacon/ProbeResp for link ID %u",
+ link_id);
+ wpa_hexdump(MSG_INFO, "RSNE in Beacon/ProbeResp",
+ sm->mlo.links[link_id].ap_rsne,
+ sm->mlo.links[link_id].ap_rsne_len);
+ wpa_hexdump(MSG_INFO, "RSNE in EAPOL-Key msg 3/4",
+ rsne, rsne_len);
+ return -1;
+ }
+
+ if ((sm->mlo.links[link_id].ap_rsnxe && !rsnxe) ||
+ (!sm->mlo.links[link_id].ap_rsnxe && rsnxe) ||
+ (sm->mlo.links[link_id].ap_rsnxe && rsnxe &&
+ (sm->mlo.links[link_id].ap_rsnxe_len != rsnxe_len ||
+ os_memcmp(sm->mlo.links[link_id].ap_rsnxe, rsnxe,
+ sm->mlo.links[link_id].ap_rsnxe_len) != 0))) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
+ "RSN MLO: RSNXE mismatch between Beacon/ProbeResp and EAPOL-Key msg 3/4 for link ID %u",
+ link_id);
+ wpa_hexdump(MSG_INFO, "RSNXE in Beacon/ProbeResp",
+ sm->mlo.links[link_id].ap_rsnxe,
+ sm->mlo.links[link_id].ap_rsnxe_len);
+ wpa_hexdump(MSG_INFO, "RSNXE in EAPOL-Key msg 3/4",
+ rsnxe, rsnxe_len);
+ wpa_sm_deauthenticate(sm, WLAN_REASON_IE_IN_4WAY_DIFFERS);
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static int wpa_validate_mlo_ieee80211w_kdes(struct wpa_sm *sm,
+ u8 link_id,
+ struct wpa_eapol_ie_parse *ie)
+{
+ if (ie->mlo_igtk[link_id] &&
+ ie->mlo_igtk_len[link_id] != RSN_MLO_IGTK_KDE_PREFIX_LENGTH +
+ (unsigned int) wpa_cipher_key_len(sm->mgmt_group_cipher)) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
+ "RSN MLO: Invalid IGTK KDE length %lu for link ID %u",
+ (unsigned long) ie->mlo_igtk_len, link_id);
+ return -1;
+ }
+
+ if (!sm->beacon_prot)
+ return 0;
+
+ if (ie->mlo_bigtk[link_id] &&
+ ie->mlo_bigtk_len[link_id] != RSN_MLO_BIGTK_KDE_PREFIX_LENGTH +
+ (unsigned int) wpa_cipher_key_len(sm->mgmt_group_cipher)) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
+ "RSN MLO: Invalid BIGTK KDE length %lu for link ID %u",
+ (unsigned long) ie->mlo_bigtk_len, link_id);
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static void wpa_supplicant_process_3_of_4_wpa(struct wpa_sm *sm,
+ const struct wpa_eapol_key *key,
+ u16 ver, const u8 *key_data,
+ size_t key_data_len)
+{
+ u16 key_info, keylen;
+ struct wpa_eapol_ie_parse ie;
+
+ wpa_sm_set_state(sm, WPA_4WAY_HANDSHAKE);
+ wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
+ "WPA: RX message 3 of 4-Way Handshake from " MACSTR
+ " (ver=%d)", MAC2STR(sm->bssid), ver);
+
+ key_info = WPA_GET_BE16(key->key_info);
+
+ wpa_hexdump(MSG_DEBUG, "WPA: IE KeyData", key_data, key_data_len);
+ if (wpa_supplicant_parse_ies(key_data, key_data_len, &ie) < 0)
+ goto failed;
+
+ if (wpa_supplicant_validate_ie(sm, sm->bssid, &ie) < 0)
+ goto failed;
+
+ if (os_memcmp(sm->anonce, key->key_nonce, WPA_NONCE_LEN) != 0) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
+ "WPA: ANonce from message 1 of 4-Way Handshake differs from 3 of 4-Way Handshake - drop packet (src="
+ MACSTR ")", MAC2STR(sm->bssid));
+ goto failed;
+ }
+
+ keylen = WPA_GET_BE16(key->key_length);
+ if (keylen != wpa_cipher_key_len(sm->pairwise_cipher)) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
+ "WPA: Invalid %s key length %d (src=" MACSTR ")",
+ wpa_cipher_txt(sm->pairwise_cipher), keylen,
+ MAC2STR(sm->bssid));
+ goto failed;
+ }
+
+ if (wpa_supplicant_send_4_of_4(sm, wpa_sm_get_auth_addr(sm), key, ver,
+ key_info, &sm->ptk) < 0)
+ goto failed;
+
+ /* SNonce was successfully used in msg 3/4, so mark it to be renewed
+ * for the next 4-Way Handshake. If msg 3 is received again, the old
+ * SNonce will still be used to avoid changing PTK. */
+ sm->renew_snonce = 1;
+
+ if ((key_info & WPA_KEY_INFO_INSTALL) &&
+ wpa_supplicant_install_ptk(sm, key, KEY_FLAG_RX_TX))
+ goto failed;
+
+ if (key_info & WPA_KEY_INFO_SECURE) {
+ wpa_sm_mlme_setprotection(
+ sm, sm->bssid, MLME_SETPROTECTION_PROTECT_TYPE_RX,
+ MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
+ eapol_sm_notify_portValid(sm->eapol, true);
+ }
+ wpa_sm_set_state(sm, WPA_GROUP_HANDSHAKE);
+
+ sm->msg_3_of_4_ok = 1;
+ return;
+
+failed:
+ wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED);
+}
+
+
static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm,
const struct wpa_eapol_key *key,
u16 ver, const u8 *key_data,
@@ -1705,28 +2419,83 @@
{
u16 key_info, keylen;
struct wpa_eapol_ie_parse ie;
+ bool mlo = sm->mlo.valid_links;
+ int i;
wpa_sm_set_state(sm, WPA_4WAY_HANDSHAKE);
- wpa_dbg(sm->ctx->msg_ctx, MSG_INFO, "WPA: RX message 3 of 4-Way "
- "Handshake from " MACSTR " (ver=%d)", MAC2STR(sm->bssid), ver);
+ wpa_dbg(sm->ctx->msg_ctx, MSG_INFO,
+ "RSN: RX message 3 of 4-Way Handshake from " MACSTR
+ " (ver=%d)%s", MAC2STR(sm->bssid), ver, mlo ? " (MLO)" : "");
key_info = WPA_GET_BE16(key->key_info);
wpa_hexdump(MSG_DEBUG, "WPA: IE KeyData", key_data, key_data_len);
if (wpa_supplicant_parse_ies(key_data, key_data_len, &ie) < 0)
goto failed;
- if (ie.gtk && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
+
+ if (mlo && !ie.valid_mlo_gtks) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
+ "MLO RSN: No GTK KDE included in EAPOL-Key msg 3/4");
+ goto failed;
+ }
+ if (mlo &&
+ (key_info &
+ (WPA_KEY_INFO_ENCR_KEY_DATA | WPA_KEY_INFO_INSTALL |
+ WPA_KEY_INFO_SECURE)) !=
+ (WPA_KEY_INFO_ENCR_KEY_DATA | WPA_KEY_INFO_INSTALL |
+ WPA_KEY_INFO_SECURE)) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
+ "RSN MLO: Invalid key info (0x%x) in EAPOL-Key msg 3/4",
+ key_info);
+ goto failed;
+ }
+
+ if (mlo && !is_valid_ap_mld_mac_kde(sm, ie.mac_addr)) {
+ wpa_printf(MSG_DEBUG, "RSN: Invalid AP MLD MAC address KDE");
+ goto failed;
+ }
+
+ for (i = 0; mlo && i < MAX_NUM_MLD_LINKS; i++) {
+ if (!(sm->mlo.req_links & BIT(i)))
+ continue;
+
+ if (wpa_supplicant_validate_link_kde(sm, i, ie.mlo_link[i],
+ ie.mlo_link_len[i]) < 0)
+ goto failed;
+
+ if (!(sm->mlo.valid_links & BIT(i)))
+ continue;
+
+ if (!ie.mlo_gtk[i]) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_ERROR,
+ "RSN: GTK not found for link ID %u", i);
+ goto failed;
+ }
+
+ if (sm->mgmt_group_cipher != WPA_CIPHER_GTK_NOT_USED &&
+ wpa_cipher_valid_mgmt_group(sm->mgmt_group_cipher) &&
+ wpa_validate_mlo_ieee80211w_kdes(sm, i, &ie) < 0)
+ goto failed;
+ }
+
+#ifdef CONFIG_IEEE80211R
+ if (mlo && wpa_key_mgmt_ft(sm->key_mgmt) &&
+ wpa_supplicant_validate_ie_ft(sm, sm->bssid, &ie) < 0)
+ goto failed;
+#endif /* CONFIG_IEEE80211R */
+
+ if (!mlo && ie.gtk && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
"WPA: GTK IE in unencrypted key data");
goto failed;
}
- if (ie.igtk && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
+ if (!mlo && ie.igtk && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
"WPA: IGTK KDE in unencrypted key data");
goto failed;
}
- if (ie.igtk &&
+ if (!mlo && ie.igtk &&
sm->mgmt_group_cipher != WPA_CIPHER_GTK_NOT_USED &&
wpa_cipher_valid_mgmt_group(sm->mgmt_group_cipher) &&
ie.igtk_len != WPA_IGTK_KDE_PREFIX_LEN +
@@ -1737,7 +2506,7 @@
goto failed;
}
- if (wpa_supplicant_validate_ie(sm, sm->bssid, &ie) < 0)
+ if (!mlo && wpa_supplicant_validate_ie(sm, sm->bssid, &ie) < 0)
goto failed;
if (wpa_handle_ext_key_id(sm, &ie))
@@ -1807,10 +2576,9 @@
wpa_supplicant_install_ptk(sm, key, KEY_FLAG_RX))
goto failed;
- if (wpa_supplicant_send_4_of_4(sm, sm->bssid, key, ver, key_info,
- &sm->ptk) < 0) {
+ if (wpa_supplicant_send_4_of_4(sm, wpa_sm_get_auth_addr(sm), key, ver,
+ key_info, &sm->ptk) < 0)
goto failed;
- }
/* SNonce was successfully used in msg 3/4, so mark it to be renewed
* for the next 4-Way Handshake. If msg 3 is received again, the old
@@ -1837,7 +2605,14 @@
}
wpa_sm_set_state(sm, WPA_GROUP_HANDSHAKE);
- if (sm->group_cipher == WPA_CIPHER_GTK_NOT_USED) {
+ if (mlo) {
+ if (wpa_supplicant_pairwise_mlo_gtk(sm, key, &ie,
+ key_info) < 0) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
+ "MLO RSN: Failed to configure MLO GTKs");
+ goto failed;
+ }
+ } else if (sm->group_cipher == WPA_CIPHER_GTK_NOT_USED) {
/* No GTK to be set to the driver */
} else if (!ie.gtk && sm->proto == WPA_PROTO_RSN) {
wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
@@ -1851,17 +2626,18 @@
goto failed;
}
- if (ieee80211w_set_keys(sm, &ie) < 0) {
+ if ((mlo && mlo_ieee80211w_set_keys(sm, &ie) < 0) ||
+ (!mlo && ieee80211w_set_keys(sm, &ie) < 0)) {
wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
"RSN: Failed to configure IGTK");
goto failed;
}
- if (sm->group_cipher == WPA_CIPHER_GTK_NOT_USED || ie.gtk)
+ if (mlo || sm->group_cipher == WPA_CIPHER_GTK_NOT_USED || ie.gtk)
wpa_supplicant_key_neg_complete(sm, sm->bssid,
key_info & WPA_KEY_INFO_SECURE);
- if (ie.gtk)
+ if (mlo || ie.gtk)
wpa_sm_set_rekey_offload(sm);
/* Add PMKSA cache entry for Suite B AKMs here since PMKID can be
@@ -1875,7 +2651,7 @@
sa = pmksa_cache_add(sm->pmksa, sm->pmk, sm->pmk_len, NULL,
sm->ptk.kck, sm->ptk.kck_len,
- sm->bssid, sm->own_addr,
+ wpa_sm_get_auth_addr(sm), sm->own_addr,
sm->network_ctx, sm->key_mgmt, NULL);
if (!sm->cur_pmksa)
sm->cur_pmksa = sa;
@@ -1891,173 +2667,6 @@
}
-static int wpa_supplicant_process_1_of_2_rsn(struct wpa_sm *sm,
- const u8 *keydata,
- size_t keydatalen,
- u16 key_info,
- struct wpa_gtk_data *gd)
-{
- int maxkeylen;
- struct wpa_eapol_ie_parse ie;
- u16 gtk_len;
-
- wpa_hexdump_key(MSG_DEBUG, "RSN: msg 1/2 key data",
- keydata, keydatalen);
- if (wpa_supplicant_parse_ies(keydata, keydatalen, &ie) < 0)
- return -1;
- if (ie.gtk && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
- wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
- "WPA: GTK IE in unencrypted key data");
- return -1;
- }
- if (ie.gtk == NULL) {
- wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
- "WPA: No GTK IE in Group Key msg 1/2");
- return -1;
- }
- gtk_len = ie.gtk_len;
- if (gtk_len < 2) {
- wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
- "RSN: Invalid GTK KDE length (%u) in Group Key msg 1/2",
- gtk_len);
- return -1;
- }
- gtk_len -= 2;
- if (gtk_len > sizeof(gd->gtk)) {
- wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
- "RSN: Too long GTK in GTK KDE (len=%u)", gtk_len);
- return -1;
- }
- maxkeylen = gd->gtk_len = gtk_len;
-
-#ifdef CONFIG_OCV
- if (wpa_sm_ocv_enabled(sm)) {
- struct wpa_channel_info ci;
-
- if (wpa_sm_channel_info(sm, &ci) != 0) {
- wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
- "Failed to get channel info to validate received OCI in EAPOL-Key group msg 1/2");
- return -1;
- }
-
- if (ocv_verify_tx_params(ie.oci, ie.oci_len, &ci,
- channel_width_to_int(ci.chanwidth),
- ci.seg1_idx) != OCI_SUCCESS) {
- wpa_msg(sm->ctx->msg_ctx, MSG_INFO, OCV_FAILURE
- "addr=" MACSTR " frame=eapol-key-g1 error=%s",
- MAC2STR(sm->bssid), ocv_errorstr);
- return -1;
- }
- }
-#endif /* CONFIG_OCV */
-
- if (wpa_supplicant_check_group_cipher(sm, sm->group_cipher,
- gtk_len, maxkeylen,
- &gd->key_rsc_len, &gd->alg))
- return -1;
-
- wpa_hexdump_key(MSG_DEBUG, "RSN: received GTK in group key handshake",
- ie.gtk, 2 + gtk_len);
- gd->keyidx = ie.gtk[0] & 0x3;
- gd->tx = wpa_supplicant_gtk_tx_bit_workaround(sm,
- !!(ie.gtk[0] & BIT(2)));
- os_memcpy(gd->gtk, ie.gtk + 2, gtk_len);
-
- if (ieee80211w_set_keys(sm, &ie) < 0)
- wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
- "RSN: Failed to configure IGTK");
-
- return 0;
-}
-
-
-static int wpa_supplicant_process_1_of_2_wpa(struct wpa_sm *sm,
- const struct wpa_eapol_key *key,
- const u8 *key_data,
- size_t key_data_len, u16 key_info,
- u16 ver, struct wpa_gtk_data *gd)
-{
- size_t maxkeylen;
- u16 gtk_len;
-
- gtk_len = WPA_GET_BE16(key->key_length);
- maxkeylen = key_data_len;
- if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
- if (maxkeylen < 8) {
- wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
- "WPA: Too short maxkeylen (%lu)",
- (unsigned long) maxkeylen);
- return -1;
- }
- maxkeylen -= 8;
- }
-
- if (gtk_len > maxkeylen ||
- wpa_supplicant_check_group_cipher(sm, sm->group_cipher,
- gtk_len, maxkeylen,
- &gd->key_rsc_len, &gd->alg))
- return -1;
-
- gd->gtk_len = gtk_len;
- gd->keyidx = (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) >>
- WPA_KEY_INFO_KEY_INDEX_SHIFT;
- if (ver == WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 && sm->ptk.kek_len == 16) {
-#ifdef CONFIG_NO_RC4
- wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
- "WPA: RC4 not supported in the build");
- return -1;
-#else /* CONFIG_NO_RC4 */
- u8 ek[32];
- if (key_data_len > sizeof(gd->gtk)) {
- wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
- "WPA: RC4 key data too long (%lu)",
- (unsigned long) key_data_len);
- return -1;
- }
- os_memcpy(ek, key->key_iv, 16);
- os_memcpy(ek + 16, sm->ptk.kek, sm->ptk.kek_len);
- os_memcpy(gd->gtk, key_data, key_data_len);
- if (rc4_skip(ek, 32, 256, gd->gtk, key_data_len)) {
- forced_memzero(ek, sizeof(ek));
- wpa_msg(sm->ctx->msg_ctx, MSG_ERROR,
- "WPA: RC4 failed");
- return -1;
- }
- forced_memzero(ek, sizeof(ek));
-#endif /* CONFIG_NO_RC4 */
- } else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
- if (maxkeylen % 8) {
- wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
- "WPA: Unsupported AES-WRAP len %lu",
- (unsigned long) maxkeylen);
- return -1;
- }
- if (maxkeylen > sizeof(gd->gtk)) {
- wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
- "WPA: AES-WRAP key data "
- "too long (keydatalen=%lu maxkeylen=%lu)",
- (unsigned long) key_data_len,
- (unsigned long) maxkeylen);
- return -1;
- }
- if (aes_unwrap(sm->ptk.kek, sm->ptk.kek_len, maxkeylen / 8,
- key_data, gd->gtk)) {
- wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
- "WPA: AES unwrap failed - could not decrypt "
- "GTK");
- return -1;
- }
- } else {
- wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
- "WPA: Unsupported key_info type %d", ver);
- return -1;
- }
- gd->tx = wpa_supplicant_gtk_tx_bit_workaround(
- sm, !!(key_info & WPA_KEY_INFO_TXRX));
- return 0;
-}
-
-
static int wpa_supplicant_send_2_of_2(struct wpa_sm *sm,
const struct wpa_eapol_key *key,
int ver, u16 key_info)
@@ -2141,19 +2750,121 @@
}
-static void wpa_supplicant_process_1_of_2(struct wpa_sm *sm,
- const unsigned char *src_addr,
- const struct wpa_eapol_key *key,
- const u8 *key_data,
- size_t key_data_len, u16 ver)
+static void wpa_supplicant_process_mlo_1_of_2(struct wpa_sm *sm,
+ const unsigned char *src_addr,
+ const struct wpa_eapol_key *key,
+ const u8 *key_data,
+ size_t key_data_len, u16 ver)
{
u16 key_info;
- int rekey, ret;
- struct wpa_gtk_data gd;
- const u8 *key_rsc;
+ u8 i;
+ struct wpa_eapol_ie_parse ie;
if (!sm->msg_3_of_4_ok && !wpa_fils_is_completed(sm)) {
wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
+ "MLO RSN: Group Key Handshake started prior to completion of 4-way handshake");
+ goto failed;
+ }
+
+ wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "MLO RSN: RX message 1 of Group "
+ "Key Handshake from " MACSTR " (ver=%d)", MAC2STR(src_addr),
+ ver);
+
+ key_info = WPA_GET_BE16(key->key_info);
+
+ wpa_sm_set_state(sm, WPA_GROUP_HANDSHAKE);
+
+ wpa_hexdump_key(MSG_DEBUG, "MLO RSN: msg 1/2 key data", key_data,
+ key_data_len);
+ if (wpa_supplicant_parse_ies(key_data, key_data_len, &ie) < 0)
+ goto failed;
+
+ if (!ie.valid_mlo_gtks) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
+ "MLO RSN: No MLO GTK KDE in Group Key msg 1/2");
+ goto failed;
+ }
+
+ if (!(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
+ "MLO RSN: MLO GTK KDE in unencrypted key data");
+ goto failed;
+ }
+
+#ifdef CONFIG_OCV
+ if (wpa_sm_ocv_enabled(sm)) {
+ struct wpa_channel_info ci;
+
+ if (wpa_sm_channel_info(sm, &ci) != 0) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
+ "Failed to get channel info to validate received OCI in EAPOL-Key group msg 1/2");
+ goto failed;
+ }
+
+ if (ocv_verify_tx_params(ie.oci, ie.oci_len, &ci,
+ channel_width_to_int(ci.chanwidth),
+ ci.seg1_idx) != OCI_SUCCESS) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_INFO, OCV_FAILURE
+ "addr=" MACSTR " frame=eapol-key-g1 error=%s",
+ MAC2STR(sm->bssid), ocv_errorstr);
+ goto failed;
+ }
+ }
+#endif /* CONFIG_OCV */
+
+ if (mlo_ieee80211w_set_keys(sm, &ie) < 0)
+ wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
+ "MLO RSN: Failed to configure MLO IGTK");
+
+ for (i = 0; i < MAX_NUM_MLO_LINKS; i++) {
+ if (!(sm->mlo.valid_links & BIT(i)))
+ continue;
+
+ /*
+ * AP may send group keys for subset of the all links during
+ * rekey
+ */
+ if (!ie.mlo_gtk[i])
+ continue;
+
+ if (wpa_supplicant_mlo_gtk(sm, i, ie.mlo_gtk[i],
+ ie.mlo_gtk_len[i], key_info))
+ goto failed;
+ }
+
+ if (wpa_supplicant_send_2_of_2(sm, key, ver, key_info) < 0)
+ goto failed;
+
+ wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "MLO RSN: Group rekeying completed "
+ "with " MACSTR " [GTK=%s]", MAC2STR(sm->mlo.ap_mld_addr),
+ wpa_cipher_txt(sm->group_cipher));
+ wpa_sm_cancel_auth_timeout(sm);
+ wpa_sm_set_state(sm, WPA_COMPLETED);
+
+ wpa_sm_set_rekey_offload(sm);
+
+ return;
+
+failed:
+ wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED);
+}
+
+
+static void wpa_supplicant_process_1_of_2_wpa(struct wpa_sm *sm,
+ const unsigned char *src_addr,
+ const struct wpa_eapol_key *key,
+ const u8 *key_data,
+ size_t key_data_len, u16 ver)
+{
+ u16 key_info;
+ int rekey;
+ struct wpa_gtk_data gd;
+ const u8 *key_rsc;
+ size_t maxkeylen;
+ u16 gtk_len;
+
+ if (!sm->msg_3_of_4_ok) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
"WPA: Group Key Handshake started prior to completion of 4-way handshake");
goto failed;
}
@@ -2161,25 +2872,88 @@
os_memset(&gd, 0, sizeof(gd));
rekey = wpa_sm_get_state(sm) == WPA_COMPLETED;
- wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: RX message 1 of Group Key "
- "Handshake from " MACSTR " (ver=%d)", MAC2STR(src_addr), ver);
+ wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
+ "WPA: RX message 1 of Group Key Handshake from " MACSTR
+ " (ver=%d)", MAC2STR(src_addr), ver);
key_info = WPA_GET_BE16(key->key_info);
- if (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) {
- ret = wpa_supplicant_process_1_of_2_rsn(sm, key_data,
- key_data_len, key_info,
- &gd);
- } else {
- ret = wpa_supplicant_process_1_of_2_wpa(sm, key, key_data,
- key_data_len,
- key_info, ver, &gd);
+ gtk_len = WPA_GET_BE16(key->key_length);
+ maxkeylen = key_data_len;
+ if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
+ if (maxkeylen < 8) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
+ "WPA: Too short maxkeylen (%lu)",
+ (unsigned long) maxkeylen);
+ goto failed;
+ }
+ maxkeylen -= 8;
}
+ if (gtk_len > maxkeylen ||
+ wpa_supplicant_check_group_cipher(sm, sm->group_cipher,
+ gtk_len, maxkeylen,
+ &gd.key_rsc_len, &gd.alg))
+ goto failed;
+
wpa_sm_set_state(sm, WPA_GROUP_HANDSHAKE);
- if (ret)
+ gd.gtk_len = gtk_len;
+ gd.keyidx = (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) >>
+ WPA_KEY_INFO_KEY_INDEX_SHIFT;
+ if (ver == WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 && sm->ptk.kek_len == 16) {
+#if defined(CONFIG_NO_RC4) || defined(CONFIG_FIPS)
+ wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
+ "WPA: RC4 not supported in the build");
goto failed;
+#else /* CONFIG_NO_RC4 || CONFIG_FIPS */
+ u8 ek[32];
+ if (key_data_len > sizeof(gd.gtk)) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
+ "WPA: RC4 key data too long (%lu)",
+ (unsigned long) key_data_len);
+ goto failed;
+ }
+ os_memcpy(ek, key->key_iv, 16);
+ os_memcpy(ek + 16, sm->ptk.kek, sm->ptk.kek_len);
+ os_memcpy(gd.gtk, key_data, key_data_len);
+ if (rc4_skip(ek, 32, 256, gd.gtk, key_data_len)) {
+ forced_memzero(ek, sizeof(ek));
+ wpa_msg(sm->ctx->msg_ctx, MSG_ERROR,
+ "WPA: RC4 failed");
+ goto failed;
+ }
+ forced_memzero(ek, sizeof(ek));
+#endif /* CONFIG_NO_RC4 || CONFIG_FIPS */
+ } else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
+ if (maxkeylen % 8) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
+ "WPA: Unsupported AES-WRAP len %lu",
+ (unsigned long) maxkeylen);
+ goto failed;
+ }
+ if (maxkeylen > sizeof(gd.gtk)) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
+ "WPA: AES-WRAP key data "
+ "too long (keydatalen=%lu maxkeylen=%lu)",
+ (unsigned long) key_data_len,
+ (unsigned long) maxkeylen);
+ goto failed;
+ }
+ if (aes_unwrap(sm->ptk.kek, sm->ptk.kek_len, maxkeylen / 8,
+ key_data, gd.gtk)) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
+ "WPA: AES unwrap failed - could not decrypt "
+ "GTK");
+ goto failed;
+ }
+ } else {
+ wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
+ "WPA: Unsupported key_info type %d", ver);
+ goto failed;
+ }
+ gd.tx = wpa_supplicant_gtk_tx_bit_workaround(
+ sm, !!(key_info & WPA_KEY_INFO_TXRX));
key_rsc = key->key_rsc;
if (wpa_supplicant_rsc_relaxation(sm, key->key_rsc))
@@ -2191,15 +2965,15 @@
forced_memzero(&gd, sizeof(gd));
if (rekey) {
- wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "WPA: Group rekeying "
- "completed with " MACSTR " [GTK=%s]",
+ wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
+ "WPA: Group rekeying completed with " MACSTR
+ " [GTK=%s]",
MAC2STR(sm->bssid), wpa_cipher_txt(sm->group_cipher));
wpa_sm_cancel_auth_timeout(sm);
wpa_sm_set_state(sm, WPA_COMPLETED);
} else {
wpa_supplicant_key_neg_complete(sm, sm->bssid,
- key_info &
- WPA_KEY_INFO_SECURE);
+ key_info & WPA_KEY_INFO_SECURE);
}
wpa_sm_set_rekey_offload(sm);
@@ -2212,6 +2986,127 @@
}
+static void wpa_supplicant_process_1_of_2(struct wpa_sm *sm,
+ const unsigned char *src_addr,
+ const struct wpa_eapol_key *key,
+ const u8 *key_data,
+ size_t key_data_len, u16 ver)
+{
+ u16 key_info;
+ struct wpa_gtk_data gd;
+ const u8 *key_rsc;
+ int maxkeylen;
+ struct wpa_eapol_ie_parse ie;
+ u16 gtk_len;
+
+ if (!sm->msg_3_of_4_ok && !wpa_fils_is_completed(sm)) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
+ "RSN: Group Key Handshake started prior to completion of 4-way handshake");
+ goto failed;
+ }
+
+ os_memset(&gd, 0, sizeof(gd));
+
+ wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
+ "RSN: RX message 1 of Group Key Handshake from " MACSTR
+ " (ver=%d)", MAC2STR(src_addr), ver);
+
+ key_info = WPA_GET_BE16(key->key_info);
+
+ wpa_hexdump_key(MSG_DEBUG, "RSN: msg 1/2 key data",
+ key_data, key_data_len);
+ if (wpa_supplicant_parse_ies(key_data, key_data_len, &ie) < 0)
+ goto failed;
+
+ wpa_sm_set_state(sm, WPA_GROUP_HANDSHAKE);
+
+ if (ie.gtk && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
+ "RSN: GTK KDE in unencrypted key data");
+ goto failed;
+ }
+ if (!ie.gtk) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
+ "RSN: No GTK KDE in Group Key msg 1/2");
+ goto failed;
+ }
+ gtk_len = ie.gtk_len;
+ if (gtk_len < 2) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
+ "RSN: Invalid GTK KDE length (%u) in Group Key msg 1/2",
+ gtk_len);
+ goto failed;
+ }
+ gtk_len -= 2;
+ if (gtk_len > sizeof(gd.gtk)) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
+ "RSN: Too long GTK in GTK KDE (len=%u)", gtk_len);
+ goto failed;
+ }
+ maxkeylen = gd.gtk_len = gtk_len;
+
+#ifdef CONFIG_OCV
+ if (wpa_sm_ocv_enabled(sm)) {
+ struct wpa_channel_info ci;
+
+ if (wpa_sm_channel_info(sm, &ci) != 0) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
+ "Failed to get channel info to validate received OCI in EAPOL-Key group msg 1/2");
+ goto failed;
+ }
+
+ if (ocv_verify_tx_params(ie.oci, ie.oci_len, &ci,
+ channel_width_to_int(ci.chanwidth),
+ ci.seg1_idx) != OCI_SUCCESS) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_INFO, OCV_FAILURE
+ "addr=" MACSTR " frame=eapol-key-g1 error=%s",
+ MAC2STR(sm->bssid), ocv_errorstr);
+ goto failed;
+ }
+ }
+#endif /* CONFIG_OCV */
+
+ if (wpa_supplicant_check_group_cipher(sm, sm->group_cipher,
+ gtk_len, maxkeylen,
+ &gd.key_rsc_len, &gd.alg))
+ goto failed;
+
+ wpa_hexdump_key(MSG_DEBUG, "RSN: received GTK in group key handshake",
+ ie.gtk, 2 + gtk_len);
+ gd.keyidx = ie.gtk[0] & 0x3;
+ gd.tx = wpa_supplicant_gtk_tx_bit_workaround(sm,
+ !!(ie.gtk[0] & BIT(2)));
+ os_memcpy(gd.gtk, ie.gtk + 2, gtk_len);
+
+ if (ieee80211w_set_keys(sm, &ie) < 0)
+ wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
+ "RSN: Failed to configure IGTK");
+
+ key_rsc = key->key_rsc;
+ if (wpa_supplicant_rsc_relaxation(sm, key->key_rsc))
+ key_rsc = null_rsc;
+
+ if (wpa_supplicant_install_gtk(sm, &gd, key_rsc, 0) ||
+ wpa_supplicant_send_2_of_2(sm, key, ver, key_info) < 0)
+ goto failed;
+ forced_memzero(&gd, sizeof(gd));
+
+ wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
+ "RSN: Group rekeying completed with " MACSTR " [GTK=%s]",
+ MAC2STR(sm->bssid), wpa_cipher_txt(sm->group_cipher));
+ wpa_sm_cancel_auth_timeout(sm);
+ wpa_sm_set_state(sm, WPA_COMPLETED);
+
+ wpa_sm_set_rekey_offload(sm);
+
+ return;
+
+failed:
+ forced_memzero(&gd, sizeof(gd));
+ wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED);
+}
+
+
static int wpa_supplicant_verify_eapol_key_mic(struct wpa_sm *sm,
struct wpa_eapol_key *key,
u16 ver,
@@ -2310,11 +3205,11 @@
/* Decrypt key data here so that this operation does not need
* to be implemented separately for each message type. */
if (ver == WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 && sm->ptk.kek_len == 16) {
-#ifdef CONFIG_NO_RC4
+#if defined(CONFIG_NO_RC4) || defined(CONFIG_FIPS)
wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
"WPA: RC4 not supported in the build");
return -1;
-#else /* CONFIG_NO_RC4 */
+#else /* CONFIG_NO_RC4 || CONFIG_FIPS */
u8 ek[32];
wpa_printf(MSG_DEBUG, "WPA: Decrypt Key Data using RC4");
@@ -2327,7 +3222,7 @@
return -1;
}
forced_memzero(ek, sizeof(ek));
-#endif /* CONFIG_NO_RC4 */
+#endif /* CONFIG_NO_RC4 || CONFIG_FIPS */
} else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES ||
ver == WPA_KEY_INFO_TYPE_AES_128_CMAC ||
wpa_use_aes_key_wrap(sm->key_mgmt)) {
@@ -2513,6 +3408,88 @@
#endif /* CONFIG_FILS */
+static int wpa_sm_rx_eapol_wpa(struct wpa_sm *sm, const u8 *src_addr,
+ struct wpa_eapol_key *key,
+ enum frame_encryption encrypted,
+ const u8 *tmp, size_t data_len,
+ u8 *key_data, size_t key_data_len)
+{
+ u16 key_info, ver;
+
+ key_info = WPA_GET_BE16(key->key_info);
+
+ if (key->type != EAPOL_KEY_TYPE_WPA) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
+ "WPA: Unsupported EAPOL-Key type %d", key->type);
+ return -1;
+ }
+
+ ver = key_info & WPA_KEY_INFO_TYPE_MASK;
+ if (ver != WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 &&
+ ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
+ "WPA: Unsupported EAPOL-Key descriptor version %d",
+ ver);
+ return -1;
+ }
+
+ if (sm->pairwise_cipher == WPA_CIPHER_CCMP &&
+ ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
+ "WPA: CCMP is used, but EAPOL-Key descriptor version (%d) is not 2",
+ ver);
+ if (sm->group_cipher != WPA_CIPHER_CCMP &&
+ !(key_info & WPA_KEY_INFO_KEY_TYPE)) {
+ /* Earlier versions of IEEE 802.11i did not explicitly
+ * require version 2 descriptor for all EAPOL-Key
+ * packets, so allow group keys to use version 1 if
+ * CCMP is not used for them. */
+ wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
+ "WPA: Backwards compatibility: allow invalid version for non-CCMP group keys");
+ } else
+ return -1;
+ }
+
+ if ((key_info & WPA_KEY_INFO_MIC) &&
+ wpa_supplicant_verify_eapol_key_mic(sm, key, ver, tmp, data_len))
+ return -1;
+
+ if (key_info & WPA_KEY_INFO_KEY_TYPE) {
+ if (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
+ "WPA: Ignored EAPOL-Key (Pairwise) with non-zero key index");
+ return -1;
+ }
+ if (key_info & (WPA_KEY_INFO_MIC |
+ WPA_KEY_INFO_ENCR_KEY_DATA)) {
+ /* 3/4 4-Way Handshake */
+ wpa_supplicant_process_3_of_4_wpa(sm, key, ver,
+ key_data,
+ key_data_len);
+ } else {
+ /* 1/4 4-Way Handshake */
+ wpa_supplicant_process_1_of_4_wpa(sm, src_addr, key,
+ ver, key_data,
+ key_data_len,
+ encrypted);
+ }
+ } else {
+ if (key_info & WPA_KEY_INFO_MIC) {
+ /* 1/2 Group Key Handshake */
+ wpa_supplicant_process_1_of_2_wpa(sm, src_addr, key,
+ key_data,
+ key_data_len,
+ ver);
+ } else {
+ wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
+ "WPA: EAPOL-Key (Group) without Mic/Encr bit - dropped");
+ }
+ }
+
+ return 1;
+}
+
+
/**
* wpa_sm_rx_eapol - Process received WPA EAPOL frames
* @sm: Pointer to WPA state machine data from wpa_sm_init()
@@ -2624,19 +3601,77 @@
goto out;
}
+ if (sm->rx_replay_counter_set &&
+ os_memcmp(key->replay_counter, sm->rx_replay_counter,
+ WPA_REPLAY_COUNTER_LEN) <= 0) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
+ "WPA: EAPOL-Key Replay Counter did not increase - dropping packet");
+ goto out;
+ }
+
eapol_sm_notify_lower_layer_success(sm->eapol, 0);
+
key_info = WPA_GET_BE16(key->key_info);
+
+ if (key_info & WPA_KEY_INFO_SMK_MESSAGE) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
+ "WPA: Unsupported SMK bit in key_info");
+ goto out;
+ }
+
+ if (!(key_info & WPA_KEY_INFO_ACK)) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
+ "WPA: No Ack bit in key_info");
+ goto out;
+ }
+
+ if (key_info & WPA_KEY_INFO_REQUEST) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
+ "WPA: EAPOL-Key with Request bit - dropped");
+ goto out;
+ }
+
+ if (sm->proto == WPA_PROTO_WPA) {
+ ret = wpa_sm_rx_eapol_wpa(sm, src_addr, key, encrypted,
+ tmp, data_len,
+ key_data, key_data_len);
+ goto out;
+ }
+
+ if (key->type != EAPOL_KEY_TYPE_RSN) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
+ "RSN: Unsupported EAPOL-Key type %d", key->type);
+ goto out;
+ }
+
ver = key_info & WPA_KEY_INFO_TYPE_MASK;
if (ver != WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 &&
ver != WPA_KEY_INFO_TYPE_AES_128_CMAC &&
ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES &&
!wpa_use_akm_defined(sm->key_mgmt)) {
wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
- "WPA: Unsupported EAPOL-Key descriptor version %d",
+ "RSN: Unsupported EAPOL-Key descriptor version %d",
ver);
goto out;
}
+ if (ver == WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 &&
+ sm->pairwise_cipher != WPA_CIPHER_TKIP) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
+ "RSN: EAPOL-Key descriptor version %d not allowed without TKIP as the pairwise cipher",
+ ver);
+ goto out;
+ }
+
+ if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES &&
+ (sm->key_mgmt != WPA_KEY_MGMT_IEEE8021X &&
+ sm->key_mgmt != WPA_KEY_MGMT_PSK)) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
+ "RSN: EAPOL-Key descriptor version %d not allowed due to negotiated AKM (0x%x)",
+ ver, sm->key_mgmt);
+ goto out;
+ }
+
if (wpa_use_akm_defined(sm->key_mgmt) &&
ver != WPA_KEY_INFO_TYPE_AKM_DEFINED) {
wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
@@ -2660,63 +3695,28 @@
if (ver != WPA_KEY_INFO_TYPE_AES_128_CMAC &&
!wpa_use_akm_defined(sm->key_mgmt)) {
wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
- "WPA: AP did not use the "
- "negotiated AES-128-CMAC");
+ "RSN: AP did not use the negotiated AES-128-CMAC");
goto out;
}
} else if (sm->pairwise_cipher == WPA_CIPHER_CCMP &&
!wpa_use_akm_defined(sm->key_mgmt) &&
ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
- "WPA: CCMP is used, but EAPOL-Key "
- "descriptor version (%d) is not 2", ver);
- if (sm->group_cipher != WPA_CIPHER_CCMP &&
- !(key_info & WPA_KEY_INFO_KEY_TYPE)) {
- /* Earlier versions of IEEE 802.11i did not explicitly
- * require version 2 descriptor for all EAPOL-Key
- * packets, so allow group keys to use version 1 if
- * CCMP is not used for them. */
+ "RSN: CCMP is used, but EAPOL-Key descriptor version (%d) is not 2", ver);
+ if (ver == WPA_KEY_INFO_TYPE_AES_128_CMAC) {
wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
- "WPA: Backwards compatibility: allow invalid "
- "version for non-CCMP group keys");
- } else if (ver == WPA_KEY_INFO_TYPE_AES_128_CMAC) {
+ "RSN: Interoperability workaround: allow incorrect (should have been HMAC-SHA1), but stronger (is AES-128-CMAC), descriptor version to be used");
+ } else {
wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
- "WPA: Interoperability workaround: allow incorrect (should have been HMAC-SHA1), but stronger (is AES-128-CMAC), descriptor version to be used");
- } else
+ "RSN: Unexpected descriptor version %u", ver);
goto out;
+ }
} else if (sm->pairwise_cipher == WPA_CIPHER_GCMP &&
!wpa_use_akm_defined(sm->key_mgmt) &&
ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
- "WPA: GCMP is used, but EAPOL-Key "
- "descriptor version (%d) is not 2", ver);
- goto out;
- }
-
- if (sm->rx_replay_counter_set &&
- os_memcmp(key->replay_counter, sm->rx_replay_counter,
- WPA_REPLAY_COUNTER_LEN) <= 0) {
- wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
- "WPA: EAPOL-Key Replay Counter did not increase - "
- "dropping packet");
- goto out;
- }
-
- if (key_info & WPA_KEY_INFO_SMK_MESSAGE) {
- wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
- "WPA: Unsupported SMK bit in key_info");
- goto out;
- }
-
- if (!(key_info & WPA_KEY_INFO_ACK)) {
- wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
- "WPA: No Ack bit in key_info");
- goto out;
- }
-
- if (key_info & WPA_KEY_INFO_REQUEST) {
- wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
- "WPA: EAPOL-Key with Request bit - dropped");
+ "RSN: GCMP is used, but EAPOL-Key descriptor version (%d) is not 2",
+ ver);
goto out;
}
@@ -2753,8 +3753,7 @@
if (key_info & WPA_KEY_INFO_KEY_TYPE) {
if (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) {
wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
- "WPA: Ignored EAPOL-Key (Pairwise) with "
- "non-zero key index");
+ "RSN: Ignored EAPOL-Key (Pairwise) with non-zero key index");
goto out;
}
if (key_info & (WPA_KEY_INFO_MIC |
@@ -2773,13 +3772,19 @@
if ((mic_len && (key_info & WPA_KEY_INFO_MIC)) ||
(!mic_len && (key_info & WPA_KEY_INFO_ENCR_KEY_DATA))) {
/* 1/2 Group Key Handshake */
- wpa_supplicant_process_1_of_2(sm, src_addr, key,
- key_data, key_data_len,
- ver);
+ if (sm->mlo.valid_links)
+ wpa_supplicant_process_mlo_1_of_2(sm, src_addr,
+ key, key_data,
+ key_data_len,
+ ver);
+ else
+ wpa_supplicant_process_1_of_2(sm, src_addr, key,
+ key_data,
+ key_data_len,
+ ver);
} else {
wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
- "WPA: EAPOL-Key (Group) without Mic/Encr bit - "
- "dropped");
+ "RSN: EAPOL-Key (Group) without Mic/Encr bit - dropped");
}
}
@@ -2965,6 +3970,15 @@
}
+static void wpa_sm_pmksa_notify_cb(struct rsn_pmksa_cache_entry *entry,
+ void *ctx)
+{
+ struct wpa_sm *sm = ctx;
+
+ wpa_sm_notify_pmksa_cache_entry(sm, entry);
+}
+
+
/**
* wpa_sm_init - Initialize WPA state machine
* @ctx: Context pointer for callbacks; this needs to be an allocated buffer
@@ -2989,7 +4003,8 @@
sm->dot11RSNAConfigSATimeout = 60;
sm->pmksa = pmksa_cache_init(wpa_sm_pmksa_free_cb,
- wpa_sm_pmksa_is_current_cb, sm, sm);
+ wpa_sm_pmksa_is_current_cb,
+ wpa_sm_pmksa_notify_cb, sm, sm);
if (sm->pmksa == NULL) {
wpa_msg(sm->ctx->msg_ctx, MSG_ERROR,
"RSN: PMKSA cache initialization failed");
@@ -3007,6 +4022,8 @@
*/
void wpa_sm_deinit(struct wpa_sm *sm)
{
+ int i;
+
if (sm == NULL)
return;
pmksa_cache_deinit(sm->pmksa);
@@ -3017,6 +4034,10 @@
os_free(sm->ap_wpa_ie);
os_free(sm->ap_rsn_ie);
os_free(sm->ap_rsnxe);
+ for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
+ os_free(sm->mlo.links[i].ap_rsne);
+ os_free(sm->mlo.links[i].ap_rsnxe);
+ }
wpa_sm_drop_sa(sm);
os_free(sm->ctx);
#ifdef CONFIG_IEEE80211R
@@ -3041,6 +4062,32 @@
}
+static void wpa_sm_clear_ptk(struct wpa_sm *sm)
+{
+ int i;
+
+ sm->ptk_set = 0;
+ os_memset(&sm->ptk, 0, sizeof(sm->ptk));
+ sm->tptk_set = 0;
+ os_memset(&sm->tptk, 0, sizeof(sm->tptk));
+ os_memset(&sm->gtk, 0, sizeof(sm->gtk));
+ os_memset(&sm->gtk_wnm_sleep, 0, sizeof(sm->gtk_wnm_sleep));
+ os_memset(&sm->igtk, 0, sizeof(sm->igtk));
+ os_memset(&sm->igtk_wnm_sleep, 0, sizeof(sm->igtk_wnm_sleep));
+ sm->tk_set = false;
+ for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
+ os_memset(&sm->mlo.links[i].gtk, 0,
+ sizeof(sm->mlo.links[i].gtk));
+ os_memset(&sm->mlo.links[i].gtk_wnm_sleep, 0,
+ sizeof(sm->mlo.links[i].gtk_wnm_sleep));
+ os_memset(&sm->mlo.links[i].igtk, 0,
+ sizeof(sm->mlo.links[i].igtk));
+ os_memset(&sm->mlo.links[i].igtk_wnm_sleep, 0,
+ sizeof(sm->mlo.links[i].igtk_wnm_sleep));
+ }
+}
+
+
/**
* wpa_sm_notify_assoc - Notify WPA state machine about association
* @sm: Pointer to WPA state machine data from wpa_sm_init()
@@ -3100,15 +4147,7 @@
* this is not part of a Fast BSS Transition.
*/
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Clear old PTK");
- sm->ptk_set = 0;
- os_memset(&sm->ptk, 0, sizeof(sm->ptk));
- sm->tptk_set = 0;
- os_memset(&sm->tptk, 0, sizeof(sm->tptk));
- os_memset(&sm->gtk, 0, sizeof(sm->gtk));
- os_memset(&sm->gtk_wnm_sleep, 0, sizeof(sm->gtk_wnm_sleep));
- os_memset(&sm->igtk, 0, sizeof(sm->igtk));
- os_memset(&sm->igtk_wnm_sleep, 0, sizeof(sm->igtk_wnm_sleep));
- sm->tk_set = false;
+ wpa_sm_clear_ptk(sm);
}
#ifdef CONFIG_TDLS
@@ -3305,6 +4344,85 @@
}
+int wpa_sm_set_mlo_params(struct wpa_sm *sm, const struct wpa_sm_mlo *mlo)
+{
+ int i;
+
+ if (!sm)
+ return -1;
+
+ os_memcpy(sm->mlo.ap_mld_addr, mlo->ap_mld_addr, ETH_ALEN);
+ sm->mlo.assoc_link_id = mlo->assoc_link_id;
+ sm->mlo.valid_links = mlo->valid_links;
+ sm->mlo.req_links = mlo->req_links;
+
+ for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
+ const u8 *ie;
+ size_t len;
+
+ if (sm->mlo.req_links & BIT(i)) {
+ if (!mlo->links[i].ap_rsne ||
+ mlo->links[i].ap_rsne_len == 0) {
+ wpa_dbg(sm->ctx->msg_ctx, MSG_INFO,
+ "RSN: No RSNE for AP MLO link %d with BSSID "
+ MACSTR,
+ i, MAC2STR(mlo->links[i].bssid));
+ return -1;
+
+ }
+ os_memcpy(sm->mlo.links[i].addr, mlo->links[i].addr,
+ ETH_ALEN);
+ os_memcpy(sm->mlo.links[i].bssid, mlo->links[i].bssid,
+ ETH_ALEN);
+ }
+
+ ie = mlo->links[i].ap_rsne;
+ len = mlo->links[i].ap_rsne_len;
+ os_free(sm->mlo.links[i].ap_rsne);
+ if (!ie || len == 0) {
+ if (sm->mlo.links[i].ap_rsne)
+ wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
+ "RSN: Clearing MLO link[%u] AP RSNE",
+ i);
+ sm->mlo.links[i].ap_rsne = NULL;
+ sm->mlo.links[i].ap_rsne_len = 0;
+ } else {
+ wpa_hexdump_link(MSG_DEBUG, i, "RSN: Set AP RSNE",
+ ie, len);
+ sm->mlo.links[i].ap_rsne = os_memdup(ie, len);
+ if (!sm->mlo.links[i].ap_rsne) {
+ sm->mlo.links[i].ap_rsne_len = 0;
+ return -1;
+ }
+ sm->mlo.links[i].ap_rsne_len = len;
+ }
+
+ ie = mlo->links[i].ap_rsnxe;
+ len = mlo->links[i].ap_rsnxe_len;
+ os_free(sm->mlo.links[i].ap_rsnxe);
+ if (!ie || len == 0) {
+ if (sm->mlo.links[i].ap_rsnxe)
+ wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
+ "RSN: Clearing MLO link[%u] AP RSNXE",
+ i);
+ sm->mlo.links[i].ap_rsnxe = NULL;
+ sm->mlo.links[i].ap_rsnxe_len = 0;
+ } else {
+ wpa_hexdump_link(MSG_DEBUG, i, "RSN: Set AP RSNXE", ie,
+ len);
+ sm->mlo.links[i].ap_rsnxe = os_memdup(ie, len);
+ if (!sm->mlo.links[i].ap_rsnxe) {
+ sm->mlo.links[i].ap_rsnxe_len = 0;
+ return -1;
+ }
+ sm->mlo.links[i].ap_rsnxe_len = len;
+ }
+ }
+
+ return 0;
+}
+
+
/**
* wpa_sm_set_own_addr - Set own MAC address
* @sm: Pointer to WPA state machine data from wpa_sm_init()
@@ -3874,10 +4992,11 @@
}
-int wpa_sm_pmksa_exists(struct wpa_sm *sm, const u8 *bssid,
+int wpa_sm_pmksa_exists(struct wpa_sm *sm, const u8 *bssid, const u8 *own_addr,
const void *network_ctx)
{
- return pmksa_cache_get(sm->pmksa, bssid, NULL, network_ctx, 0) != NULL;
+ return pmksa_cache_get(sm->pmksa, bssid, own_addr, NULL, network_ctx,
+ 0) != NULL;
}
@@ -3887,24 +5006,25 @@
const void *network_ctx,
int akmp)
{
- return pmksa_cache_get(sm->pmksa, aa, pmkid, network_ctx, akmp);
+ return pmksa_cache_get(sm->pmksa, aa, sm->own_addr, pmkid, network_ctx,
+ akmp);
+}
+
+
+void wpa_sm_pmksa_cache_remove(struct wpa_sm *sm,
+ struct rsn_pmksa_cache_entry *entry)
+{
+ if (sm && sm->pmksa)
+ pmksa_cache_remove(sm->pmksa, entry);
}
void wpa_sm_drop_sa(struct wpa_sm *sm)
{
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Clear old PMK and PTK");
- sm->ptk_set = 0;
- sm->tptk_set = 0;
- sm->tk_set = false;
+ wpa_sm_clear_ptk(sm);
sm->pmk_len = 0;
os_memset(sm->pmk, 0, sizeof(sm->pmk));
- os_memset(&sm->ptk, 0, sizeof(sm->ptk));
- os_memset(&sm->tptk, 0, sizeof(sm->tptk));
- os_memset(&sm->gtk, 0, sizeof(sm->gtk));
- os_memset(&sm->gtk_wnm_sleep, 0, sizeof(sm->gtk_wnm_sleep));
- os_memset(&sm->igtk, 0, sizeof(sm->igtk));
- os_memset(&sm->igtk_wnm_sleep, 0, sizeof(sm->igtk_wnm_sleep));
#ifdef CONFIG_IEEE80211R
os_memset(sm->xxkey, 0, sizeof(sm->xxkey));
sm->xxkey_len = 0;
@@ -3921,12 +5041,21 @@
}
-int wpa_sm_has_ptk(struct wpa_sm *sm)
+#ifdef CONFIG_IEEE80211R
+bool wpa_sm_has_ft_keys(struct wpa_sm *sm, const u8 *md)
{
- if (sm == NULL)
- return 0;
+ if (!sm)
+ return false;
+ if (!wpa_key_mgmt_ft(sm->key_mgmt) ||
+ os_memcmp(md, sm->key_mobility_domain,
+ MOBILITY_DOMAIN_ID_LEN) != 0) {
+ /* Do not allow FT protocol to be used even if we were to have
+ * an PTK since the mobility domain has changed. */
+ return false;
+ }
return sm->ptk_set;
}
+#endif /* CONFIG_IEEE80211R */
int wpa_sm_has_ptk_installed(struct wpa_sm *sm)
@@ -3958,7 +5087,7 @@
void wpa_sm_install_pmk(struct wpa_sm *sm)
{
/* In case the driver wants to handle re-assocs, pass it down the PMK. */
- if (wpa_sm_set_key(sm, wpa_cipher_to_alg(sm->pairwise_cipher), NULL, 0, 0, NULL, 0,
+ if (wpa_sm_set_key(sm, -1, wpa_cipher_to_alg(sm->pairwise_cipher), NULL, 0, 0, NULL, 0,
(u8*)sm->pmk, sm->pmk_len, KEY_FLAG_PMK) < 0) {
wpa_hexdump(MSG_DEBUG, "PSK: Install PMK to the driver for driver reassociations",
(u8*)sm->pmk, sm->pmk_len);
@@ -4127,6 +5256,12 @@
}
+const u8 * wpa_sm_get_auth_addr(struct wpa_sm *sm)
+{
+ return sm->mlo.valid_links ? sm->mlo.ap_mld_addr : sm->bssid;
+}
+
+
#ifdef CONFIG_FILS
struct wpabuf * fils_build_auth(struct wpa_sm *sm, int dh_group, const u8 *md)
@@ -4362,7 +5497,7 @@
}
if (wpa_ft_parse_ies(pos, end - pos, &parse,
- wpa_key_mgmt_sha384(sm->key_mgmt)) < 0) {
+ sm->key_mgmt) < 0) {
wpa_printf(MSG_DEBUG, "FILS+FT: Failed to parse IEs");
goto fail;
}
@@ -4509,7 +5644,8 @@
else
kdk_len = 0;
- if (fils_pmk_to_ptk(sm->pmk, sm->pmk_len, sm->own_addr, sm->bssid,
+ if (fils_pmk_to_ptk(sm->pmk, sm->pmk_len, sm->own_addr,
+ wpa_sm_get_auth_addr(sm),
sm->fils_nonce, sm->fils_anonce,
dh_ss ? wpabuf_head(dh_ss) : NULL,
dh_ss ? wpabuf_len(dh_ss) : 0,
@@ -4651,21 +5787,27 @@
if (wpa_derive_pmk_r0(sm->fils_ft, sm->fils_ft_len, sm->ssid,
sm->ssid_len, sm->mobility_domain,
sm->r0kh_id, sm->r0kh_id_len, sm->own_addr,
- sm->pmk_r0, sm->pmk_r0_name, use_sha384) < 0) {
+ sm->pmk_r0, sm->pmk_r0_name, sm->key_mgmt) < 0) {
wpa_printf(MSG_WARNING, "FILS+FT: Could not derive PMK-R0");
return -1;
}
- sm->pmk_r0_len = use_sha384 ? SHA384_MAC_LEN : PMK_LEN;
+ if (wpa_key_mgmt_sae_ext_key(sm->key_mgmt))
+ sm->pmk_r0_len = sm->fils_ft_len;
+ else
+ sm->pmk_r0_len = use_sha384 ? SHA384_MAC_LEN : PMK_LEN;
wpa_printf(MSG_DEBUG, "FILS+FT: R1KH-ID: " MACSTR,
MAC2STR(sm->r1kh_id));
pos = wpabuf_put(buf, WPA_PMK_NAME_LEN);
if (wpa_derive_pmk_r1_name(sm->pmk_r0_name, sm->r1kh_id, sm->own_addr,
- sm->pmk_r1_name, use_sha384) < 0) {
+ sm->pmk_r1_name, sm->fils_ft_len) < 0) {
wpa_printf(MSG_WARNING, "FILS+FT: Could not derive PMKR1Name");
return -1;
}
os_memcpy(pos, sm->pmk_r1_name, WPA_PMK_NAME_LEN);
+ os_memcpy(sm->key_mobility_domain, sm->mobility_domain,
+ MOBILITY_DOMAIN_ID_LEN);
+
if (sm->mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC) {
/* Management Group Cipher Suite */
pos = wpabuf_put(buf, RSN_SELECTOR_LEN);
@@ -5071,12 +6213,13 @@
rsclen = wpa_cipher_rsc_len(sm->pairwise_cipher);
wpa_hexdump_key(MSG_DEBUG, "FILS: Set TK to driver",
sm->ptk.tk, keylen);
- if (wpa_sm_set_key(sm, alg, sm->bssid, 0, 1, null_rsc, rsclen,
+ if (wpa_sm_set_key(sm, -1, alg, wpa_sm_get_auth_addr(sm), 0, 1,
+ null_rsc, rsclen,
sm->ptk.tk, keylen, KEY_FLAG_PAIRWISE_RX_TX) < 0) {
wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
- "FILS: Failed to set PTK to the driver (alg=%d keylen=%d bssid="
+ "FILS: Failed to set PTK to the driver (alg=%d keylen=%d auth_addr="
MACSTR ")",
- alg, keylen, MAC2STR(sm->bssid));
+ alg, keylen, MAC2STR(wpa_sm_get_auth_addr(sm)));
goto fail;
}
@@ -5360,15 +6503,6 @@
#ifdef CONFIG_PASN
-void wpa_pasn_pmksa_cache_add(struct wpa_sm *sm, const u8 *pmk, size_t pmk_len,
- const u8 *pmkid, const u8 *bssid, int key_mgmt)
-{
- sm->cur_pmksa = pmksa_cache_add(sm->pmksa, pmk, pmk_len, pmkid, NULL, 0,
- bssid, sm->own_addr, NULL,
- key_mgmt, 0);
-}
-
-
void wpa_pasn_sm_set_caps(struct wpa_sm *sm, unsigned int flags2)
{
if (flags2 & WPA_DRIVER_FLAGS2_SEC_LTF_STA)
@@ -5387,3 +6521,17 @@
if (sm)
pmksa_cache_reconfig(sm->pmksa);
}
+
+
+struct rsn_pmksa_cache * wpa_sm_get_pmksa_cache(struct wpa_sm *sm)
+{
+ return sm ? sm->pmksa : NULL;
+}
+
+
+void wpa_sm_set_cur_pmksa(struct wpa_sm *sm,
+ struct rsn_pmksa_cache_entry *entry)
+{
+ if (sm)
+ sm->cur_pmksa = entry;
+}