[wpa_supplicant] Cumulative patch from commit dd2daf084

Bug: 156933657
Test: Confirm random dialog token usage from logs
Test: Verify Passpoint ANQP functionality and Passpoint association
Test: act.py -c ../WifiDppConfig.json -tc WifiDppTest
Test: Connect to Passpoint, Open, WPA2, WPA3 networks and run traffic
Test: Regression test passed (Bug: 156969218)

dd2daf084 HE: Process HE 6 GHz band capab from associating HE STA
db603634a HE: Add 6 GHz Band Capabilities element in Beacon and response frames
88911a0aa HE: Add HE 6 GHz Band Capabilities into ieee802_11_parse_elems()
b2c0b83c6 HE: Remove VHT Operation Information from HE Operation element
e297a5bfd HE: Define 6 GHz band capability elements
39f29f250 defconfig: Enable TDLS
025ab330b ACS: Channel selection based freqlist
4ae3f3972 Add a helper function for recognizing BIP enum wpa_alg values
d3cab56c0 Rename WPA_ALG_IGTK to use the correct cipher name for BIP
bd1aebbd0 hostapd: Extend RESET_PN for BIGTK
df49c53f4 Fix a typo in a comment
4294d221d D-Bus: Increase introspection buffer size
79488da57 wolfssl: Do not hardcode include directory in wpa_supplicant build
eb595b3e3 wolfssl: Fix crypto_bignum_rand() implementation
6a28c4dbc wolfssl: Fix compiler warnings on size_t printf format use
f2dbaa8ac SAE: Fix a typo in a comment
038899290 wpa_gui: Fix build with Inkscape 1.0
3e1a13010 nl80211: Change AKM suite limit from warning to debug print
5a04a76aa Ignore Management frames while AP interface is not fully enabled
c82535edd Move deauthentication at AP start to be after beacon configuration
094c8a621 Remove unnecessary key clearing at AP start with nl80211
04030e8c0 nl80211: Remove AP mode interface from bridge for STA-mode-scan
7adea21d2 dpp-nfc: Enable hostapd beaconing for listen state
134ad50b0 dpp-nfc: Clean up debug prints when handover select is received
5d49c1bf7 dpp-nfc: Do not indicate a single channel 1 by default
d0e2d8091 dpp-nfc: Make handover request collision detection more robust
8791e7461 dpp-nfc: Write debug info to summary log
1e0bc897a dpp-nfc: Collision detection for handover request
9ad3fe934 dpp-nfc: Start handover server regardless of init-on-touch setting
24efcdf74 dpp-nfc: Own MAC address fetching from hostapd
8f96f2c3b dpp-nfc: Be more graceful when wpa_supplicant is not available
0b04d3c57 dpp-nfc: Allow wpa_supplicant control interface directory to be set
69dfbe6a9 dpp-nfc: Use Configurator/Enrollee parameters with tag reading
f85fb349f dpp-nfc: More robust determination of the script directory
98e4b3840 DPP2: Chirping in hostapd Enrollee
95471fc3e Handle hostapd_for_each_interface() at the process termination
99809c7a4 nl80211: Disable offchannel-ok in AP mode only if beaconing
0f58c88fc DPP2: Fix CONFIG_DPP2=y build with OpenSSL 1.0.2
44f786678 Clean up GET_CAPABILITY handling of 'strict' argument
3790f3a6e Use per-interface type driver key_mgmt capabilities when possible
8d7502809 Allow per interface type AKM capabilities to be fetched
b67bedf2e nl80211: Fetch information on supported AKMs from the driver
6fffb320f nl80211: Remove QCA vendor specific AKM capability handling
db59827a3 DPP2: Extend TCP encapsulation case to support Configurator as Initiator
0086c1452 DPP: Extend NFC bootstrapping script for more control by caller
890ae336c DPP2: Clean up CONFIG_DPP2 use with configurator connectivity IE
670e15337 DPP2: Fix DPP_CHIRP listen parameter value validation
7f20a3ebd DPP2: Reconfiguration support in Controller
6dcb8aaf1 DPP2: Reconfig Announcement relaying from AP to Controller
3b4f7dfaa DPP2: Fix Presence Announcement processing in Controller
5e2d877cc DPP: Mark internal-to-file functions static
3aaf269f6 DPP: Move TCP encapsulation into a separate source code file
21c612017 DPP: Move configurator backup into a separate source code file
fdbbb7406 DPP: Move authentication functionality into a separate source code file
182f6ae90 DPP2: Remove reconfigured network
3e48c5d4b DPP2: Reconfig Authentication Confirm processing
24b01c706 DPP2: Reconfig Authentication Response processing and Confirm generation
65e94351d DPP2: Reconfig Authentication Request processing and Response generation
3774b6bd0 DPP2: Reconfig Authentication Request generation and transmission
66ac616cd DPP2: Process received Reconfig Announcement frame
0c043d9de DPP2: Reconfig Announcement transmission
92492dd3a DPP2: Extend connector matching for reconfiguration
961435097 DPP2: Move connStatus object building into a helper function
94f73f90e DPP: Move signed connector checking into a helper function
94a28a494 DPP: Move parsing of own connector into a helper function
d4ae12355 DPP: Move PKEX functionality into a separate source code file
87b657261 DPP: Move crypto routines into a separate source code file
16626dff9 DPP2: Derive bk ("base key")
76029c6e1 DPP: Use EVP_PKEY_get0_EC_KEY() when a const reference is sufficient
0a488ef35 DPP: Track ending time for remain-on-channel operations
481fdfc46 DPP2: Fix URI version parser
7dd768c3c DPP2: Version information in bootstrapping info URI
cbafc8ef4 Fix truncated control interface command detection
5a0718a19 DPP2: Report MUD URL and bandSupport in control interface events
769139c49 DPP2: Do not include Protocol Version in Auth Req when testing v1
fad64b416 DPP: Move dppCon signing to a set of helper functions
12c8eacf7 DPP: Allow version number to be overridden for testing purposes
c3c38bc8b DPP2: Detect PFS downgrade attack while processing EAPOL-Key msg 3/4
9561925b4 DPP2: Detect PFS downgrade attack while processing EAPOL-Key msg 2/4
68422fedb DPP2: Parse DPP KDE in EAPOL-Key Key Data field
143e3d8bc DPP2: Add DPP KDE into EAPOL-Key msg 2/4 when using DPP AKM
b11a12401 DPP2: Add DPP KDE into EAPOL-Key msg 3/4 when using DPP AKM
85d545699 DPP2: Indicate if PFS was used in control interface STATUS
1f5f00008 DPP2: Try to negotiate PFS only if AP supports version 2 or newer
f6c22dcde Use a local pointer to simply current_ssid accesses in sme_associate()
42acf1292 DPP2: Add Protocol Version attribute to network introduction messages
96b6dd21a Increase wpa_supplicant control interface buffer size
a7d6098fb Add PRINTF_FORMAT for printf wrapper functions

Change-Id: I26a15ac578ce81d1e35f426085661e5c7b43b6ef
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index e3b13bc..1e2e332 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -1553,8 +1553,9 @@
 	 * alg - Encryption algorithm
 	 *
 	 * (%WPA_ALG_NONE, %WPA_ALG_WEP, %WPA_ALG_TKIP, %WPA_ALG_CCMP,
-	 * %WPA_ALG_IGTK, %WPA_ALG_GCMP, %WPA_ALG_GCMP_256, %WPA_ALG_CCMP_256,
-	 * %WPA_ALG_BIP_GMAC_128, %WPA_ALG_BIP_GMAC_256, %WPA_ALG_BIP_CMAC_256);
+	 * %WPA_ALG_BIP_AES_CMAC_128, %WPA_ALG_GCMP, %WPA_ALG_GCMP_256,
+	 * %WPA_ALG_CCMP_256, %WPA_ALG_BIP_GMAC_128, %WPA_ALG_BIP_GMAC_256,
+	 * %WPA_ALG_BIP_CMAC_256);
 	 * %WPA_ALG_NONE clears the key. */
 	enum wpa_alg alg;
 
@@ -1658,6 +1659,73 @@
 	enum key_flag key_flag;
 };
 
+enum wpa_driver_if_type {
+	/**
+	 * WPA_IF_STATION - Station mode interface
+	 */
+	WPA_IF_STATION,
+
+	/**
+	 * WPA_IF_AP_VLAN - AP mode VLAN interface
+	 *
+	 * This interface shares its address and Beacon frame with the main
+	 * BSS.
+	 */
+	WPA_IF_AP_VLAN,
+
+	/**
+	 * WPA_IF_AP_BSS - AP mode BSS interface
+	 *
+	 * This interface has its own address and Beacon frame.
+	 */
+	WPA_IF_AP_BSS,
+
+	/**
+	 * WPA_IF_P2P_GO - P2P Group Owner
+	 */
+	WPA_IF_P2P_GO,
+
+	/**
+	 * WPA_IF_P2P_CLIENT - P2P Client
+	 */
+	WPA_IF_P2P_CLIENT,
+
+	/**
+	 * WPA_IF_P2P_GROUP - P2P Group interface (will become either
+	 * WPA_IF_P2P_GO or WPA_IF_P2P_CLIENT, but the role is not yet known)
+	 */
+	WPA_IF_P2P_GROUP,
+
+	/**
+	 * WPA_IF_P2P_DEVICE - P2P Device interface is used to indentify the
+	 * abstracted P2P Device function in the driver
+	 */
+	WPA_IF_P2P_DEVICE,
+
+	/*
+	 * WPA_IF_MESH - Mesh interface
+	 */
+	WPA_IF_MESH,
+
+	/*
+	 * WPA_IF_TDLS - TDLS offchannel interface (used for pref freq only)
+	 */
+	WPA_IF_TDLS,
+
+	/*
+	 * WPA_IF_IBSS - IBSS interface (used for pref freq only)
+	 */
+	WPA_IF_IBSS,
+
+	/*
+	 * WPA_IF_NAN - NAN Device
+	 */
+	WPA_IF_NAN,
+
+	/* keep last */
+	WPA_IF_MAX
+};
+
 /**
  * struct wpa_driver_capa - Driver capability information
  */
@@ -1681,6 +1749,7 @@
 #define WPA_DRIVER_CAPA_KEY_MGMT_SAE 		0x00010000
 	/** Bitfield of supported key management suites */
 	unsigned int key_mgmt;
+	unsigned int key_mgmt_iftype[WPA_IF_MAX];
 
 #define WPA_DRIVER_CAPA_ENC_WEP40	0x00000001
 #define WPA_DRIVER_CAPA_ENC_WEP104	0x00000002
@@ -2018,6 +2087,7 @@
 	u8 vht_opmode;
 	const struct ieee80211_he_capabilities *he_capab;
 	size_t he_capab_len;
+	const struct ieee80211_he_6ghz_band_cap *he_6ghz_capab;
 	u32 flags; /* bitmask of WPA_STA_* flags */
 	u32 flags_mask; /* unset bits in flags */
 #ifdef CONFIG_MESH
@@ -2045,65 +2115,6 @@
 	struct mac_address mac_acl[0];
 };
 
-enum wpa_driver_if_type {
-	/**
-	 * WPA_IF_STATION - Station mode interface
-	 */
-	WPA_IF_STATION,
-
-	/**
-	 * WPA_IF_AP_VLAN - AP mode VLAN interface
-	 *
-	 * This interface shares its address and Beacon frame with the main
-	 * BSS.
-	 */
-	WPA_IF_AP_VLAN,
-
-	/**
-	 * WPA_IF_AP_BSS - AP mode BSS interface
-	 *
-	 * This interface has its own address and Beacon frame.
-	 */
-	WPA_IF_AP_BSS,
-
-	/**
-	 * WPA_IF_P2P_GO - P2P Group Owner
-	 */
-	WPA_IF_P2P_GO,
-
-	/**
-	 * WPA_IF_P2P_CLIENT - P2P Client
-	 */
-	WPA_IF_P2P_CLIENT,
-
-	/**
-	 * WPA_IF_P2P_GROUP - P2P Group interface (will become either
-	 * WPA_IF_P2P_GO or WPA_IF_P2P_CLIENT, but the role is not yet known)
-	 */
-	WPA_IF_P2P_GROUP,
-
-	/**
-	 * WPA_IF_P2P_DEVICE - P2P Device interface is used to indentify the
-	 * abstracted P2P Device function in the driver
-	 */
-	WPA_IF_P2P_DEVICE,
-
-	/*
-	 * WPA_IF_MESH - Mesh interface
-	 */
-	WPA_IF_MESH,
-
-	/*
-	 * WPA_IF_TDLS - TDLS offchannel interface (used for pref freq only)
-	 */
-	WPA_IF_TDLS,
-
-	/*
-	 * WPA_IF_IBSS - IBSS interface (used for pref freq only)
-	 */
-	WPA_IF_IBSS,
-};
-
 struct wpa_init_params {
 	void *global_priv;
 	const u8 *bssid;
diff --git a/src/drivers/driver_atheros.c b/src/drivers/driver_atheros.c
index d630c3d..9b4166d 100644
--- a/src/drivers/driver_atheros.c
+++ b/src/drivers/driver_atheros.c
@@ -532,7 +532,7 @@
 		cipher = IEEE80211_CIPHER_AES_GCM_256;
 		break;
 #endif /* ATH_GCM_SUPPORT */
-	case WPA_ALG_IGTK:
+	case WPA_ALG_BIP_CMAC_128:
 		cipher = IEEE80211_CIPHER_AES_CMAC;
 		break;
 #ifdef ATH_GCM_SUPPORT
diff --git a/src/drivers/driver_bsd.c b/src/drivers/driver_bsd.c
index b4400d7..5adee13 100644
--- a/src/drivers/driver_bsd.c
+++ b/src/drivers/driver_bsd.c
@@ -1451,6 +1451,7 @@
 #define	GETPARAM(drv, param, v) \
 	(((v) = get80211param(drv, param)) != -1)
 	struct bsd_driver_data *drv;
+	int i;
 
 	drv = os_zalloc(sizeof(*drv));
 	if (drv == NULL)
@@ -1486,6 +1487,10 @@
 	if (wpa_driver_bsd_capa(drv))
 		goto fail;
 
+	/* Update per interface supported AKMs */
+	for (i = 0; i < WPA_IF_MAX; i++)
+		drv->capa.key_mgmt_iftype[i] = drv->capa.key_mgmt;
+
 	/* Down interface during setup. */
 	if (bsd_get_iface_flags(drv) < 0)
 		goto fail;
diff --git a/src/drivers/driver_ndis.c b/src/drivers/driver_ndis.c
index 529fc3b..b5fff48 100644
--- a/src/drivers/driver_ndis.c
+++ b/src/drivers/driver_ndis.c
@@ -2809,6 +2809,7 @@
 {
 	struct wpa_driver_ndis_data *drv;
 	u32 mode;
+	int i;
 
 	drv = os_zalloc(sizeof(*drv));
 	if (drv == NULL)
@@ -2855,6 +2856,11 @@
 	}
 	wpa_driver_ndis_get_capability(drv);
 
+	/* Update per interface supported AKMs */
+	for (i = 0; i < WPA_IF_MAX; i++)
+		drv->capa.key_mgmt_iftype[i] = drv->capa.key_mgmt;
+
+
 	/* Make sure that the driver does not have any obsolete PMKID entries.
 	 */
 	wpa_driver_ndis_flush_pmkid(drv);
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index d48f8cb..8be593a 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -2328,10 +2328,19 @@
 	/* FT Action frames */
 	if (nl80211_register_action_frame(bss, (u8 *) "\x06", 1) < 0)
 		ret = -1;
-	else
+	else if (!drv->has_driver_key_mgmt) {
+		int i;
+
+		/* Update supported AKMs only if the driver doesn't advertize
+		 * any AKM capabilities. */
 		drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FT |
 			WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK;
 
+		/* Update per interface supported AKMs */
+		for (i = 0; i < WPA_IF_MAX; i++)
+			drv->capa.key_mgmt_iftype[i] = drv->capa.key_mgmt;
+	}
+
 	/* WNM - BSS Transition Management Request */
 	if (nl80211_register_action_frame(bss, (u8 *) "\x0a\x07", 2) < 0)
 		ret = -1;
@@ -2918,7 +2927,7 @@
 		return RSN_CIPHER_SUITE_CCMP_256;
 	case WPA_ALG_GCMP_256:
 		return RSN_CIPHER_SUITE_GCMP_256;
-	case WPA_ALG_IGTK:
+	case WPA_ALG_BIP_CMAC_128:
 		return RSN_CIPHER_SUITE_AES_128_CMAC;
 	case WPA_ALG_BIP_GMAC_128:
 		return RSN_CIPHER_SUITE_BIP_GMAC_128;
@@ -3275,10 +3284,7 @@
 		goto fail2;
 	if (!key_msg ||
 	    nla_put_u8(key_msg, NL80211_KEY_IDX, key_idx) ||
-	    nla_put_flag(key_msg, (alg == WPA_ALG_IGTK ||
-				   alg == WPA_ALG_BIP_GMAC_128 ||
-				   alg == WPA_ALG_BIP_GMAC_256 ||
-				   alg == WPA_ALG_BIP_CMAC_256) ?
+	    nla_put_flag(key_msg, wpa_alg_bip(alg) ?
 			 (key_idx == 6 || key_idx == 7 ?
 			  NL80211_KEY_DEFAULT_BEACON :
 			  NL80211_KEY_DEFAULT_MGMT) :
@@ -3347,7 +3353,7 @@
 	if (!suite)
 		return -1;
 
-	if (defkey && alg == WPA_ALG_IGTK) {
+	if (defkey && wpa_alg_bip(alg)) {
 		if (nla_put_flag(msg, NL80211_KEY_DEFAULT_MGMT))
 			return -1;
 	} else if (defkey) {
@@ -4323,7 +4329,7 @@
 	num_suites = wpa_key_mgmt_to_suites(params->key_mgmt_suites,
 					    suites, ARRAY_SIZE(suites));
 	if (num_suites > NL80211_MAX_NR_AKM_SUITES)
-		wpa_printf(MSG_WARNING,
+		wpa_printf(MSG_DEBUG,
 			   "nl80211: Not enough room for all AKM suites (num_suites=%d > NL80211_MAX_NR_AKM_SUITES)",
 			   num_suites);
 	else if (num_suites &&
@@ -5056,6 +5062,10 @@
 		return "P2P_GO";
 	case NL80211_IFTYPE_P2P_DEVICE:
 		return "P2P_DEVICE";
+	case NL80211_IFTYPE_OCB:
+		return "OCB";
+	case NL80211_IFTYPE_NAN:
+		return "NAN";
 	default:
 		return "unknown";
 	}
@@ -6261,6 +6271,20 @@
 			}
 		}
 
+		if (i == 0 && was_ap && !is_ap_interface(nlmode) &&
+		    bss->brname[0] &&
+		    (bss->added_if_into_bridge || bss->already_in_bridge)) {
+			wpa_printf(MSG_DEBUG,
+				   "nl80211: Remove AP interface %s temporarily from the bridge %s to allow its mode to be set to STATION",
+				   bss->ifname, bss->brname);
+			if (linux_br_del_if(drv->global->ioctl_sock,
+					    bss->brname, bss->ifname) < 0)
+				wpa_printf(MSG_INFO,
+					   "nl80211: Failed to remove interface %s from bridge %s: %s",
+					   bss->ifname, bss->brname,
+					   strerror(errno));
+		}
+
 		/* Try to set the mode again while the interface is down */
 		mode_switch_res = nl80211_set_mode(drv, drv->ifindex, nlmode);
 		if (mode_switch_res == -EBUSY) {
@@ -6333,6 +6357,29 @@
 }
 
 
+void nl80211_restore_ap_mode(struct i802_bss *bss)
+{
+	struct wpa_driver_nl80211_data *drv = bss->drv;
+	int was_ap = is_ap_interface(drv->nlmode);
+
+	wpa_driver_nl80211_set_mode(bss, drv->ap_scan_as_station);
+	if (!was_ap && is_ap_interface(drv->ap_scan_as_station) &&
+	    bss->brname[0] &&
+	    (bss->added_if_into_bridge || bss->already_in_bridge)) {
+		wpa_printf(MSG_DEBUG,
+			   "nl80211: Add AP interface %s back into the bridge %s",
+			   bss->ifname, bss->brname);
+		if (linux_br_add_if(drv->global->ioctl_sock, bss->brname,
+				    bss->ifname) < 0) {
+			wpa_printf(MSG_WARNING,
+				   "nl80211: Failed to add interface %s into bridge %s: %s",
+				   bss->ifname, bss->brname, strerror(errno));
+		}
+	}
+	drv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED;
+}
+
+
 int wpa_driver_nl80211_set_mode(struct i802_bss *bss,
 				enum nl80211_iftype nlmode)
 {
@@ -7742,7 +7789,8 @@
 	struct ieee80211_hdr *hdr;
 	int offchanok = 1;
 
-	if (is_ap_interface(drv->nlmode) && (int) freq == bss->freq)
+	if (is_ap_interface(drv->nlmode) && (int) freq == bss->freq &&
+	    bss->beacon_set)
 		offchanok = 0;
 
 	wpa_printf(MSG_DEBUG, "nl80211: Send Action frame (ifindex=%d, "
diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h
index dc80a17..895f9d7 100644
--- a/src/drivers/driver_nl80211.h
+++ b/src/drivers/driver_nl80211.h
@@ -111,6 +111,7 @@
 	unsigned int num_iface_ext_capa;
 
 	int has_capability;
+	int has_driver_key_mgmt;
 
 	int operstate;
 
@@ -169,7 +170,6 @@
 	unsigned int set_wifi_conf_vendor_cmd_avail:1;
 	unsigned int fetch_bss_trans_status:1;
 	unsigned int roam_vendor_cmd_avail:1;
-	unsigned int get_supported_akm_suites_avail:1;
 	unsigned int add_sta_node_vendor_cmd_avail:1;
 	unsigned int control_port_ap:1;
 	unsigned int multicast_registrations:1;
@@ -275,6 +275,8 @@
 
 const char * nl80211_iftype_str(enum nl80211_iftype mode);
 
+void nl80211_restore_ap_mode(struct i802_bss *bss);
+
 #ifdef ANDROID
 int android_nl_socket_set_nonblocking(struct nl_sock *handle);
 int android_pno_start(struct i802_bss *bss,
diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
index f997577..a3341a0 100644
--- a/src/drivers/driver_nl80211_capa.c
+++ b/src/drivers/driver_nl80211_capa.c
@@ -79,6 +79,8 @@
 	unsigned int mac_addr_rand_scan_supported:1;
 	unsigned int mac_addr_rand_sched_scan_supported:1;
 	unsigned int update_ft_ies_supported:1;
+	unsigned int has_key_mgmt:1;
+	unsigned int has_key_mgmt_iftype:1;
 };
 
 
@@ -252,6 +254,158 @@
 }
 
 
+static unsigned int get_akm_suites_info(struct nlattr *tb)
+{
+	int i, num;
+	unsigned int key_mgmt = 0;
+	u32 *akms;
+
+	if (!tb)
+		return 0;
+
+	num = nla_len(tb) / sizeof(u32);
+	akms = nla_data(tb);
+	for (i = 0; i < num; i++) {
+		switch (akms[i]) {
+		case RSN_AUTH_KEY_MGMT_UNSPEC_802_1X:
+			key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA |
+				WPA_DRIVER_CAPA_KEY_MGMT_WPA2;
+			break;
+		case RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X:
+			key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
+				WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK;
+			break;
+		case RSN_AUTH_KEY_MGMT_FT_802_1X:
+			key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FT;
+			break;
+		case RSN_AUTH_KEY_MGMT_FT_PSK:
+			key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK;
+			break;
+		case RSN_AUTH_KEY_MGMT_802_1X_SUITE_B:
+			key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B;
+			break;
+		case RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192:
+			key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B_192;
+			break;
+		case RSN_AUTH_KEY_MGMT_OWE:
+			key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_OWE;
+			break;
+		case RSN_AUTH_KEY_MGMT_DPP:
+			key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_DPP;
+			break;
+		case RSN_AUTH_KEY_MGMT_FILS_SHA256:
+			key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA256;
+			break;
+		case RSN_AUTH_KEY_MGMT_FILS_SHA384:
+			key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384;
+			break;
+		case RSN_AUTH_KEY_MGMT_FT_FILS_SHA256:
+			key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA256;
+			break;
+		case RSN_AUTH_KEY_MGMT_FT_FILS_SHA384:
+			key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA384;
+			break;
+		case RSN_AUTH_KEY_MGMT_SAE:
+			key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_SAE;
+			break;
+		}
+	}
+
+	return key_mgmt;
+}
+
+
+static void get_iface_akm_suites_info(struct wiphy_info_data *info,
+					struct nlattr *nl_akms)
+{
+	struct nlattr *tb[NL80211_IFTYPE_AKM_ATTR_MAX + 1];
+	struct nlattr *nl_iftype;
+	unsigned int key_mgmt;
+	int i;
+
+	if (!nl_akms)
+		return;
+
+	nla_parse(tb, NL80211_IFTYPE_AKM_ATTR_MAX,
+		  nla_data(nl_akms), nla_len(nl_akms), NULL);
+
+	if (!tb[NL80211_IFTYPE_AKM_ATTR_IFTYPES] ||
+	    !tb[NL80211_IFTYPE_AKM_ATTR_SUITES])
+		return;
+
+	info->has_key_mgmt_iftype = 1;
+	key_mgmt = get_akm_suites_info(tb[NL80211_IFTYPE_AKM_ATTR_SUITES]);
+
+	nla_for_each_nested(nl_iftype, tb[NL80211_IFTYPE_AKM_ATTR_IFTYPES], i) {
+		switch (nla_type(nl_iftype)) {
+		case NL80211_IFTYPE_ADHOC:
+			info->drv->capa.key_mgmt_iftype[WPA_IF_IBSS] = key_mgmt;
+			break;
+		case NL80211_IFTYPE_STATION:
+			info->drv->capa.key_mgmt_iftype[WPA_IF_STATION] =
+				key_mgmt;
+			break;
+		case NL80211_IFTYPE_AP:
+			info->drv->capa.key_mgmt_iftype[WPA_IF_AP_BSS] =
+				key_mgmt;
+			break;
+		case NL80211_IFTYPE_AP_VLAN:
+			info->drv->capa.key_mgmt_iftype[WPA_IF_AP_VLAN] =
+				key_mgmt;
+			break;
+		case NL80211_IFTYPE_MESH_POINT:
+			info->drv->capa.key_mgmt_iftype[WPA_IF_MESH] = key_mgmt;
+			break;
+		case NL80211_IFTYPE_P2P_CLIENT:
+			info->drv->capa.key_mgmt_iftype[WPA_IF_P2P_CLIENT] =
+				key_mgmt;
+			break;
+		case NL80211_IFTYPE_P2P_GO:
+			info->drv->capa.key_mgmt_iftype[WPA_IF_P2P_GO] =
+				key_mgmt;
+			break;
+		case NL80211_IFTYPE_P2P_DEVICE:
+			info->drv->capa.key_mgmt_iftype[WPA_IF_P2P_DEVICE] =
+				key_mgmt;
+			break;
+		case NL80211_IFTYPE_NAN:
+			info->drv->capa.key_mgmt_iftype[WPA_IF_NAN] = key_mgmt;
+			break;
+		}
+		wpa_printf(MSG_DEBUG, "nl80211: %s supported key_mgmt 0x%x",
+			   nl80211_iftype_str(nla_type(nl_iftype)),
+			   key_mgmt);
+	}
+}
+
+
+static void wiphy_info_iftype_akm_suites(struct wiphy_info_data *info,
+					 struct nlattr *tb)
+{
+	struct nlattr *nl_if;
+	int rem_if;
+
+	if (!tb)
+		return;
+
+	nla_for_each_nested(nl_if, tb, rem_if)
+		get_iface_akm_suites_info(info, nl_if);
+}
+
+
+static void wiphy_info_akm_suites(struct wiphy_info_data *info,
+				  struct nlattr *tb)
+{
+	if (!tb)
+		return;
+
+	info->has_key_mgmt = 1;
+	info->capa->key_mgmt = get_akm_suites_info(tb);
+	wpa_printf(MSG_DEBUG, "nl80211: wiphy supported key_mgmt 0x%x",
+		   info->capa->key_mgmt);
+}
+
+
 static void wiphy_info_cipher_suites(struct wiphy_info_data *info,
 				     struct nlattr *tb)
 {
@@ -696,6 +850,8 @@
 	wiphy_info_iface_comb(info, tb[NL80211_ATTR_INTERFACE_COMBINATIONS]);
 	wiphy_info_supp_cmds(info, tb[NL80211_ATTR_SUPPORTED_COMMANDS]);
 	wiphy_info_cipher_suites(info, tb[NL80211_ATTR_CIPHER_SUITES]);
+	wiphy_info_akm_suites(info, tb[NL80211_ATTR_AKM_SUITES]);
+	wiphy_info_iftype_akm_suites(info, tb[NL80211_ATTR_IFTYPE_AKM_SUITES]);
 
 	if (tb[NL80211_ATTR_OFFCHANNEL_TX_OK]) {
 		wpa_printf(MSG_DEBUG, "nl80211: Using driver-based "
@@ -809,9 +965,6 @@
 				case QCA_NL80211_VENDOR_SUBCMD_ROAM:
 					drv->roam_vendor_cmd_avail = 1;
 					break;
-				case QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_AKMS:
-					drv->get_supported_akm_suites_avail = 1;
-					break;
 				case QCA_NL80211_VENDOR_SUBCMD_ADD_STA_NODE:
 					drv->add_sta_node_vendor_cmd_avail = 1;
 					break;
@@ -990,126 +1143,6 @@
 }
 
 
-static unsigned int get_akm_suites_info(struct nlattr *tb)
-{
-	int i, num;
-	unsigned int key_mgmt = 0;
-	u32 *akms;
-
-	if (!tb)
-		return 0;
-
-	num = nla_len(tb) / sizeof(u32);
-	akms = nla_data(tb);
-	for (i = 0; i < num; i++) {
-		u32 a = akms[i];
-
-		wpa_printf(MSG_DEBUG,
-			   "nl80211: Supported AKM %02x-%02x-%02x:%u",
-			   a >> 24, (a >> 16) & 0xff,
-			   (a >> 8) & 0xff, a & 0xff);
-		switch (a) {
-		case RSN_AUTH_KEY_MGMT_UNSPEC_802_1X:
-			key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA |
-				WPA_DRIVER_CAPA_KEY_MGMT_WPA2;
-			break;
-		case RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X:
-			key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
-				WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK;
-			break;
-		case RSN_AUTH_KEY_MGMT_FT_802_1X:
-			key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FT;
-			break;
-		case RSN_AUTH_KEY_MGMT_FT_PSK:
-			key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK;
-			break;
-		case RSN_AUTH_KEY_MGMT_802_1X_SUITE_B:
-			key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B;
-			break;
-		case RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192:
-			key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B_192;
-			break;
-		case RSN_AUTH_KEY_MGMT_OWE:
-			key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_OWE;
-			break;
-		case RSN_AUTH_KEY_MGMT_DPP:
-			key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_DPP;
-			break;
-		case RSN_AUTH_KEY_MGMT_FILS_SHA256:
-			key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA256;
-			break;
-		case RSN_AUTH_KEY_MGMT_FILS_SHA384:
-			key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384;
-			break;
-		case RSN_AUTH_KEY_MGMT_FT_FILS_SHA256:
-			key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA256;
-			break;
-		case RSN_AUTH_KEY_MGMT_FT_FILS_SHA384:
-			key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA384;
-			break;
-		case RSN_AUTH_KEY_MGMT_SAE:
-			key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_SAE;
-			break;
-		}
-	}
-
-	return key_mgmt;
-}
-
-
-static int get_akm_suites_handler(struct nl_msg *msg, void *arg)
-{
-	struct nlattr *tb[NL80211_ATTR_MAX + 1];
-	struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
-	unsigned int *key_mgmt = arg;
-
-	nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
-		  genlmsg_attrlen(gnlh, 0), NULL);
-
-	if (tb[NL80211_ATTR_VENDOR_DATA]) {
-		struct nlattr *nl_vend = tb[NL80211_ATTR_VENDOR_DATA];
-		struct nlattr *tb_data[NL80211_ATTR_MAX + 1];
-
-		nla_parse(tb_data, NL80211_ATTR_MAX,
-			  nla_data(nl_vend), nla_len(nl_vend), NULL);
-
-		*key_mgmt =
-			get_akm_suites_info(tb_data[NL80211_ATTR_AKM_SUITES]);
-	}
-
-	return NL_SKIP;
-}
-
-
-static int qca_nl80211_get_akm_suites(struct wpa_driver_nl80211_data *drv)
-{
-	struct nl_msg *msg;
-	unsigned int key_mgmt = 0;
-	int ret;
-
-	if (!drv->get_supported_akm_suites_avail)
-		return -1;
-
-	if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) ||
-	    nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
-	    nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
-			QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_AKMS)) {
-		nlmsg_free(msg);
-		return -1;
-	}
-
-	ret = send_and_recv_msgs(drv, msg, get_akm_suites_handler, &key_mgmt);
-	if (!ret) {
-		wpa_printf(MSG_DEBUG,
-			   "nl80211: Replace capa.key_mgmt based on driver advertised capabilities: 0x%x",
-			   key_mgmt);
-		drv->capa.key_mgmt = key_mgmt;
-	}
-
-	return ret;
-}
-
-
 struct features_info {
 	u8 *flags;
 	size_t flags_len;
@@ -1221,6 +1254,8 @@
 int wpa_driver_nl80211_capa(struct wpa_driver_nl80211_data *drv)
 {
 	struct wiphy_info_data info;
+	int i;
+
 	if (wpa_driver_nl80211_get_info(drv, &info))
 		return -1;
 
@@ -1228,33 +1263,62 @@
 		return -1;
 
 	drv->has_capability = 1;
-	drv->capa.key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA |
-		WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
-		WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
-		WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK |
-		WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B |
-		WPA_DRIVER_CAPA_KEY_MGMT_OWE |
-		WPA_DRIVER_CAPA_KEY_MGMT_DPP;
+	drv->has_driver_key_mgmt = info.has_key_mgmt | info.has_key_mgmt_iftype;
 
-	if (drv->capa.enc & (WPA_DRIVER_CAPA_ENC_CCMP_256 |
-			     WPA_DRIVER_CAPA_ENC_GCMP_256))
-		drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B_192;
+	/* Fallback to hardcoded defaults if the driver does nott advertize any
+	 * AKM capabilities. */
+	if (!drv->has_driver_key_mgmt) {
+		drv->capa.key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA |
+			WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
+			WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
+			WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK |
+			WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B |
+			WPA_DRIVER_CAPA_KEY_MGMT_OWE |
+			WPA_DRIVER_CAPA_KEY_MGMT_DPP;
 
-	if (drv->capa.flags & WPA_DRIVER_FLAGS_SME)
-		drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA256 |
-			WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384 |
-			WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA256 |
-			WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA384 |
-			WPA_DRIVER_CAPA_KEY_MGMT_SAE;
-	else if (drv->capa.flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD)
-		drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA256 |
-			WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384;
+		if (drv->capa.enc & (WPA_DRIVER_CAPA_ENC_CCMP_256 |
+				     WPA_DRIVER_CAPA_ENC_GCMP_256))
+			drv->capa.key_mgmt |=
+				WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B_192;
 
-#ifdef CONFIG_DRIVER_NL80211_QCA
-	/* Override drv->capa.key_mgmt based on driver advertised capability
-	 * constraints, if available. */
-	qca_nl80211_get_akm_suites(drv);
-#endif /* CONFIG_DRIVER_NL80211_QCA */
+		if (drv->capa.flags & WPA_DRIVER_FLAGS_SME)
+			drv->capa.key_mgmt |=
+				WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA256 |
+				WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384 |
+				WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA256 |
+				WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA384 |
+				WPA_DRIVER_CAPA_KEY_MGMT_SAE;
+		else if (drv->capa.flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD)
+			drv->capa.key_mgmt |=
+				WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA256 |
+				WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384;
+	}
+
+	if (!info.has_key_mgmt_iftype) {
+		/* If the driver does not advertize per interface AKM
+		 * capabilities, consider all interfaces to support default AKMs
+		 * in key_mgmt. */
+		for (i = 0; i < WPA_IF_MAX; i++)
+			drv->capa.key_mgmt_iftype[i] = drv->capa.key_mgmt;
+	} else if (info.has_key_mgmt_iftype && !info.has_key_mgmt) {
+		/* If the driver advertizes only per interface supported AKMs
+		 * but does not advertize per wiphy AKM capabilities, consider
+		 * the default key_mgmt as a mask of per interface supported
+		 * AKMs. */
+		drv->capa.key_mgmt = 0;
+		for (i = 0; i < WPA_IF_MAX; i++)
+			drv->capa.key_mgmt |= drv->capa.key_mgmt_iftype[i];
+	} else if (info.has_key_mgmt_iftype && info.has_key_mgmt) {
+		/* If the driver advertizes AKM capabilities both per wiphy and
+		 * per interface, consider the interfaces for which per
+		 * interface AKM capabilities were not received to support the
+		 * default key_mgmt capabilities.
+		 */
+		for (i = 0; i < WPA_IF_MAX; i++)
+			if (!drv->capa.key_mgmt_iftype[i])
+				drv->capa.key_mgmt_iftype[i] =
+					drv->capa.key_mgmt;
+	}
 
 	drv->capa.auth = WPA_DRIVER_AUTH_OPEN |
 		WPA_DRIVER_AUTH_SHARED |
diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c
index 1152312..6a2de1f 100644
--- a/src/drivers/driver_nl80211_event.c
+++ b/src/drivers/driver_nl80211_event.c
@@ -2581,11 +2581,8 @@
 
 	if (drv->ap_scan_as_station != NL80211_IFTYPE_UNSPECIFIED &&
 	    (cmd == NL80211_CMD_NEW_SCAN_RESULTS ||
-	     cmd == NL80211_CMD_SCAN_ABORTED)) {
-		wpa_driver_nl80211_set_mode(drv->first_bss,
-					    drv->ap_scan_as_station);
-		drv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED;
-	}
+	     cmd == NL80211_CMD_SCAN_ABORTED))
+		nl80211_restore_ap_mode(bss);
 
 	switch (cmd) {
 	case NL80211_CMD_TRIGGER_SCAN:
diff --git a/src/drivers/driver_nl80211_scan.c b/src/drivers/driver_nl80211_scan.c
index 17e8b2c..dc91a29 100644
--- a/src/drivers/driver_nl80211_scan.c
+++ b/src/drivers/driver_nl80211_scan.c
@@ -166,11 +166,8 @@
 
 	wpa_printf(MSG_DEBUG, "nl80211: Failed to abort scan");
 
-	if (drv->ap_scan_as_station != NL80211_IFTYPE_UNSPECIFIED) {
-		wpa_driver_nl80211_set_mode(drv->first_bss,
-					    drv->ap_scan_as_station);
-		drv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED;
-	}
+	if (drv->ap_scan_as_station != NL80211_IFTYPE_UNSPECIFIED)
+		nl80211_restore_ap_mode(drv->first_bss);
 
 	wpa_printf(MSG_DEBUG, "nl80211: Try to get scan results");
 	wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);
diff --git a/src/drivers/driver_wext.c b/src/drivers/driver_wext.c
index 978e1cf..0f0ad1f 100644
--- a/src/drivers/driver_wext.c
+++ b/src/drivers/driver_wext.c
@@ -968,6 +968,7 @@
 static int wpa_driver_wext_finish_drv_init(struct wpa_driver_wext_data *drv)
 {
 	int send_rfkill_event = 0;
+	int i;
 
 	if (linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 1) < 0) {
 		if (rfkill_is_blocked(drv->rfkill)) {
@@ -996,6 +997,10 @@
 
 	wpa_driver_wext_get_range(drv);
 
+	/* Update per interface supported AKMs */
+	for (i = 0; i < WPA_IF_MAX; i++)
+		drv->capa.key_mgmt_iftype[i] = drv->capa.key_mgmt;
+
 	/*
 	 * Unlock the driver's BSSID and force to a random SSID to clear any
 	 * previous association the driver might have when the supplicant
@@ -1768,7 +1773,7 @@
 		case WPA_ALG_CCMP:
 			ext->alg = IW_ENCODE_ALG_CCMP;
 			break;
-		case WPA_ALG_IGTK:
+		case WPA_ALG_BIP_CMAC_128:
 			ext->alg = IW_ENCODE_ALG_AES_CMAC;
 			break;
 		default: