diff mbox series

[1/4] Update API and drivers for Extended Key ID support

Message ID 20190422212701.16124-1-alexander@wetzel-home.de
State Superseded
Headers show
Series [1/4] Update API and drivers for Extended Key ID support | expand

Commit Message

Alexander Wetzel April 22, 2019, 9:26 p.m. UTC
Update the nl80211 driver for Extended Key ID support and update the
internal API to pass through the needed actions to the drivers.

1) Sync nl80211_copy.h with mac80211-next from 2019-04-18

2) Add key_flag to all needed set_key() to request derivations from
   normal key install without using it (key_flag is always set to 0)

3) Add key_flags KEY_FLAG_NO_AUTO_TX and KEY_FLAG_SET_TX needed for
   Extended Key ID support and implement them with the nl80211 driver

Signed-off-by: Alexander Wetzel <alexander@wetzel-home.de>
---

I first tried to replace set_tx with key_flag first but this has a high risk
of causing regressions for drivers. I'm pretty sure set_tx is mostly
useless today and we only may need it for web default keys... but the
API (usage) is really broken as it stands today.
We actually *are* setting default keys with nl80211 all the time when
we should not... like on every WPA unicast key install.

To not mix the API problem with Extended Key ID support I've now kept
set_tx as it is and added key_flag for the information Extended Key ID
has to pass down to the drivers.

This patch adds Extended Key ID support for nl80211 and then adds
key_flag to each and every set_key() but always set it to zero.

 hostapd/ctrl_iface.c              |  32 +++++----
 src/ap/ap_drv_ops.c               |   4 +-
 src/ap/ap_drv_ops.h               |   2 +-
 src/ap/hostapd.c                  |   8 +--
 src/ap/ieee802_11.c               |   2 +-
 src/ap/ieee802_1x.c               |   6 +-
 src/ap/wpa_auth.c                 |  15 ++--
 src/ap/wpa_auth.h                 |   3 +-
 src/ap/wpa_auth_ft.c              |   6 +-
 src/ap/wpa_auth_glue.c            |   4 +-
 src/common/wpa_common.h           |   4 ++
 src/drivers/driver.h              |  23 +++++--
 src/drivers/driver_atheros.c      |   2 +-
 src/drivers/driver_bsd.c          |   2 +-
 src/drivers/driver_hostap.c       |   3 +-
 src/drivers/driver_ndis.c         |   2 +-
 src/drivers/driver_nl80211.c      | 111 ++++++++++++++++++++----------
 src/drivers/driver_nl80211_capa.c |   4 ++
 src/drivers/driver_openbsd.c      |   2 +-
 src/drivers/driver_privsep.c      |   3 +-
 src/drivers/driver_wext.c         |   7 +-
 src/drivers/driver_wext.h         |   2 +-
 src/drivers/nl80211_copy.h        |  69 ++++++++++++++++++-
 src/rsn_supp/tdls.c               |   4 +-
 src/rsn_supp/wpa.c                |  17 ++---
 src/rsn_supp/wpa.h                |   2 +-
 src/rsn_supp/wpa_ft.c             |   6 +-
 src/rsn_supp/wpa_i.h              |   4 +-
 tests/hwsim/test_ap_ciphers.py    |   2 +-
 wpa_supplicant/ctrl_iface.c       |  18 ++---
 wpa_supplicant/driver_i.h         |   4 +-
 wpa_supplicant/ibss_rsn.c         |  11 +--
 wpa_supplicant/mesh_mpm.c         |   6 +-
 wpa_supplicant/mesh_rsn.c         |   9 +--
 wpa_supplicant/wpa_supplicant.c   |   8 +--
 wpa_supplicant/wpas_glue.c        |  10 +--
 36 files changed, 278 insertions(+), 139 deletions(-)
diff mbox series

Patch

diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
index e4b16e61a..30900f217 100644
--- a/hostapd/ctrl_iface.c
+++ b/hostapd/ctrl_iface.c
@@ -2099,7 +2099,7 @@  static int hostapd_ctrl_reset_pn(struct hostapd_data *hapd, const char *cmd)
 					hapd->last_igtk_alg,
 					broadcast_ether_addr,
 					hapd->last_igtk_key_idx, 1, NULL, 0,
-					zero, hapd->last_igtk_len) < 0)
+					zero, hapd->last_igtk_len, 0) < 0)
 			return -1;
 
 		/* Set the previously configured key to reset its TSC */
@@ -2108,7 +2108,7 @@  static int hostapd_ctrl_reset_pn(struct hostapd_data *hapd, const char *cmd)
 					   broadcast_ether_addr,
 					   hapd->last_igtk_key_idx, 1, NULL, 0,
 					   hapd->last_igtk,
-					   hapd->last_igtk_len);
+					   hapd->last_igtk_len, 0);
 	}
 #endif /* CONFIG_IEEE80211W */
 
@@ -2124,7 +2124,7 @@  static int hostapd_ctrl_reset_pn(struct hostapd_data *hapd, const char *cmd)
 					hapd->last_gtk_alg,
 					broadcast_ether_addr,
 					hapd->last_gtk_key_idx, 1, NULL, 0,
-					zero, hapd->last_gtk_len) < 0)
+					zero, hapd->last_gtk_len, 0) < 0)
 			return -1;
 
 		/* Set the previously configured key to reset its TSC */
@@ -2132,7 +2132,7 @@  static int hostapd_ctrl_reset_pn(struct hostapd_data *hapd, const char *cmd)
 					   hapd->last_gtk_alg,
 					   broadcast_ether_addr,
 					   hapd->last_gtk_key_idx, 1, NULL, 0,
-					   hapd->last_gtk, hapd->last_gtk_len);
+					   hapd->last_gtk, hapd->last_gtk_len, 0);
 	}
 
 	sta = ap_get_sta(hapd, addr);
@@ -2149,13 +2149,13 @@  static int hostapd_ctrl_reset_pn(struct hostapd_data *hapd, const char *cmd)
 	 * in the driver. */
 	if (hostapd_drv_set_key(hapd->conf->iface, hapd, sta->last_tk_alg,
 				sta->addr, sta->last_tk_key_idx, 1, NULL, 0,
-				zero, sta->last_tk_len) < 0)
+				zero, sta->last_tk_len, 0) < 0)
 		return -1;
 
 	/* Set the previously configured key to reset its TSC/RSC */
 	return hostapd_drv_set_key(hapd->conf->iface, hapd, sta->last_tk_alg,
 				   sta->addr, sta->last_tk_key_idx, 1, NULL, 0,
-				   sta->last_tk, sta->last_tk_len);
+				   sta->last_tk, sta->last_tk_len, 0);
 }
 
 
@@ -2164,11 +2164,11 @@  static int hostapd_ctrl_set_key(struct hostapd_data *hapd, const char *cmd)
 	u8 addr[ETH_ALEN];
 	const char *pos = cmd;
 	enum wpa_alg alg;
-	int idx, set_tx;
+	int idx, set_tx, key_flag;
 	u8 seq[6], key[WPA_TK_MAX_LEN];
 	size_t key_len;
 
-	/* parameters: alg addr idx set_tx seq key */
+	/* parameters: alg addr idx set_tx seq key key_flag*/
 
 	alg = atoi(pos);
 	pos = os_strchr(pos, ' ');
@@ -2201,9 +2201,15 @@  static int hostapd_ctrl_set_key(struct hostapd_data *hapd, const char *cmd)
 	if (hexstr2bin(pos, key, key_len) < 0)
 		return -1;
 
+	pos++;
+	key_flag = atoi(pos);
+	pos = os_strchr(pos, ' ');
+	if (!pos)
+		return -1;
+
 	wpa_printf(MSG_INFO, "TESTING: Set key");
 	return hostapd_drv_set_key(hapd->conf->iface, hapd, alg, addr, idx,
-				   set_tx, seq, 6, key, key_len);
+				   set_tx, seq, 6, key, key_len, key_flag);
 }
 
 
@@ -2219,7 +2225,7 @@  static void restore_tk(void *ctx1, void *ctx2)
 	 * preventing encryption of a single EAPOL frame. */
 	hostapd_drv_set_key(hapd->conf->iface, hapd, sta->last_tk_alg,
 			    sta->addr, sta->last_tk_key_idx, 1, NULL, 0,
-			    sta->last_tk, sta->last_tk_len);
+			    sta->last_tk, sta->last_tk_len, 0);
 }
 
 
@@ -2243,7 +2249,7 @@  static int hostapd_ctrl_resend_m1(struct hostapd_data *hapd, const char *cmd)
 			   MAC2STR(sta->addr));
 		hostapd_drv_set_key(hapd->conf->iface, hapd, WPA_ALG_NONE,
 				    sta->addr, sta->last_tk_key_idx, 0, NULL, 0,
-				    NULL, 0);
+				    NULL, 0, 0);
 	}
 
 	wpa_printf(MSG_INFO, "TESTING: Send M1 to " MACSTR, MAC2STR(sta->addr));
@@ -2273,7 +2279,7 @@  static int hostapd_ctrl_resend_m3(struct hostapd_data *hapd, const char *cmd)
 			   MAC2STR(sta->addr));
 		hostapd_drv_set_key(hapd->conf->iface, hapd, WPA_ALG_NONE,
 				    sta->addr, sta->last_tk_key_idx, 0, NULL, 0,
-				    NULL, 0);
+				    NULL, 0, 0);
 	}
 
 	wpa_printf(MSG_INFO, "TESTING: Send M3 to " MACSTR, MAC2STR(sta->addr));
@@ -2303,7 +2309,7 @@  static int hostapd_ctrl_resend_group_m1(struct hostapd_data *hapd,
 			   MAC2STR(sta->addr));
 		hostapd_drv_set_key(hapd->conf->iface, hapd, WPA_ALG_NONE,
 				    sta->addr, sta->last_tk_key_idx, 0, NULL, 0,
-				    NULL, 0);
+				    NULL, 0, 0);
 	}
 
 	wpa_printf(MSG_INFO,
diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
index 067cf863e..0e81948a1 100644
--- a/src/ap/ap_drv_ops.c
+++ b/src/ap/ap_drv_ops.c
@@ -660,13 +660,13 @@  int hostapd_drv_set_key(const char *ifname, struct hostapd_data *hapd,
 			enum wpa_alg alg, const u8 *addr,
 			int key_idx, int set_tx,
 			const u8 *seq, size_t seq_len,
-			const u8 *key, size_t key_len)
+			const u8 *key, size_t key_len, int key_flag)
 {
 	if (hapd->driver == NULL || hapd->driver->set_key == NULL)
 		return 0;
 	return hapd->driver->set_key(ifname, hapd->drv_priv, alg, addr,
 				     key_idx, set_tx, seq, seq_len, key,
-				     key_len);
+				     key_len, key_flag);
 }
 
 
diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h
index de40171e1..bbe44b1b5 100644
--- a/src/ap/ap_drv_ops.h
+++ b/src/ap/ap_drv_ops.h
@@ -86,7 +86,7 @@  int hostapd_drv_set_key(const char *ifname,
 			enum wpa_alg alg, const u8 *addr,
 			int key_idx, int set_tx,
 			const u8 *seq, size_t seq_len,
-			const u8 *key, size_t key_len);
+			const u8 *key, size_t key_len, int key_flag);
 int hostapd_drv_send_mlme(struct hostapd_data *hapd,
 			  const void *msg, size_t len, int noack);
 int hostapd_drv_send_mlme_csa(struct hostapd_data *hapd,
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index 20c8e8f5a..020124ddf 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -285,7 +285,7 @@  static void hostapd_broadcast_key_clear_iface(struct hostapd_data *hapd,
 		return;
 	for (i = 0; i < NUM_WEP_KEYS; i++) {
 		if (hostapd_drv_set_key(ifname, hapd, WPA_ALG_NONE, NULL, i,
-					0, NULL, 0, NULL, 0)) {
+					0, NULL, 0, NULL, 0, 0)) {
 			wpa_printf(MSG_DEBUG, "Failed to clear default "
 				   "encryption keys (ifname=%s keyidx=%d)",
 				   ifname, i);
@@ -296,7 +296,7 @@  static void hostapd_broadcast_key_clear_iface(struct hostapd_data *hapd,
 		for (i = NUM_WEP_KEYS; i < NUM_WEP_KEYS + 2; i++) {
 			if (hostapd_drv_set_key(ifname, hapd, WPA_ALG_NONE,
 						NULL, i, 0, NULL,
-						0, NULL, 0)) {
+						0, NULL, 0, 0)) {
 				wpa_printf(MSG_DEBUG, "Failed to clear "
 					   "default mgmt encryption keys "
 					   "(ifname=%s keyidx=%d)", ifname, i);
@@ -324,7 +324,7 @@  static int hostapd_broadcast_wep_set(struct hostapd_data *hapd)
 	    hostapd_drv_set_key(hapd->conf->iface,
 				hapd, WPA_ALG_WEP, broadcast_ether_addr, idx,
 				1, NULL, 0, ssid->wep.key[idx],
-				ssid->wep.len[idx])) {
+				ssid->wep.len[idx], 0)) {
 		wpa_printf(MSG_WARNING, "Could not set WEP encryption.");
 		errors++;
 	}
@@ -550,7 +550,7 @@  static int hostapd_setup_encryption(char *iface, struct hostapd_data *hapd)
 		    hostapd_drv_set_key(iface, hapd, WPA_ALG_WEP, NULL, i,
 					i == hapd->conf->ssid.wep.idx, NULL, 0,
 					hapd->conf->ssid.wep.key[i],
-					hapd->conf->ssid.wep.len[i])) {
+					hapd->conf->ssid.wep.len[i], 0)) {
 			wpa_printf(MSG_WARNING, "Could not set WEP "
 				   "encryption.");
 			return -1;
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index fde19b526..393fc9092 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -4608,7 +4608,7 @@  static void hostapd_set_wds_encryption(struct hostapd_data *hapd,
 		if (ssid->wep.key[i] &&
 		    hostapd_drv_set_key(ifname_wds, hapd, WPA_ALG_WEP, NULL, i,
 					i == ssid->wep.idx, NULL, 0,
-					ssid->wep.key[i], ssid->wep.len[i])) {
+					ssid->wep.key[i], ssid->wep.len[i], 0)) {
 			wpa_printf(MSG_WARNING,
 				   "Could not set WEP keys for WDS interface; %s",
 				   ifname_wds);
diff --git a/src/ap/ieee802_1x.c b/src/ap/ieee802_1x.c
index 97f503f75..0310130dc 100644
--- a/src/ap/ieee802_1x.c
+++ b/src/ap/ieee802_1x.c
@@ -258,7 +258,7 @@  static void ieee802_1x_tx_key(struct hostapd_data *hapd, struct sta_info *sta)
 		 * has ACKed EAPOL-Key frame */
 		if (hostapd_drv_set_key(hapd->conf->iface, hapd, WPA_ALG_WEP,
 					sta->addr, 0, 1, NULL, 0, ikey,
-					hapd->conf->individual_wep_key_len)) {
+					hapd->conf->individual_wep_key_len, 0)) {
 			wpa_printf(MSG_ERROR, "Could not set individual WEP "
 				   "encryption.");
 		}
@@ -2060,7 +2060,7 @@  static void ieee802_1x_rekey(void *eloop_ctx, void *timeout_ctx)
 				broadcast_ether_addr,
 				eapol->default_wep_key_idx, 1, NULL, 0,
 				eapol->default_wep_key,
-				hapd->conf->default_wep_key_len)) {
+				hapd->conf->default_wep_key_len, 0)) {
 		hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE8021X,
 			       HOSTAPD_LEVEL_WARNING, "failed to configure a "
 			       "new broadcast key");
@@ -2372,7 +2372,7 @@  int ieee802_1x_init(struct hostapd_data *hapd)
 		for (i = 0; i < 4; i++)
 			hostapd_drv_set_key(hapd->conf->iface, hapd,
 					    WPA_ALG_NONE, NULL, i, 0, NULL, 0,
-					    NULL, 0);
+					    NULL, 0, 0);
 
 		ieee802_1x_rekey(hapd, NULL);
 
diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c
index f2e028c15..d70e2982b 100644
--- a/src/ap/wpa_auth.c
+++ b/src/ap/wpa_auth.c
@@ -136,12 +136,12 @@  static inline int wpa_auth_get_msk(struct wpa_authenticator *wpa_auth,
 static inline int wpa_auth_set_key(struct wpa_authenticator *wpa_auth,
 				   int vlan_id,
 				   enum wpa_alg alg, const u8 *addr, int idx,
-				   u8 *key, size_t key_len)
+				   u8 *key, size_t key_len, int key_flag)
 {
 	if (wpa_auth->cb->set_key == NULL)
 		return -1;
 	return wpa_auth->cb->set_key(wpa_auth->cb_ctx, vlan_id, alg, addr, idx,
-				     key, key_len);
+				     key, key_len, key_flag);
 }
 
 
@@ -1710,7 +1710,7 @@  void wpa_remove_ptk(struct wpa_state_machine *sm)
 	sm->PTK_valid = FALSE;
 	os_memset(&sm->PTK, 0, sizeof(sm->PTK));
 	if (wpa_auth_set_key(sm->wpa_auth, 0, WPA_ALG_NONE, sm->addr, 0, NULL,
-			     0))
+			     0, 0))
 		wpa_printf(MSG_DEBUG,
 			   "RSN: PTK removal from the driver failed");
 	sm->pairwise_set = FALSE;
@@ -2744,7 +2744,7 @@  int fils_set_tk(struct wpa_state_machine *sm)
 
 	wpa_printf(MSG_DEBUG, "FILS: Configure TK to the driver");
 	if (wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr, 0,
-			     sm->PTK.tk, klen)) {
+			     sm->PTK.tk, klen, 0)) {
 		wpa_printf(MSG_DEBUG, "FILS: Failed to set TK to the driver");
 		return -1;
 	}
@@ -3342,7 +3342,7 @@  SM_STATE(WPA_PTK, PTKINITDONE)
 		enum wpa_alg alg = wpa_cipher_to_alg(sm->pairwise);
 		int klen = wpa_cipher_key_len(sm->pairwise);
 		if (wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr, 0,
-				     sm->PTK.tk, klen)) {
+				     sm->PTK.tk, klen, 0)) {
 			wpa_sta_disconnect(sm->wpa_auth, sm->addr,
 					   WLAN_REASON_PREV_AUTH_NOT_VALID);
 			return;
@@ -3941,7 +3941,7 @@  static int wpa_group_config_group_keys(struct wpa_authenticator *wpa_auth,
 	if (wpa_auth_set_key(wpa_auth, group->vlan_id,
 			     wpa_cipher_to_alg(wpa_auth->conf.wpa_group),
 			     broadcast_ether_addr, group->GN,
-			     group->GTK[group->GN - 1], group->GTK_len) < 0)
+			     group->GTK[group->GN - 1], group->GTK_len, 0) < 0)
 		ret = -1;
 
 #ifdef CONFIG_IEEE80211W
@@ -3955,7 +3955,8 @@  static int wpa_group_config_group_keys(struct wpa_authenticator *wpa_auth,
 		if (ret == 0 &&
 		    wpa_auth_set_key(wpa_auth, group->vlan_id, alg,
 				     broadcast_ether_addr, group->GN_igtk,
-				     group->IGTK[group->GN_igtk - 4], len) < 0)
+				     group->IGTK[group->GN_igtk - 4],
+				     len, 0) < 0)
 			ret = -1;
 	}
 #endif /* CONFIG_IEEE80211W */
diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h
index df1e17a00..783ad6007 100644
--- a/src/ap/wpa_auth.h
+++ b/src/ap/wpa_auth.h
@@ -258,7 +258,8 @@  struct wpa_auth_callbacks {
 			      int *vlan_id);
 	int (*get_msk)(void *ctx, const u8 *addr, u8 *msk, size_t *len);
 	int (*set_key)(void *ctx, int vlan_id, enum wpa_alg alg,
-		       const u8 *addr, int idx, u8 *key, size_t key_len);
+		       const u8 *addr, int idx, u8 *key, size_t key_len,
+		       int key_flag);
 	int (*get_seqnum)(void *ctx, const u8 *addr, int idx, u8 *seq);
 	int (*send_eapol)(void *ctx, const u8 *addr, const u8 *data,
 			  size_t data_len, int encrypt);
diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c
index ac16199a6..b95c96264 100644
--- a/src/ap/wpa_auth_ft.c
+++ b/src/ap/wpa_auth_ft.c
@@ -2604,12 +2604,12 @@  u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
 static inline int wpa_auth_set_key(struct wpa_authenticator *wpa_auth,
 				   int vlan_id,
 				   enum wpa_alg alg, const u8 *addr, int idx,
-				   u8 *key, size_t key_len)
+				   u8 *key, size_t key_len, int key_flag)
 {
 	if (wpa_auth->cb->set_key == NULL)
 		return -1;
 	return wpa_auth->cb->set_key(wpa_auth->cb_ctx, vlan_id, alg, addr, idx,
-				     key, key_len);
+				     key, key_len, key_flag);
 }
 
 
@@ -2642,7 +2642,7 @@  void wpa_ft_install_ptk(struct wpa_state_machine *sm)
 	 * optimized by adding the STA entry earlier.
 	 */
 	if (wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr, 0,
-			     sm->PTK.tk, klen))
+			     sm->PTK.tk, klen, 0))
 		return;
 
 	/* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */
diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c
index 45172c69a..a977b60f2 100644
--- a/src/ap/wpa_auth_glue.c
+++ b/src/ap/wpa_auth_glue.c
@@ -353,7 +353,7 @@  static int hostapd_wpa_auth_get_msk(void *ctx, const u8 *addr, u8 *msk,
 
 static int hostapd_wpa_auth_set_key(void *ctx, int vlan_id, enum wpa_alg alg,
 				    const u8 *addr, int idx, u8 *key,
-				    size_t key_len)
+				    size_t key_len, int key_flag)
 {
 	struct hostapd_data *hapd = ctx;
 	const char *ifname = hapd->conf->iface;
@@ -396,7 +396,7 @@  static int hostapd_wpa_auth_set_key(void *ctx, int vlan_id, enum wpa_alg alg,
 	}
 #endif /* CONFIG_TESTING_OPTIONS */
 	return hostapd_drv_set_key(ifname, hapd, alg, addr, idx, 1, NULL, 0,
-				   key, key_len);
+				   key, key_len, key_flag);
 }
 
 
diff --git a/src/common/wpa_common.h b/src/common/wpa_common.h
index e83d6887a..353ff4017 100644
--- a/src/common/wpa_common.h
+++ b/src/common/wpa_common.h
@@ -203,6 +203,10 @@  struct wpa_eapol_key {
 #define FILS_ICK_MAX_LEN 48
 #define FILS_FT_MAX_LEN 48
 
+#define KEY_FLAG_RESERVED BIT(0) /* reserved to replace set_tx */
+#define KEY_FLAG_NO_AUTO_TX BIT(1)
+#define KEY_FLAG_SET_TX BIT(2)
+
 /**
  * struct wpa_ptk - WPA Pairwise Transient Key
  * IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index e7c8f318f..4323924c2 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -1618,6 +1618,8 @@  struct wpa_driver_capa {
 #define WPA_DRIVER_FLAGS_FTM_RESPONDER		0x0100000000000000ULL
 /** Driver support 4-way handshake offload for WPA-Personal */
 #define WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK	0x0200000000000000ULL
+/** Driver supports Extended Key ID */
+#define WPA_DRIVER_FLAGS_EXTENDED_KEY_ID	0x0400000000000000ULL
 	u64 flags;
 
 #define FULL_AP_CLIENT_STATE_SUPP(drv_flags) \
@@ -2244,18 +2246,29 @@  struct wpa_driver_ops {
 	 *	8-byte Rx Mic Key
 	 * @key_len: length of the key buffer in octets (WEP: 5 or 13,
 	 *	TKIP: 32, CCMP/GCMP: 16, IGTK: 16)
+	 * @key_flag: Additional flag for key installation. Can only be used
+	 *	when the driver supports "Extended Key ID"
+	 *	%KEY_FLAG_NO_AUTO_TX:
+	 *	   Key must only be installed but not yet be used for Tx.
+	 *	%KEY_FLAG_SET_TX:
+	 *	   Key installed with %KEY_FLAG_NO_AUTO_TX is selected as
+	 *	   new unicast Tx key. Only @ifname, @priv, @addr and @key_idx
+	 *	   must be set and all other arguments set to zero or NULL.
 	 *
 	 * Returns: 0 on success, -1 on failure
 	 *
-	 * Configure the given key for the kernel driver. If the driver
+	 * When using WEP encryption some special rules apply: If the driver
 	 * supports separate individual keys (4 default keys + 1 individual),
 	 * addr can be used to determine whether the key is default or
 	 * individual. If only 4 keys are supported, the default key with key
 	 * index 0 is used as the individual key. STA must be configured to use
 	 * it as the default Tx key (set_tx is set) and accept Rx for all the
-	 * key indexes. In most cases, WPA uses only key indexes 1 and 2 for
-	 * broadcast keys, so key index 0 is available for this kind of
-	 * configuration.
+	 * key indexes. (Note: set_tx is being set in many cases without need.
+	 * Sometimes this is detected and needles default key installations are
+	 * suppressed, but often not. The rule seems to be: When set we may have
+	 * to install a default key. When not set we don't have to.)
+	 * TODO: cleanup or better drop set_key and migrate any remaining
+	 * functionality to key_flag.
 	 *
 	 * Please note that TKIP keys include separate TX and RX MIC keys and
 	 * some drivers may expect them in different order than wpa_supplicant
@@ -2268,7 +2281,7 @@  struct wpa_driver_ops {
 	int (*set_key)(const char *ifname, void *priv, enum wpa_alg alg,
 		       const u8 *addr, int key_idx, int set_tx,
 		       const u8 *seq, size_t seq_len,
-		       const u8 *key, size_t key_len);
+		       const u8 *key, size_t key_len, int key_flag);
 
 	/**
 	 * init - Initialize driver interface
diff --git a/src/drivers/driver_atheros.c b/src/drivers/driver_atheros.c
index 807cd9469..6471e725a 100644
--- a/src/drivers/driver_atheros.c
+++ b/src/drivers/driver_atheros.c
@@ -500,7 +500,7 @@  atheros_del_key(void *priv, const u8 *addr, int key_idx)
 static int
 atheros_set_key(const char *ifname, void *priv, enum wpa_alg alg,
 		const u8 *addr, int key_idx, int set_tx, const u8 *seq,
-		size_t seq_len, const u8 *key, size_t key_len)
+		size_t seq_len, const u8 *key, size_t key_len, int key_flag)
 {
 	struct atheros_driver_data *drv = priv;
 	struct ieee80211req_key wk;
diff --git a/src/drivers/driver_bsd.c b/src/drivers/driver_bsd.c
index 46754968f..d6ff07906 100644
--- a/src/drivers/driver_bsd.c
+++ b/src/drivers/driver_bsd.c
@@ -333,7 +333,7 @@  bsd_ctrl_iface(void *priv, int enable)
 static int
 bsd_set_key(const char *ifname, void *priv, enum wpa_alg alg,
 	    const unsigned char *addr, int key_idx, int set_tx, const u8 *seq,
-	    size_t seq_len, const u8 *key, size_t key_len)
+	    size_t seq_len, const u8 *key, size_t key_len, int key_flag)
 {
 	struct ieee80211req_key wk;
 #ifdef IEEE80211_KEY_NOREPLAY
diff --git a/src/drivers/driver_hostap.c b/src/drivers/driver_hostap.c
index 61b39b197..a7d7b6f01 100644
--- a/src/drivers/driver_hostap.c
+++ b/src/drivers/driver_hostap.c
@@ -399,7 +399,8 @@  static int wpa_driver_hostap_set_key(const char *ifname, void *priv,
 				     enum wpa_alg alg, const u8 *addr,
 				     int key_idx, int set_tx,
 				     const u8 *seq, size_t seq_len,
-				     const u8 *key, size_t key_len)
+				     const u8 *key, size_t key_len,
+				     int key_flag)
 {
 	struct hostap_driver_data *drv = priv;
 	struct prism2_hostapd_param *param;
diff --git a/src/drivers/driver_ndis.c b/src/drivers/driver_ndis.c
index 614c4521e..72ccf02b1 100644
--- a/src/drivers/driver_ndis.c
+++ b/src/drivers/driver_ndis.c
@@ -932,7 +932,7 @@  static int wpa_driver_ndis_remove_key(struct wpa_driver_ndis_data *drv,
 
 static int wpa_driver_ndis_add_wep(struct wpa_driver_ndis_data *drv,
 				   int pairwise, int key_idx, int set_tx,
-				   const u8 *key, size_t key_len)
+				   const u8 *key, size_t key_len, int key_flag)
 {
 	NDIS_802_11_WEP *wep;
 	size_t len;
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 54fe39000..ff9cc0e61 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -3015,11 +3015,13 @@  static int wpa_driver_nl80211_set_key(const char *ifname, struct i802_bss *bss,
 				      enum wpa_alg alg, const u8 *addr,
 				      int key_idx, int set_tx,
 				      const u8 *seq, size_t seq_len,
-				      const u8 *key, size_t key_len)
+				      const u8 *key, size_t key_len,
+				      int key_flag)
 {
 	struct wpa_driver_nl80211_data *drv = bss->drv;
 	int ifindex;
-	struct nl_msg *msg = NULL;
+	struct nl_msg *msg;
+	struct nl_msg *key_msg;
 	int ret;
 	int tdls = 0;
 
@@ -3029,9 +3031,9 @@  static int wpa_driver_nl80211_set_key(const char *ifname, struct i802_bss *bss,
 
 	ifindex = if_nametoindex(ifname);
 	wpa_printf(MSG_DEBUG, "%s: ifindex=%d (%s) alg=%d addr=%p key_idx=%d "
-		   "set_tx=%d seq_len=%lu key_len=%lu",
+		   "set_tx=%d seq_len=%lu key_len=%lu key_flag=%d",
 		   __func__, ifindex, ifname, alg, addr, key_idx, set_tx,
-		   (unsigned long) seq_len, (unsigned long) key_len);
+		   (unsigned long) seq_len, (unsigned long) key_len, key_flag);
 #ifdef CONFIG_TDLS
 	if (key_idx == -1) {
 		key_idx = 0;
@@ -3053,26 +3055,37 @@  static int wpa_driver_nl80211_set_key(const char *ifname, struct i802_bss *bss,
 	    (drv->capa.flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X))
 		return nl80211_set_pmk(drv, key, key_len, addr);
 
-	if (alg == WPA_ALG_NONE) {
+	key_msg = nlmsg_alloc();
+	if (!key_msg)
+		return -ENOBUFS;
+
+	if (key_flag & KEY_FLAG_SET_TX) {
+		msg = nl80211_ifindex_msg(drv, ifindex, 0, NL80211_CMD_SET_KEY);
+		if (!msg)
+			goto fail2;
+	} else if (alg == WPA_ALG_NONE) {
 		msg = nl80211_ifindex_msg(drv, ifindex, 0, NL80211_CMD_DEL_KEY);
 		if (!msg)
-			return -ENOBUFS;
+			goto fail2;
 	} else {
 		u32 suite;
 
 		suite = wpa_alg_to_cipher_suite(alg, key_len);
 		if (!suite)
-			goto fail;
+			goto fail2;
+
 		msg = nl80211_ifindex_msg(drv, ifindex, 0, NL80211_CMD_NEW_KEY);
-		if (!msg ||
-		    nla_put(msg, NL80211_ATTR_KEY_DATA, key_len, key) ||
-		    nla_put_u32(msg, NL80211_ATTR_KEY_CIPHER, suite))
+		if (!msg)
+			goto fail2;
+
+		if (nla_put(key_msg, NL80211_KEY_DATA, key_len, key) ||
+		    nla_put_u32(key_msg, NL80211_KEY_CIPHER, suite))
 			goto fail;
 		wpa_hexdump_key(MSG_DEBUG, "nl80211: KEY_DATA", key, key_len);
 	}
 
-	if (seq && seq_len) {
-		if (nla_put(msg, NL80211_ATTR_KEY_SEQ, seq_len, seq))
+	if (seq && seq_len && !(key_flag & KEY_FLAG_SET_TX)) {
+		if (nla_put(key_msg, NL80211_KEY_SEQ, seq_len, seq))
 			goto fail;
 		wpa_hexdump(MSG_DEBUG, "nl80211: KEY_SEQ", seq, seq_len);
 	}
@@ -3082,9 +3095,20 @@  static int wpa_driver_nl80211_set_key(const char *ifname, struct i802_bss *bss,
 		if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr))
 			goto fail;
 
-		if (alg != WPA_ALG_WEP && key_idx && !set_tx) {
+		if (key_flag & (KEY_FLAG_NO_AUTO_TX | KEY_FLAG_SET_TX)) {
+			wpa_printf(MSG_DEBUG, "Extended Key ID: %s for "
+				   "keyid=%d addr=" MACSTR,
+				   key_flag & KEY_FLAG_NO_AUTO_TX ?
+				   "NO_AUTO_TX" : "SET_TX",
+				   key_idx, MAC2STR(addr));
+			if (nla_put_u8(key_msg, NL80211_KEY_MODE,
+				       key_flag & KEY_FLAG_NO_AUTO_TX ?
+				       NL80211_KEY_NO_TX :
+				       NL80211_KEY_SET_TX))
+				goto fail;
+		} else if (alg != WPA_ALG_WEP && key_idx && !set_tx) {
 			wpa_printf(MSG_DEBUG, "   RSN IBSS RX GTK");
-			if (nla_put_u32(msg, NL80211_ATTR_KEY_TYPE,
+			if (nla_put_u32(key_msg, NL80211_KEY_TYPE,
 					NL80211_KEYTYPE_GROUP))
 				goto fail;
 		}
@@ -3093,13 +3117,14 @@  static int wpa_driver_nl80211_set_key(const char *ifname, struct i802_bss *bss,
 
 		wpa_printf(MSG_DEBUG, "   broadcast key");
 
-		types = nla_nest_start(msg, NL80211_ATTR_KEY_DEFAULT_TYPES);
+		types = nla_nest_start(key_msg, NL80211_KEY_DEFAULT_TYPES);
 		if (!types ||
-		    nla_put_flag(msg, NL80211_KEY_DEFAULT_TYPE_MULTICAST))
+		    nla_put_flag(key_msg, NL80211_KEY_DEFAULT_TYPE_MULTICAST))
 			goto fail;
-		nla_nest_end(msg, types);
+		nla_nest_end(key_msg, types);
 	}
-	if (nla_put_u8(msg, NL80211_ATTR_KEY_IDX, key_idx))
+	if (nla_put_u8(key_msg, NL80211_KEY_IDX, key_idx) ||
+	    nla_put_nested(msg, NL80211_ATTR_KEY, key_msg))
 		goto fail;
 
 	ret = send_and_recv_msgs(drv, msg, NULL, key ? (void *) -1 : NULL);
@@ -3113,40 +3138,50 @@  static int wpa_driver_nl80211_set_key(const char *ifname, struct i802_bss *bss,
 	 * If we failed or don't need to set the default TX key (below),
 	 * we're done here.
 	 */
-	if (ret || !set_tx || alg == WPA_ALG_NONE || tdls)
+	if (ret || !set_tx || key_flag || alg == WPA_ALG_NONE || tdls)
 		return ret;
 	if (is_ap_interface(drv->nlmode) && addr &&
 	    !is_broadcast_ether_addr(addr))
 		return ret;
 
+	key_msg = nlmsg_alloc();
+	if (!key_msg)
+		return -ENOBUFS;
+
 	msg = nl80211_ifindex_msg(drv, ifindex, 0, NL80211_CMD_SET_KEY);
-	if (!msg ||
-	    nla_put_u8(msg, NL80211_ATTR_KEY_IDX, key_idx) ||
-	    nla_put_flag(msg, (alg == WPA_ALG_IGTK ||
-			       alg == WPA_ALG_BIP_GMAC_128 ||
-			       alg == WPA_ALG_BIP_GMAC_256 ||
-			       alg == WPA_ALG_BIP_CMAC_256) ?
-			 NL80211_ATTR_KEY_DEFAULT_MGMT :
-			 NL80211_ATTR_KEY_DEFAULT))
+	if (!msg)
+		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) ?
+				   NL80211_KEY_DEFAULT_MGMT :
+				   NL80211_KEY_DEFAULT))
 		goto fail;
 	if (addr && is_broadcast_ether_addr(addr)) {
 		struct nlattr *types;
 
-		types = nla_nest_start(msg, NL80211_ATTR_KEY_DEFAULT_TYPES);
+		types = nla_nest_start(key_msg, NL80211_KEY_DEFAULT_TYPES);
 		if (!types ||
-		    nla_put_flag(msg, NL80211_KEY_DEFAULT_TYPE_MULTICAST))
+		    nla_put_flag(key_msg, NL80211_KEY_DEFAULT_TYPE_MULTICAST))
 			goto fail;
-		nla_nest_end(msg, types);
+		nla_nest_end(key_msg, types);
 	} else if (addr) {
 		struct nlattr *types;
 
-		types = nla_nest_start(msg, NL80211_ATTR_KEY_DEFAULT_TYPES);
+		types = nla_nest_start(key_msg, NL80211_KEY_DEFAULT_TYPES);
 		if (!types ||
-		    nla_put_flag(msg, NL80211_KEY_DEFAULT_TYPE_UNICAST))
+		    nla_put_flag(key_msg, NL80211_KEY_DEFAULT_TYPE_UNICAST))
 			goto fail;
-		nla_nest_end(msg, types);
+		nla_nest_end(key_msg, types);
 	}
 
+	if (nla_put_nested(msg, NL80211_ATTR_KEY, key_msg))
+		goto fail;
+
 	ret = send_and_recv_msgs(drv, msg, NULL, NULL);
 	if (ret == -ENOENT)
 		ret = 0;
@@ -3158,6 +3193,9 @@  static int wpa_driver_nl80211_set_key(const char *ifname, struct i802_bss *bss,
 fail:
 	nl80211_nlmsg_clear(msg);
 	nlmsg_free(msg);
+fail2:
+	nl80211_nlmsg_clear(key_msg);
+	nlmsg_free(key_msg);
 	return -ENOBUFS;
 }
 
@@ -3468,7 +3506,7 @@  retry:
 					   NULL, i,
 					   i == params->wep_tx_keyidx, NULL, 0,
 					   params->wep_key[i],
-					   params->wep_key_len[i]);
+					   params->wep_key_len[i], 0);
 		if (params->wep_tx_keyidx != i)
 			continue;
 		if (nl_add_key(msg, WPA_ALG_WEP, i, 1, NULL, 0,
@@ -8555,11 +8593,12 @@  static int driver_nl80211_set_key(const char *ifname, void *priv,
 				  enum wpa_alg alg, const u8 *addr,
 				  int key_idx, int set_tx,
 				  const u8 *seq, size_t seq_len,
-				  const u8 *key, size_t key_len)
+				  const u8 *key, size_t key_len, int key_flag)
 {
 	struct i802_bss *bss = priv;
 	return wpa_driver_nl80211_set_key(ifname, bss, alg, addr, key_idx,
-					  set_tx, seq, seq_len, key, key_len);
+					  set_tx, seq, seq_len, key, key_len,
+					  key_flag);
 }
 
 
diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
index 37eeb5e66..3e05205ea 100644
--- a/src/drivers/driver_nl80211_capa.c
+++ b/src/drivers/driver_nl80211_capa.c
@@ -417,6 +417,10 @@  static void wiphy_info_ext_feature_flags(struct wiphy_info_data *info,
 			      NL80211_EXT_FEATURE_DFS_OFFLOAD))
 		capa->flags |= WPA_DRIVER_FLAGS_DFS_OFFLOAD;
 
+	if (ext_feature_isset(ext_features, len,
+			      NL80211_EXT_FEATURE_EXT_KEY_ID))
+		capa->flags |= WPA_DRIVER_FLAGS_EXTENDED_KEY_ID;
+
 #ifdef CONFIG_MBO
 	if (ext_feature_isset(ext_features, len,
 			      NL80211_EXT_FEATURE_FILS_MAX_CHANNEL_TIME) &&
diff --git a/src/drivers/driver_openbsd.c b/src/drivers/driver_openbsd.c
index c06e75c0f..a6cdf5009 100644
--- a/src/drivers/driver_openbsd.c
+++ b/src/drivers/driver_openbsd.c
@@ -71,7 +71,7 @@  wpa_driver_openbsd_get_capa(void *priv, struct wpa_driver_capa *capa)
 static int
 wpa_driver_openbsd_set_key(const char *ifname, void *priv, enum wpa_alg alg,
 	    const unsigned char *addr, int key_idx, int set_tx, const u8 *seq,
-	    size_t seq_len, const u8 *key, size_t key_len)
+	    size_t seq_len, const u8 *key, size_t key_len, int key_flag)
 {
 	struct openbsd_driver_data *drv = priv;
 	struct ieee80211_keyavail keyavail;
diff --git a/src/drivers/driver_privsep.c b/src/drivers/driver_privsep.c
index a3f0837e1..977e44c6f 100644
--- a/src/drivers/driver_privsep.c
+++ b/src/drivers/driver_privsep.c
@@ -209,7 +209,8 @@  static int wpa_driver_privsep_set_key(const char *ifname, void *priv,
 				      enum wpa_alg alg, const u8 *addr,
 				      int key_idx, int set_tx,
 				      const u8 *seq, size_t seq_len,
-				      const u8 *key, size_t key_len)
+				      const u8 *key, size_t key_len,
+				      int key_flag)
 {
 	struct wpa_driver_privsep_data *drv = priv;
 	struct privsep_cmd_set_key cmd;
diff --git a/src/drivers/driver_wext.c b/src/drivers/driver_wext.c
index f7755cccd..6f63fe44d 100644
--- a/src/drivers/driver_wext.c
+++ b/src/drivers/driver_wext.c
@@ -1712,7 +1712,8 @@  static int wpa_driver_wext_set_key_ext(void *priv, enum wpa_alg alg,
 				       const u8 *addr, int key_idx,
 				       int set_tx, const u8 *seq,
 				       size_t seq_len,
-				       const u8 *key, size_t key_len)
+				       const u8 *key, size_t key_len,
+				       int key_flag)
 {
 	struct wpa_driver_wext_data *drv = priv;
 	struct iwreq iwr;
@@ -1831,7 +1832,7 @@  static int wpa_driver_wext_set_key_ext(void *priv, enum wpa_alg alg,
 int wpa_driver_wext_set_key(const char *ifname, void *priv, enum wpa_alg alg,
 			    const u8 *addr, int key_idx,
 			    int set_tx, const u8 *seq, size_t seq_len,
-			    const u8 *key, size_t key_len)
+			    const u8 *key, size_t key_len, int key_flag)
 {
 	struct wpa_driver_wext_data *drv = priv;
 	struct iwreq iwr;
@@ -1843,7 +1844,7 @@  int wpa_driver_wext_set_key(const char *ifname, void *priv, enum wpa_alg alg,
 		   (unsigned long) seq_len, (unsigned long) key_len);
 
 	ret = wpa_driver_wext_set_key_ext(drv, alg, addr, key_idx, set_tx,
-					  seq, seq_len, key, key_len);
+					  seq, seq_len, key, key_len, key_flag);
 	if (ret == 0)
 		return 0;
 
diff --git a/src/drivers/driver_wext.h b/src/drivers/driver_wext.h
index b4b5960a7..18a8cf2dc 100644
--- a/src/drivers/driver_wext.h
+++ b/src/drivers/driver_wext.h
@@ -55,7 +55,7 @@  int wpa_driver_wext_set_mode(void *priv, int mode);
 int wpa_driver_wext_set_key(const char *ifname, void *priv, enum wpa_alg alg,
 			    const u8 *addr, int key_idx,
 			    int set_tx, const u8 *seq, size_t seq_len,
-			    const u8 *key, size_t key_len);
+			    const u8 *key, size_t key_len, int key_flag);
 int wpa_driver_wext_scan(void *priv, struct wpa_driver_scan_params *params);
 struct wpa_scan_results * wpa_driver_wext_get_scan_results(void *priv);
 
diff --git a/src/drivers/nl80211_copy.h b/src/drivers/nl80211_copy.h
index dd4f86ee2..25f70dd2b 100644
--- a/src/drivers/nl80211_copy.h
+++ b/src/drivers/nl80211_copy.h
@@ -11,7 +11,7 @@ 
  * Copyright 2008 Jouni Malinen <jouni.malinen@atheros.com>
  * Copyright 2008 Colin McCabe <colin@cozybit.com>
  * Copyright 2015-2017	Intel Deutschland GmbH
- * Copyright (C) 2018 Intel Corporation
+ * Copyright (C) 2018-2019 Intel Corporation
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -1065,6 +1065,11 @@ 
  *	indicated by %NL80211_ATTR_WIPHY_FREQ and other attributes
  *	determining the width and type.
  *
+ * @NL80211_CMD_UPDATE_OWE_INFO: This interface allows the host driver to
+ *	offload OWE processing to user space. This intends to support
+ *	OWE AKM by the host drivers that implement SME but rely
+ *	on the user space for the cryptographic/DH IE processing in AP mode.
+ *
  * @NL80211_CMD_MAX: highest used command number
  * @__NL80211_CMD_AFTER_LAST: internal use
  */
@@ -1285,6 +1290,8 @@  enum nl80211_commands {
 
 	NL80211_CMD_NOTIFY_RADAR,
 
+	NL80211_CMD_UPDATE_OWE_INFO,
+
 	/* add new commands above here */
 
 	/* used to define NL80211_CMD_MAX below */
@@ -2308,6 +2315,15 @@  enum nl80211_commands {
  * @NL80211_ATTR_AIRTIME_WEIGHT: Station's weight when scheduled by the airtime
  *	scheduler.
  *
+ * @NL80211_ATTR_STA_TX_POWER_SETTING: Transmit power setting type (u8) for
+ *	station associated with the AP. See &enum nl80211_tx_power_setting for
+ *	possible values.
+ * @NL80211_ATTR_STA_TX_POWER: Transmit power level (s16) in dBm units. This
+ *	allows to set Tx power for a station. If this attribute is not included,
+ *	the default per-interface tx power setting will be overriding. Driver
+ *	should be picking up the lowest tx power, either tx power per-interface
+ *	or per-station.
+ *
  * @NUM_NL80211_ATTR: total number of nl80211_attrs available
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
@@ -2758,6 +2774,8 @@  enum nl80211_attrs {
 	NL80211_ATTR_PEER_MEASUREMENTS,
 
 	NL80211_ATTR_AIRTIME_WEIGHT,
+	NL80211_ATTR_STA_TX_POWER_SETTING,
+	NL80211_ATTR_STA_TX_POWER,
 
 	/* add attributes here, update the policy in nl80211.c */
 
@@ -2802,7 +2820,7 @@  enum nl80211_attrs {
 
 #define NL80211_MAX_SUPP_RATES			32
 #define NL80211_MAX_SUPP_HT_RATES		77
-#define NL80211_MAX_SUPP_REG_RULES		64
+#define NL80211_MAX_SUPP_REG_RULES		128
 #define NL80211_TKIP_DATA_OFFSET_ENCR_KEY	0
 #define NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY	16
 #define NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY	24
@@ -3139,6 +3157,7 @@  enum nl80211_sta_bss_param {
  * @NL80211_STA_INFO_TX_DURATION: aggregate PPDU duration for all frames
  *	sent to the station (u64, usec)
  * @NL80211_STA_INFO_AIRTIME_WEIGHT: current airtime weight for station (u16)
+ * @NL80211_STA_INFO_AIRTIME_LINK_METRIC: airtime link metric for mesh station
  * @__NL80211_STA_INFO_AFTER_LAST: internal
  * @NL80211_STA_INFO_MAX: highest possible station info attribute
  */
@@ -3184,6 +3203,7 @@  enum nl80211_sta_info {
 	NL80211_STA_INFO_CONNECTED_TO_GATE,
 	NL80211_STA_INFO_TX_DURATION,
 	NL80211_STA_INFO_AIRTIME_WEIGHT,
+	NL80211_STA_INFO_AIRTIME_LINK_METRIC,
 
 	/* keep last */
 	__NL80211_STA_INFO_AFTER_LAST,
@@ -3638,6 +3658,14 @@  enum nl80211_reg_rule_attr {
  *	value as specified by &struct nl80211_bss_select_rssi_adjust.
  * @NL80211_SCHED_SCAN_MATCH_ATTR_BSSID: BSSID to be used for matching
  *	(this cannot be used together with SSID).
+ * @NL80211_SCHED_SCAN_MATCH_PER_BAND_RSSI: Nested attribute that carries the
+ *	band specific minimum rssi thresholds for the bands defined in
+ *	enum nl80211_band. The minimum rssi threshold value(s32) specific to a
+ *	band shall be encapsulated in attribute with type value equals to one
+ *	of the NL80211_BAND_* defined in enum nl80211_band. For example, the
+ *	minimum rssi threshold value for 2.4GHZ band shall be encapsulated
+ *	within an attribute of type NL80211_BAND_2GHZ. And one or more of such
+ *	attributes will be nested within this attribute.
  * @NL80211_SCHED_SCAN_MATCH_ATTR_MAX: highest scheduled scan filter
  *	attribute number currently defined
  * @__NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST: internal use
@@ -3650,6 +3678,7 @@  enum nl80211_sched_scan_match_attr {
 	NL80211_SCHED_SCAN_MATCH_ATTR_RELATIVE_RSSI,
 	NL80211_SCHED_SCAN_MATCH_ATTR_RSSI_ADJUST,
 	NL80211_SCHED_SCAN_MATCH_ATTR_BSSID,
+	NL80211_SCHED_SCAN_MATCH_PER_BAND_RSSI,
 
 	/* keep last */
 	__NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST,
@@ -4134,6 +4163,27 @@  enum nl80211_channel_type {
 	NL80211_CHAN_HT40PLUS
 };
 
+/**
+ * enum nl80211_key_mode - Key mode
+ *
+ * @NL80211_KEY_RX_TX: (Default)
+ *	Key can be used for Rx and Tx immediately
+ *
+ * The following modes can only be selected for unicast keys and when the
+ * driver supports @NL80211_EXT_FEATURE_EXT_KEY_ID:
+ *
+ * @NL80211_KEY_NO_TX: Only allowed in combination with @NL80211_CMD_NEW_KEY:
+ *	Unicast key can only be used for Rx, Tx not allowed, yet
+ * @NL80211_KEY_SET_TX: Only allowed in combination with @NL80211_CMD_SET_KEY:
+ *	The unicast key identified by idx and mac is cleared for Tx and becomes
+ *	the preferred Tx key for the station.
+ */
+enum nl80211_key_mode {
+	NL80211_KEY_RX_TX,
+	NL80211_KEY_NO_TX,
+	NL80211_KEY_SET_TX
+};
+
 /**
  * enum nl80211_chan_width - channel width definitions
  *
@@ -4377,6 +4427,9 @@  enum nl80211_key_default_types {
  * @NL80211_KEY_DEFAULT_TYPES: A nested attribute containing flags
  *	attributes, specifying what a key should be set as default as.
  *	See &enum nl80211_key_default_types.
+ * @NL80211_KEY_MODE: the mode from enum nl80211_key_mode.
+ *	Defaults to @NL80211_KEY_RX_TX.
+ *
  * @__NL80211_KEY_AFTER_LAST: internal
  * @NL80211_KEY_MAX: highest key attribute
  */
@@ -4390,6 +4443,7 @@  enum nl80211_key_attributes {
 	NL80211_KEY_DEFAULT_MGMT,
 	NL80211_KEY_TYPE,
 	NL80211_KEY_DEFAULT_TYPES,
+	NL80211_KEY_MODE,
 
 	/* keep last */
 	__NL80211_KEY_AFTER_LAST,
@@ -5335,6 +5389,8 @@  enum nl80211_feature_flags {
  *      able to rekey an in-use key correctly. Userspace must not rekey PTK keys
  *      if this flag is not set. Ignoring this can leak clear text packets and/or
  *      freeze the connection.
+ * @NL80211_EXT_FEATURE_EXT_KEY_ID: Driver supports "Extended Key ID for
+ *      Individually Addressed Frames" from IEEE802.11-2016.
  *
  * @NL80211_EXT_FEATURE_AIRTIME_FAIRNESS: Driver supports getting airtime
  *	fairness for transmitted packets and has enabled airtime fairness
@@ -5343,6 +5399,12 @@  enum nl80211_feature_flags {
  * @NL80211_EXT_FEATURE_AP_PMKSA_CACHING: Driver/device supports PMKSA caching
  *	(set/del PMKSA operations) in AP mode.
  *
+ * @NL80211_EXT_FEATURE_SCHED_SCAN_BAND_SPECIFIC_RSSI_THOLD: Driver supports
+ *	filtering of sched scan results using band specific RSSI thresholds.
+ *
+ * @NL80211_EXT_FEATURE_STA_TX_PWR: This driver supports controlling tx power
+ *	to a station.
+ *
  * @NUM_NL80211_EXT_FEATURES: number of extended features.
  * @MAX_NL80211_EXT_FEATURES: highest extended feature index.
  */
@@ -5384,6 +5446,9 @@  enum nl80211_ext_feature_index {
 	NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER,
 	NL80211_EXT_FEATURE_AIRTIME_FAIRNESS,
 	NL80211_EXT_FEATURE_AP_PMKSA_CACHING,
+	NL80211_EXT_FEATURE_SCHED_SCAN_BAND_SPECIFIC_RSSI_THOLD,
+	NL80211_EXT_FEATURE_EXT_KEY_ID,
+	NL80211_EXT_FEATURE_STA_TX_PWR,
 
 	/* add new features before the definition below */
 	NUM_NL80211_EXT_FEATURES,
diff --git a/src/rsn_supp/tdls.c b/src/rsn_supp/tdls.c
index 704c95e68..166bf42c6 100644
--- a/src/rsn_supp/tdls.c
+++ b/src/rsn_supp/tdls.c
@@ -178,7 +178,7 @@  static u8 * wpa_add_ie(u8 *pos, const u8 *ie, size_t ie_len)
 static int wpa_tdls_del_key(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
 {
 	if (wpa_sm_set_key(sm, WPA_ALG_NONE, peer->addr,
-			   0, 0, NULL, 0, NULL, 0) < 0) {
+			   0, 0, NULL, 0, NULL, 0, 0) < 0) {
 		wpa_printf(MSG_WARNING, "TDLS: Failed to delete TPK-TK from "
 			   "the driver");
 		return -1;
@@ -228,7 +228,7 @@  static int wpa_tdls_set_key(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
 	wpa_printf(MSG_DEBUG, "TDLS: Configure pairwise key for peer " MACSTR,
 		   MAC2STR(peer->addr));
 	if (wpa_sm_set_key(sm, alg, peer->addr, -1, 1,
-			   rsc, sizeof(rsc), peer->tpk.tk, key_len) < 0) {
+			   rsc, sizeof(rsc), peer->tpk.tk, key_len, 0) < 0) {
 		wpa_printf(MSG_WARNING, "TDLS: Failed to set TPK to the "
 			   "driver");
 		return -1;
diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c
index 9163f61fa..8a5cbe2fe 100644
--- a/src/rsn_supp/wpa.c
+++ b/src/rsn_supp/wpa.c
@@ -760,7 +760,8 @@  static void wpa_sm_rekey_ptk(void *eloop_ctx, void *timeout_ctx)
 
 
 static int wpa_supplicant_install_ptk(struct wpa_sm *sm,
-				      const struct wpa_eapol_key *key)
+				      const struct wpa_eapol_key *key,
+				      int key_flag)
 {
 	int keylen, rsclen;
 	enum wpa_alg alg;
@@ -805,7 +806,7 @@  static int wpa_supplicant_install_ptk(struct wpa_sm *sm,
 	}
 
 	if (wpa_sm_set_key(sm, alg, sm->bssid, 0, 1, key_rsc, rsclen,
-			   sm->ptk.tk, keylen) < 0) {
+			   sm->ptk.tk, keylen, key_flag) < 0) {
 		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
 			"WPA: Failed to set PTK to the "
 			"driver (alg=%d keylen=%d bssid=" MACSTR ")",
@@ -898,7 +899,7 @@  static int wpa_supplicant_install_gtk(struct wpa_sm *sm,
 	if (sm->pairwise_cipher == WPA_CIPHER_NONE) {
 		if (wpa_sm_set_key(sm, gd->alg, NULL,
 				   gd->keyidx, 1, key_rsc, gd->key_rsc_len,
-				   _gtk, gd->gtk_len) < 0) {
+				   _gtk, gd->gtk_len, 0) < 0) {
 			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
 				"WPA: Failed to set GTK to the driver "
 				"(Group only)");
@@ -907,7 +908,7 @@  static int wpa_supplicant_install_gtk(struct wpa_sm *sm,
 		}
 	} else if (wpa_sm_set_key(sm, gd->alg, broadcast_ether_addr,
 				  gd->keyidx, gd->tx, key_rsc, gd->key_rsc_len,
-				  _gtk, gd->gtk_len) < 0) {
+				  _gtk, gd->gtk_len, 0) < 0) {
 		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
 			"WPA: Failed to set GTK to "
 			"the driver (alg=%d keylen=%d keyidx=%d)",
@@ -1062,7 +1063,7 @@  static int wpa_supplicant_install_igtk(struct wpa_sm *sm,
 	if (wpa_sm_set_key(sm, wpa_cipher_to_alg(sm->mgmt_group_cipher),
 			   broadcast_ether_addr,
 			   keyidx, 0, igtk->pn, sizeof(igtk->pn),
-			   igtk->igtk, len) < 0) {
+			   igtk->igtk, len, 0) < 0) {
 		if (keyidx == 0x0400 || keyidx == 0x0500) {
 			/* Assume the AP has broken PMF implementation since it
 			 * seems to have swapped the KeyID bytes. The AP cannot
@@ -1511,7 +1512,7 @@  static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm,
 	sm->renew_snonce = 1;
 
 	if (key_info & WPA_KEY_INFO_INSTALL) {
-		if (wpa_supplicant_install_ptk(sm, key))
+		if (wpa_supplicant_install_ptk(sm, key, 0))
 			goto failed;
 	}
 
@@ -2086,7 +2087,7 @@  static void wpa_eapol_key_dump(struct wpa_sm *sm,
 	wpa_hexdump(MSG_DEBUG, "  key_nonce", key->key_nonce, WPA_NONCE_LEN);
 	wpa_hexdump(MSG_DEBUG, "  key_iv", key->key_iv, 16);
 	wpa_hexdump(MSG_DEBUG, "  key_rsc", key->key_rsc, 8);
-	wpa_hexdump(MSG_DEBUG, "  key_id (reserved)", key->key_id, 8);
+	wpa_hexdump(MSG_DEBUG, "  key_id", key->key_id, 8);
 	wpa_hexdump(MSG_DEBUG, "  key_mic", mic, mic_len);
 #endif /* CONFIG_NO_STDOUT_DEBUG */
 }
@@ -4417,7 +4418,7 @@  int fils_process_assoc_resp(struct wpa_sm *sm, const u8 *resp, size_t len)
 	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,
-			   sm->ptk.tk, keylen) < 0) {
+			   sm->ptk.tk, keylen, 0) < 0) {
 		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
 			"FILS: Failed to set PTK to the driver (alg=%d keylen=%d bssid="
 			MACSTR ")",
diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h
index 8903f8e14..7a100fddc 100644
--- a/src/rsn_supp/wpa.h
+++ b/src/rsn_supp/wpa.h
@@ -30,7 +30,7 @@  struct wpa_sm_ctx {
 	int (*set_key)(void *ctx, enum wpa_alg alg,
 		       const u8 *addr, int key_idx, int set_tx,
 		       const u8 *seq, size_t seq_len,
-		       const u8 *key, size_t key_len);
+		       const u8 *key, size_t key_len, int key_flag);
 	void * (*get_network_ctx)(void *ctx);
 	int (*get_bssid)(void *ctx, u8 *bssid);
 	int (*ether_send)(void *ctx, const u8 *dest, u16 proto, const u8 *buf,
diff --git a/src/rsn_supp/wpa_ft.c b/src/rsn_supp/wpa_ft.c
index 7dcb1043b..d138591f7 100644
--- a/src/rsn_supp/wpa_ft.c
+++ b/src/rsn_supp/wpa_ft.c
@@ -404,7 +404,7 @@  static int wpa_ft_install_ptk(struct wpa_sm *sm, const u8 *bssid)
 	keylen = wpa_cipher_key_len(sm->pairwise_cipher);
 
 	if (wpa_sm_set_key(sm, alg, bssid, 0, 1, null_rsc,
-			   sizeof(null_rsc), (u8 *) sm->ptk.tk, keylen) < 0) {
+			   sizeof(null_rsc), (u8 *) sm->ptk.tk, keylen, 0) < 0) {
 		wpa_printf(MSG_WARNING, "FT: Failed to set PTK to the driver");
 		return -1;
 	}
@@ -748,7 +748,7 @@  static int wpa_ft_process_gtk_subelem(struct wpa_sm *sm, const u8 *gtk_elem,
 		os_memcpy(gtk + 24, tmp, 8);
 	}
 	if (wpa_sm_set_key(sm, alg, broadcast_ether_addr, keyidx, 0,
-			   gtk_elem + 3, rsc_len, gtk, keylen) < 0) {
+			   gtk_elem + 3, rsc_len, gtk, keylen, 0) < 0) {
 		wpa_printf(MSG_WARNING, "WPA: Failed to set GTK to the "
 			   "driver.");
 		return -1;
@@ -816,7 +816,7 @@  static int wpa_ft_process_igtk_subelem(struct wpa_sm *sm, const u8 *igtk_elem,
 			igtk_len);
 	if (wpa_sm_set_key(sm, wpa_cipher_to_alg(sm->mgmt_group_cipher),
 			   broadcast_ether_addr, keyidx, 0,
-			   igtk_elem + 2, 6, igtk, igtk_len) < 0) {
+			   igtk_elem + 2, 6, igtk, igtk_len, 0) < 0) {
 		wpa_printf(MSG_WARNING, "WPA: Failed to set IGTK to the "
 			   "driver.");
 		os_memset(igtk, 0, sizeof(igtk));
diff --git a/src/rsn_supp/wpa_i.h b/src/rsn_supp/wpa_i.h
index 0c5955c66..ed8cac767 100644
--- a/src/rsn_supp/wpa_i.h
+++ b/src/rsn_supp/wpa_i.h
@@ -197,11 +197,11 @@  static inline void wpa_sm_deauthenticate(struct wpa_sm *sm, int reason_code)
 static inline int wpa_sm_set_key(struct wpa_sm *sm, enum wpa_alg alg,
 				 const u8 *addr, int key_idx, int set_tx,
 				 const u8 *seq, size_t seq_len,
-				 const u8 *key, size_t key_len)
+				 const u8 *key, size_t key_len, int key_flag)
 {
 	WPA_ASSERT(sm->ctx->set_key);
 	return sm->ctx->set_key(sm->ctx->ctx, alg, addr, key_idx, set_tx,
-				seq, seq_len, key, key_len);
+				seq, seq_len, key, key_len, key_flag);
 }
 
 static inline void * wpa_sm_get_network_ctx(struct wpa_sm *sm)
diff --git a/tests/hwsim/test_ap_ciphers.py b/tests/hwsim/test_ap_ciphers.py
index 59fb651ad..0061d521d 100644
--- a/tests/hwsim/test_ap_ciphers.py
+++ b/tests/hwsim/test_ap_ciphers.py
@@ -852,7 +852,7 @@  def test_ap_wpa2_delayed_m1_m3_zero_tk(dev, apdev):
     if "OK" not in hapd.request("RESEND_M3 " + addr):
         raise Exception("RESEND_M3 failed")
 
-    if "OK" not in hapd.request("SET_KEY 3 %s %d %d %s %s" % (addr, 0, 1, 6*"00", 16*"00")):
+    if "OK" not in hapd.request("SET_KEY 3 %s %d %d %s %s 0" % (addr, 0, 1, 6*"00", 16*"00")):
         raise Exception("SET_KEY failed")
     time.sleep(0.1)
     hwsim_utils.test_connectivity(dev[0], hapd, timeout=1, broadcast=False,
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index 198ac562d..2b6d45665 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -5194,17 +5194,17 @@  static void wpa_supplicant_ctrl_iface_drop_sa(struct wpa_supplicant *wpa_s)
 {
 	wpa_printf(MSG_DEBUG, "Dropping SA without deauthentication");
 	/* MLME-DELETEKEYS.request */
-	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 0, 0, NULL, 0, NULL, 0);
-	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 1, 0, NULL, 0, NULL, 0);
-	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 2, 0, NULL, 0, NULL, 0);
-	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 3, 0, NULL, 0, NULL, 0);
+	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 0, 0, NULL, 0, NULL, 0, 0);
+	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 1, 0, NULL, 0, NULL, 0, 0);
+	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 2, 0, NULL, 0, NULL, 0, 0);
+	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 3, 0, NULL, 0, NULL, 0, 0);
 #ifdef CONFIG_IEEE80211W
-	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 4, 0, NULL, 0, NULL, 0);
-	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 5, 0, NULL, 0, NULL, 0);
+	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 4, 0, NULL, 0, NULL, 0, 0);
+	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 5, 0, NULL, 0, NULL, 0, 0);
 #endif /* CONFIG_IEEE80211W */
 
 	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, wpa_s->bssid, 0, 0, NULL, 0, NULL,
-			0);
+			0, 0);
 	/* MLME-SETPROTECTION.request(None) */
 	wpa_drv_mlme_setprotection(wpa_s, wpa_s->bssid,
 				   MLME_SETPROTECTION_PROTECT_TYPE_NONE,
@@ -9184,13 +9184,13 @@  static int wpas_ctrl_reset_pn(struct wpa_supplicant *wpa_s)
 	 * in the driver. */
 	if (wpa_drv_set_key(wpa_s, wpa_s->last_tk_alg, wpa_s->last_tk_addr,
 			    wpa_s->last_tk_key_idx, 1, zero, 6,
-			    zero, wpa_s->last_tk_len) < 0)
+			    zero, wpa_s->last_tk_len, 0) < 0)
 		return -1;
 
 	/* Set the previously configured key to reset its TSC/RSC */
 	return wpa_drv_set_key(wpa_s, wpa_s->last_tk_alg, wpa_s->last_tk_addr,
 			       wpa_s->last_tk_key_idx, 1, zero, 6,
-			       wpa_s->last_tk, wpa_s->last_tk_len);
+			       wpa_s->last_tk, wpa_s->last_tk_len, 0);
 }
 
 
diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h
index 4a9f472e8..88f8eedc5 100644
--- a/wpa_supplicant/driver_i.h
+++ b/wpa_supplicant/driver_i.h
@@ -142,7 +142,7 @@  static inline int wpa_drv_set_key(struct wpa_supplicant *wpa_s,
 				  enum wpa_alg alg, const u8 *addr,
 				  int key_idx, int set_tx,
 				  const u8 *seq, size_t seq_len,
-				  const u8 *key, size_t key_len)
+				  const u8 *key, size_t key_len, int key_flag)
 {
 	if (alg != WPA_ALG_NONE) {
 		if (key_idx >= 0 && key_idx <= 6)
@@ -153,7 +153,7 @@  static inline int wpa_drv_set_key(struct wpa_supplicant *wpa_s,
 	if (wpa_s->driver->set_key) {
 		return wpa_s->driver->set_key(wpa_s->ifname, wpa_s->drv_priv,
 					      alg, addr, key_idx, set_tx,
-					      seq, seq_len, key, key_len);
+					      seq, seq_len, key, key_len, key_flag);
 	}
 	return -1;
 }
diff --git a/wpa_supplicant/ibss_rsn.c b/wpa_supplicant/ibss_rsn.c
index e96ea65a7..798c60975 100644
--- a/wpa_supplicant/ibss_rsn.c
+++ b/wpa_supplicant/ibss_rsn.c
@@ -139,7 +139,7 @@  static void ibss_check_rsn_completed(struct ibss_rsn_peer *peer)
 static int supp_set_key(void *ctx, enum wpa_alg alg,
 			const u8 *addr, int key_idx, int set_tx,
 			const u8 *seq, size_t seq_len,
-			const u8 *key, size_t key_len)
+			const u8 *key, size_t key_len, int key_flag)
 {
 	struct ibss_rsn_peer *peer = ctx;
 
@@ -166,7 +166,7 @@  static int supp_set_key(void *ctx, enum wpa_alg alg,
 	if (is_broadcast_ether_addr(addr))
 		addr = peer->addr;
 	return wpa_drv_set_key(peer->ibss_rsn->wpa_s, alg, addr, key_idx,
-			       set_tx, seq, seq_len, key, key_len);
+			       set_tx, seq, seq_len, key, key_len, key_flag);
 }
 
 
@@ -295,7 +295,8 @@  static int auth_send_eapol(void *ctx, const u8 *addr, const u8 *data,
 
 
 static int auth_set_key(void *ctx, int vlan_id, enum wpa_alg alg,
-			const u8 *addr, int idx, u8 *key, size_t key_len)
+			const u8 *addr, int idx, u8 *key, size_t key_len,
+			int key_flag)
 {
 	struct ibss_rsn *ibss_rsn = ctx;
 	u8 seq[6];
@@ -334,7 +335,7 @@  static int auth_set_key(void *ctx, int vlan_id, enum wpa_alg alg,
 	}
 
 	return wpa_drv_set_key(ibss_rsn->wpa_s, alg, addr, idx,
-			       1, seq, 6, key, key_len);
+			       1, seq, 6, key, key_len, key_flag);
 }
 
 
@@ -851,7 +852,7 @@  static void ibss_rsn_handle_auth_1_of_2(struct ibss_rsn *ibss_rsn,
 		wpa_printf(MSG_DEBUG, "RSN: Clear pairwise key for peer "
 			   MACSTR, MAC2STR(addr));
 		wpa_drv_set_key(ibss_rsn->wpa_s, WPA_ALG_NONE, addr, 0, 0,
-				NULL, 0, NULL, 0);
+				NULL, 0, NULL, 0, 0);
 	}
 
 	if (peer &&
diff --git a/wpa_supplicant/mesh_mpm.c b/wpa_supplicant/mesh_mpm.c
index 9d6ab8da1..a751a1de3 100644
--- a/wpa_supplicant/mesh_mpm.c
+++ b/wpa_supplicant/mesh_mpm.c
@@ -844,7 +844,7 @@  static void mesh_mpm_plink_estab(struct wpa_supplicant *wpa_s,
 		wpa_hexdump_key(MSG_DEBUG, "mesh: MTK", sta->mtk, sta->mtk_len);
 		wpa_drv_set_key(wpa_s, wpa_cipher_to_alg(conf->pairwise_cipher),
 				sta->addr, 0, 0, seq, sizeof(seq),
-				sta->mtk, sta->mtk_len);
+				sta->mtk, sta->mtk_len, 0);
 
 		wpa_hexdump_key(MSG_DEBUG, "mesh: RX MGTK Key RSC",
 				sta->mgtk_rsc, sizeof(sta->mgtk_rsc));
@@ -853,7 +853,7 @@  static void mesh_mpm_plink_estab(struct wpa_supplicant *wpa_s,
 		wpa_drv_set_key(wpa_s, wpa_cipher_to_alg(conf->group_cipher),
 				sta->addr, sta->mgtk_key_id, 0,
 				sta->mgtk_rsc, sizeof(sta->mgtk_rsc),
-				sta->mgtk, sta->mgtk_len);
+				sta->mgtk, sta->mgtk_len, 0);
 
 		if (sta->igtk_len) {
 			wpa_hexdump_key(MSG_DEBUG, "mesh: RX IGTK Key RSC",
@@ -865,7 +865,7 @@  static void mesh_mpm_plink_estab(struct wpa_supplicant *wpa_s,
 				wpa_cipher_to_alg(conf->mgmt_group_cipher),
 				sta->addr, sta->igtk_key_id, 0,
 				sta->igtk_rsc, sizeof(sta->igtk_rsc),
-				sta->igtk, sta->igtk_len);
+				sta->igtk, sta->igtk_len, 0);
 		}
 	}
 
diff --git a/wpa_supplicant/mesh_rsn.c b/wpa_supplicant/mesh_rsn.c
index 4b8d6c469..9e7e89634 100644
--- a/wpa_supplicant/mesh_rsn.c
+++ b/wpa_supplicant/mesh_rsn.c
@@ -100,7 +100,8 @@  static const u8 *auth_get_psk(void *ctx, const u8 *addr,
 
 
 static int auth_set_key(void *ctx, int vlan_id, enum wpa_alg alg,
-			const u8 *addr, int idx, u8 *key, size_t key_len)
+			const u8 *addr, int idx, u8 *key, size_t key_len,
+			int key_flag)
 {
 	struct mesh_rsn *mesh_rsn = ctx;
 	u8 seq[6];
@@ -118,7 +119,7 @@  static int auth_set_key(void *ctx, int vlan_id, enum wpa_alg alg,
 	wpa_hexdump_key(MSG_DEBUG, "AUTH: set_key - key", key, key_len);
 
 	return wpa_drv_set_key(mesh_rsn->wpa_s, alg, addr, idx,
-			       1, seq, 6, key, key_len);
+			       1, seq, 6, key, key_len, 0);
 }
 
 
@@ -199,7 +200,7 @@  static int __mesh_rsn_auth_init(struct mesh_rsn *rsn, const u8 *addr,
 		wpa_drv_set_key(rsn->wpa_s,
 				wpa_cipher_to_alg(rsn->mgmt_group_cipher), NULL,
 				rsn->igtk_key_id, 1,
-				seq, sizeof(seq), rsn->igtk, rsn->igtk_len);
+				seq, sizeof(seq), rsn->igtk, rsn->igtk_len, 0);
 	}
 #endif /* CONFIG_IEEE80211W */
 
@@ -208,7 +209,7 @@  static int __mesh_rsn_auth_init(struct mesh_rsn *rsn, const u8 *addr,
 			rsn->mgtk, rsn->mgtk_len);
 	wpa_drv_set_key(rsn->wpa_s, wpa_cipher_to_alg(rsn->group_cipher), NULL,
 			rsn->mgtk_key_id, 1, seq, sizeof(seq),
-			rsn->mgtk, rsn->mgtk_len);
+			rsn->mgtk, rsn->mgtk_len, 0);
 
 	return 0;
 }
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 96a3691cf..03e1658cc 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -138,7 +138,7 @@  int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
 		set = 1;
 		wpa_drv_set_key(wpa_s, WPA_ALG_WEP, NULL,
 				i, i == ssid->wep_tx_keyidx, NULL, 0,
-				ssid->wep_key[i], ssid->wep_key_len[i]);
+				ssid->wep_key[i], ssid->wep_key_len[i], 0);
 	}
 
 	return set;
@@ -196,7 +196,7 @@  int wpa_supplicant_set_wpa_none_key(struct wpa_supplicant *wpa_s,
 	/* TODO: should actually remember the previously used seq#, both for TX
 	 * and RX from each STA.. */
 
-	ret = wpa_drv_set_key(wpa_s, alg, NULL, 0, 1, seq, 6, key, keylen);
+	ret = wpa_drv_set_key(wpa_s, alg, NULL, 0, 1, seq, 6, key, keylen, 0);
 	os_memset(key, 0, sizeof(key));
 	return ret;
 }
@@ -702,12 +702,12 @@  void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr)
 		if (wpa_s->keys_cleared & BIT(i))
 			continue;
 		wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, i, 0, NULL, 0,
-				NULL, 0);
+				NULL, 0, 0);
 	}
 	if (!(wpa_s->keys_cleared & BIT(0)) && addr &&
 	    !is_zero_ether_addr(addr)) {
 		wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 0, 0, NULL, 0, NULL,
-				0);
+				0, 0);
 		/* MLME-SETPROTECTION.request(None) */
 		wpa_drv_mlme_setprotection(
 			wpa_s, addr,
diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c
index 449e04acd..0b5da9c9f 100644
--- a/wpa_supplicant/wpas_glue.c
+++ b/wpa_supplicant/wpas_glue.c
@@ -242,7 +242,7 @@  static int wpa_eapol_set_wep_key(void *ctx, int unicast, int keyidx,
 	}
 	return wpa_drv_set_key(wpa_s, WPA_ALG_WEP,
 			       unicast ? wpa_s->bssid : NULL,
-			       keyidx, unicast, NULL, 0, key, keylen);
+			       keyidx, unicast, NULL, 0, key, keylen, 0);
 }
 
 
@@ -341,7 +341,7 @@  static void wpa_supplicant_eapol_cb(struct eapol_sm *eapol,
 			"handshake", pmk, pmk_len);
 
 	if (wpa_drv_set_key(wpa_s, WPA_ALG_PMK, NULL, 0, 0, NULL, 0, pmk,
-			    pmk_len)) {
+			    pmk_len, 0)) {
 		wpa_printf(MSG_DEBUG, "Failed to set PMK to the driver");
 	}
 
@@ -488,7 +488,7 @@  static int wpa_supplicant_get_bssid(void *ctx, u8 *bssid)
 static int wpa_supplicant_set_key(void *_wpa_s, enum wpa_alg alg,
 				  const u8 *addr, int key_idx, int set_tx,
 				  const u8 *seq, size_t seq_len,
-				  const u8 *key, size_t key_len)
+				  const u8 *key, size_t key_len, int key_flag)
 {
 	struct wpa_supplicant *wpa_s = _wpa_s;
 	if (alg == WPA_ALG_TKIP && key_idx == 0 && key_len == 32) {
@@ -513,7 +513,7 @@  static int wpa_supplicant_set_key(void *_wpa_s, enum wpa_alg alg,
 	}
 #endif /* CONFIG_TESTING_OPTIONS */
 	return wpa_drv_set_key(wpa_s, alg, addr, key_idx, set_tx, seq, seq_len,
-			       key, key_len);
+			       key, key_len, key_flag);
 }
 
 
@@ -1160,7 +1160,7 @@  static int wpa_supplicant_key_mgmt_set_pmk(void *ctx, const u8 *pmk,
 	if (wpa_s->conf->key_mgmt_offload &&
 	    (wpa_s->drv_flags & WPA_DRIVER_FLAGS_KEY_MGMT_OFFLOAD))
 		return wpa_drv_set_key(wpa_s, WPA_ALG_PMK, NULL, 0, 0,
-				       NULL, 0, pmk, pmk_len);
+				       NULL, 0, pmk, pmk_len, 0);
 	else
 		return 0;
 }