[RFC,1/3] Update API and drivers for extended Key ID

Message ID 20181111115441.15015-2-alexander.wetzel@web.de
State New
Headers show
Series
  • Extended Key ID support
Related show

Commit Message

Alexander Wetzel Nov. 11, 2018, 11:54 a.m.
From: Alexander Wetzel <alexander@wetzel-home.de>

nl80211 support for Extended Key ID and switch all other drivers to the
new API.

Also syncs nl80211_copy.h with git version from linux wireless git
wt-2018-11-07 with additional and unofficial extensions which are still
WIP.

Signed-off-by: Alexander Wetzel <alexander@wetzel-home.de>
---
 src/common/wpa_common.h           |   4 +
 src/drivers/driver.h              |  20 ++++-
 src/drivers/driver_atheros.c      |   8 +-
 src/drivers/driver_bsd.c          |  10 +--
 src/drivers/driver_hostap.c       |   5 +-
 src/drivers/driver_ndis.c         |  10 +--
 src/drivers/driver_nl80211.c      |  30 +++++--
 src/drivers/driver_nl80211_capa.c |   4 +
 src/drivers/driver_openbsd.c      |   2 +-
 src/drivers/driver_privsep.c      |   8 +-
 src/drivers/driver_wext.c         |  19 ++--
 src/drivers/nl80211_copy.h        | 139 ++++++++++++++++++++++++++++++
 12 files changed, 218 insertions(+), 41 deletions(-)

Patch

diff --git a/src/common/wpa_common.h b/src/common/wpa_common.h
index 626174440..ee03fd34d 100644
--- a/src/common/wpa_common.h
+++ b/src/common/wpa_common.h
@@ -201,6 +201,10 @@  struct wpa_eapol_key {
 #define FILS_ICK_MAX_LEN 48
 #define FILS_FT_MAX_LEN 48
 
+#define KEY_FLAG_DEFAULT_KEY BIT(0)
+#define KEY_FLAG_RX_ONLY BIT(1)
+#define KEY_FLAG_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 d34c6794f..22848a19d 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -1579,6 +1579,8 @@  struct wpa_driver_capa {
 #define WPA_DRIVER_FLAGS_MFP_OPTIONAL		0x0040000000000000ULL
 /** Driver is a self-managed regulatory device */
 #define WPA_DRIVER_FLAGS_SELF_MANAGED_REGULATORY       0x0080000000000000ULL
+/** Driver supports Extended Key ID */
+#define WPA_DRIVER_FLAGS_EXTENDED_KEY_ID	0x0100000000000000ULL
 	u64 flags;
 
 #define FULL_AP_CLIENT_STATE_SUPP(drv_flags) \
@@ -2169,8 +2171,20 @@  struct wpa_driver_ops {
 	 *	specified key index is to be cleared
 	 * @key_idx: key index (0..3), usually 0 for unicast keys; 0..4095 for
 	 *	IGTK
-	 * @set_tx: configure this key as the default Tx key (only used when
-	 *	driver does not support separate unicast/individual key
+	 * @key_flag: Additional flag for key install.
+	 *      Can be zero or one of the following:
+	 *	%KEY_FLAG_DEFAULT_KEY:
+	 *	    configure this key as the default Tx key (only used when
+	 *	    driver does not support separate unicast/individual keys)
+	 *	%KEY_FLAG_RX_ONLY:
+	 *	    Install the unicast key in driver for only Rx.
+	 *	    Can only be used when driver has set
+	 *	    %WPA_DRIVER_FLAGS_EXTENDED_KEY_ID
+	 *	%KEY_FLAG_TX:
+	 *	    Activate key_idx for addr for Tx (Key must previously have
+	 *	    been installed with %KEY_FLAG_RX_ONLY flag set.)
+	 *	    only @ifname, @priv, @addr and @key_idx are required when
+	 *	    this flag is set.
 	 * @seq: sequence number/packet number, seq_len octets, the next
 	 *	packet number to be used for in replay protection; configured
 	 *	for Rx keys (in most cases, this is only used with broadcast
@@ -2203,7 +2217,7 @@  struct wpa_driver_ops {
 	 * example on how this can be done.
 	 */
 	int (*set_key)(const char *ifname, void *priv, enum wpa_alg alg,
-		       const u8 *addr, int key_idx, int set_tx,
+		       const u8 *addr, int key_idx, int key_flag,
 		       const u8 *seq, size_t seq_len,
 		       const u8 *key, size_t key_len);
 
diff --git a/src/drivers/driver_atheros.c b/src/drivers/driver_atheros.c
index 16c2ae919..e473920a1 100644
--- a/src/drivers/driver_atheros.c
+++ b/src/drivers/driver_atheros.c
@@ -499,7 +499,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,
+		const u8 *addr, int key_idx, int key_flag, const u8 *seq,
 		size_t seq_len, const u8 *key, size_t key_len)
 {
 	struct atheros_driver_data *drv = priv;
@@ -568,7 +568,7 @@  atheros_set_key(const char *ifname, void *priv, enum wpa_alg alg,
 	if (addr == NULL || is_broadcast_ether_addr(addr)) {
 		os_memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN);
 		wk.ik_keyix = key_idx;
-		if (set_tx)
+		if (key_flag & KEY_FLAG_DEFAULT_KEY)
 			wk.ik_flags |= IEEE80211_KEY_DEFAULT;
 	} else {
 		os_memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN);
@@ -580,9 +580,9 @@  atheros_set_key(const char *ifname, void *priv, enum wpa_alg alg,
 	ret = set80211priv(drv, IEEE80211_IOCTL_SETKEY, &wk, sizeof(wk));
 	if (ret < 0) {
 		wpa_printf(MSG_DEBUG, "%s: Failed to set key (addr %s"
-			   " key_idx %d alg %d key_len %lu set_tx %d)",
+			   " key_idx %d alg %d key_len %lu key_flag %d)",
 			   __func__, ether_sprintf(wk.ik_macaddr), key_idx,
-			   alg, (unsigned long) key_len, set_tx);
+			   alg, (unsigned long) key_len, key_flag);
 	}
 
 	return ret;
diff --git a/src/drivers/driver_bsd.c b/src/drivers/driver_bsd.c
index 8621aa0b0..9c6600400 100644
--- a/src/drivers/driver_bsd.c
+++ b/src/drivers/driver_bsd.c
@@ -332,7 +332,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,
+	    const unsigned char *addr, int key_idx, int key_flag, const u8 *seq,
 	    size_t seq_len, const u8 *key, size_t key_len)
 {
 	struct ieee80211req_key wk;
@@ -340,9 +340,9 @@  bsd_set_key(const char *ifname, void *priv, enum wpa_alg alg,
 	struct bsd_driver_data *drv = priv;
 #endif /* IEEE80211_KEY_NOREPLAY */
 
-	wpa_printf(MSG_DEBUG, "%s: alg=%d addr=%p key_idx=%d set_tx=%d "
+	wpa_printf(MSG_DEBUG, "%s: alg=%d addr=%p key_idx=%d key_flag=%d "
 		   "seq_len=%zu key_len=%zu", __func__, alg, addr, key_idx,
-		   set_tx, seq_len, key_len);
+		   key_flag, seq_len, key_len);
 
 	if (alg == WPA_ALG_NONE) {
 #ifndef HOSTAPD
@@ -370,7 +370,7 @@  bsd_set_key(const char *ifname, void *priv, enum wpa_alg alg,
 	}
 
 	wk.ik_flags = IEEE80211_KEY_RECV;
-	if (set_tx)
+	if (key_flag & KEY_FLAG_DEFAULT_KEY)
 		wk.ik_flags |= IEEE80211_KEY_XMIT;
 
 	if (addr == NULL) {
@@ -391,7 +391,7 @@  bsd_set_key(const char *ifname, void *priv, enum wpa_alg alg,
 				key_idx;
 		}
 	}
-	if (wk.ik_keyix != IEEE80211_KEYIX_NONE && set_tx)
+	if (wk.ik_keyix != IEEE80211_KEYIX_NONE && key_flag & KEY_FLAG_DEFAULT_KEY)
 		wk.ik_flags |= IEEE80211_KEY_DEFAULT;
 #ifndef HOSTAPD
 #ifdef IEEE80211_KEY_NOREPLAY
diff --git a/src/drivers/driver_hostap.c b/src/drivers/driver_hostap.c
index 597da335e..002fc1b8a 100644
--- a/src/drivers/driver_hostap.c
+++ b/src/drivers/driver_hostap.c
@@ -390,7 +390,7 @@  static int hostapd_ioctl(void *priv, struct prism2_hostapd_param *param,
 
 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,
+				     int key_idx, int key_flag,
 				     const u8 *seq, size_t seq_len,
 				     const u8 *key, size_t key_len)
 {
@@ -432,7 +432,8 @@  static int wpa_driver_hostap_set_key(const char *ifname, void *priv,
 		os_free(buf);
 		return -1;
 	}
-	param->u.crypt.flags = set_tx ? HOSTAP_CRYPT_FLAG_SET_TX_KEY : 0;
+	param->u.crypt.flags = key_flag & KEY_FLAG_DEFAULT_KEY ?
+			       HOSTAP_CRYPT_FLAG_SET_TX_KEY : 0;
 	param->u.crypt.idx = key_idx;
 	param->u.crypt.key_len = key_len;
 	memcpy((u8 *) (param + 1), key, key_len);
diff --git a/src/drivers/driver_ndis.c b/src/drivers/driver_ndis.c
index 614c4521e..c617ce7c4 100644
--- a/src/drivers/driver_ndis.c
+++ b/src/drivers/driver_ndis.c
@@ -931,7 +931,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,
+				   int pairwise, int key_idx, int key_flag,
 				   const u8 *key, size_t key_len)
 {
 	NDIS_802_11_WEP *wep;
@@ -944,7 +944,7 @@  static int wpa_driver_ndis_add_wep(struct wpa_driver_ndis_data *drv,
 		return -1;
 	wep->Length = len;
 	wep->KeyIndex = key_idx;
-	if (set_tx)
+	if (key_flag & KEY_FLAG_DEFAULT_KEY)
 		wep->KeyIndex |= 1 << 31;
 #if 0 /* Setting bit30 does not seem to work with some NDIS drivers */
 	if (pairwise)
@@ -965,7 +965,7 @@  static int wpa_driver_ndis_add_wep(struct wpa_driver_ndis_data *drv,
 
 static int wpa_driver_ndis_set_key(const char *ifname, void *priv,
 				   enum wpa_alg alg, const u8 *addr,
-				   int key_idx, int set_tx,
+				   int key_idx, int key_flag,
 				   const u8 *seq, size_t seq_len,
 				   const u8 *key, size_t key_len)
 {
@@ -992,7 +992,7 @@  static int wpa_driver_ndis_set_key(const char *ifname, void *priv,
 	}
 
 	if (alg == WPA_ALG_WEP) {
-		return wpa_driver_ndis_add_wep(drv, pairwise, key_idx, set_tx,
+		return wpa_driver_ndis_add_wep(drv, pairwise, key_idx, key_flag,
 					       key, key_len);
 	}
 
@@ -1004,7 +1004,7 @@  static int wpa_driver_ndis_set_key(const char *ifname, void *priv,
 
 	nkey->Length = len;
 	nkey->KeyIndex = key_idx;
-	if (set_tx)
+	if (key_flag & KEY_FLAG_DEFAULT_KEY)
 		nkey->KeyIndex |= 1 << 31;
 	if (pairwise)
 		nkey->KeyIndex |= 1 << 30;
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 771e76696..acbef4a35 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -2925,7 +2925,7 @@  static int nl80211_set_pmk(struct wpa_driver_nl80211_data *drv,
 
 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,
+				      int key_idx, int key_flag,
 				      const u8 *seq, size_t seq_len,
 				      const u8 *key, size_t key_len)
 {
@@ -2941,8 +2941,8 @@  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",
-		   __func__, ifindex, ifname, alg, addr, key_idx, set_tx,
+		   "key_flag=%d seq_len=%lu key_len=%lu",
+		   __func__, ifindex, ifname, alg, addr, key_idx, key_flag,
 		   (unsigned long) seq_len, (unsigned long) key_len);
 #ifdef CONFIG_TDLS
 	if (key_idx == -1) {
@@ -2965,7 +2965,13 @@  static int wpa_driver_nl80211_set_key(const char *ifname, struct i802_bss *bss,
 	    (drv->capa.flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE))
 		return nl80211_set_pmk(drv, key, key_len, addr);
 
-	if (alg == WPA_ALG_NONE) {
+	if (key_flag & KEY_FLAG_TX && !key) {
+		wpa_printf(MSG_DEBUG, "Extended Key ID: Activate keyid=%d "
+			   "for TX to addr=%p", key_idx, addr);
+		msg = nl80211_ifindex_msg(drv, ifindex, 0, NL80211_CMD_SET_KEY);
+		if (!msg)
+			return -ENOBUFS;
+	} else 	if (alg == WPA_ALG_NONE) {
 		msg = nl80211_ifindex_msg(drv, ifindex, 0, NL80211_CMD_DEL_KEY);
 		if (!msg)
 			return -ENOBUFS;
@@ -2994,7 +3000,15 @@  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_RX_ONLY | KEY_FLAG_TX)) {
+			wpa_printf(MSG_DEBUG, "   Extended Key ID action: %d", key_flag);
+			if (nla_put_flag(msg,
+					 key_flag & KEY_FLAG_RX_ONLY ?
+					 NL80211_ATTR_KEY_RXONLY :
+					 NL80211_ATTR_KEY_SETTX))
+				goto fail;
+		} else if (alg != WPA_ALG_WEP && key_idx &&
+			   !(key_flag & KEY_FLAG_DEFAULT_KEY)) {
 			wpa_printf(MSG_DEBUG, "   RSN IBSS RX GTK");
 			if (nla_put_u32(msg, NL80211_ATTR_KEY_TYPE,
 					NL80211_KEYTYPE_GROUP))
@@ -3025,7 +3039,7 @@  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 || !(key_flag & KEY_FLAG_DEFAULT_KEY) || alg == WPA_ALG_NONE || tdls)
 		return ret;
 	if (is_ap_interface(drv->nlmode) && addr &&
 	    !is_broadcast_ether_addr(addr))
@@ -8382,13 +8396,13 @@  nl80211_tdls_disable_channel_switch(void *priv, const u8 *addr)
 
 static int driver_nl80211_set_key(const char *ifname, void *priv,
 				  enum wpa_alg alg, const u8 *addr,
-				  int key_idx, int set_tx,
+				  int key_idx, int key_flag,
 				  const u8 *seq, size_t seq_len,
 				  const u8 *key, size_t key_len)
 {
 	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);
+					  key_flag, seq, seq_len, key, key_len);
 }
 
 
diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
index 7b360d209..d8c73c0dc 100644
--- a/src/drivers/driver_nl80211_capa.c
+++ b/src/drivers/driver_nl80211_capa.c
@@ -416,6 +416,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 e94eda08f..2e7a14765 100644
--- a/src/drivers/driver_openbsd.c
+++ b/src/drivers/driver_openbsd.c
@@ -69,7 +69,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,
+	    const unsigned char *addr, int key_idx, int key_flag, const u8 *seq,
 	    size_t seq_len, const u8 *key, size_t key_len)
 {
 	struct openbsd_driver_data *drv = priv;
diff --git a/src/drivers/driver_privsep.c b/src/drivers/driver_privsep.c
index a3f0837e1..382ad298b 100644
--- a/src/drivers/driver_privsep.c
+++ b/src/drivers/driver_privsep.c
@@ -207,15 +207,15 @@  wpa_driver_privsep_get_scan_results2(void *priv)
 
 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,
+				      int key_idx, int key_flag,
 				      const u8 *seq, size_t seq_len,
 				      const u8 *key, size_t key_len)
 {
 	struct wpa_driver_privsep_data *drv = priv;
 	struct privsep_cmd_set_key cmd;
 
-	wpa_printf(MSG_DEBUG, "%s: priv=%p alg=%d key_idx=%d set_tx=%d",
-		   __func__, priv, alg, key_idx, set_tx);
+	wpa_printf(MSG_DEBUG, "%s: priv=%p alg=%d key_idx=%d key_flag=%d",
+		   __func__, priv, alg, key_idx, key_flag);
 
 	os_memset(&cmd, 0, sizeof(cmd));
 	cmd.alg = alg;
@@ -224,7 +224,7 @@  static int wpa_driver_privsep_set_key(const char *ifname, void *priv,
 	else
 		os_memset(cmd.addr, 0xff, ETH_ALEN);
 	cmd.key_idx = key_idx;
-	cmd.set_tx = set_tx;
+	cmd.set_tx = key_flag & KEY_FLAG_DEFAULT_KEY;
 	if (seq && seq_len > 0 && seq_len < sizeof(cmd.seq)) {
 		os_memcpy(cmd.seq, seq, seq_len);
 		cmd.seq_len = seq_len;
diff --git a/src/drivers/driver_wext.c b/src/drivers/driver_wext.c
index 933b8d986..d37903529 100644
--- a/src/drivers/driver_wext.c
+++ b/src/drivers/driver_wext.c
@@ -1707,7 +1707,7 @@  static int wpa_driver_wext_set_psk(struct wpa_driver_wext_data *drv,
 
 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,
+				       int key_flag, const u8 *seq,
 				       size_t seq_len,
 				       const u8 *key, size_t key_len)
 {
@@ -1736,7 +1736,7 @@  static int wpa_driver_wext_set_key_ext(void *priv, enum wpa_alg alg,
 
 	if (addr == NULL || is_broadcast_ether_addr(addr))
 		ext->ext_flags |= IW_ENCODE_EXT_GROUP_KEY;
-	if (set_tx)
+	if (key_flag & KEY_FLAG_DEFAULT_KEY)
 		ext->ext_flags |= IW_ENCODE_EXT_SET_TX_KEY;
 
 	ext->addr.sa_family = ARPHRD_ETHER;
@@ -1808,7 +1808,8 @@  static int wpa_driver_wext_set_key_ext(void *priv, enum wpa_alg alg,
  * @addr: Address of the peer STA or ff:ff:ff:ff:ff:ff for
  *	broadcast/default keys
  * @key_idx: key index (0..3), usually 0 for unicast keys
- * @set_tx: Configure this key as the default Tx key (only used when
+ * @key_flag: %KEY_FLAG_DEFAULT_KEY (Other flags not supported)
+ *      Configure this key as the default Tx key (only used when
  *	driver does not support separate unicast/individual key
  * @seq: Sequence number/packet number, seq_len octets, the next
  *	packet number to be used for in replay protection; configured
@@ -1827,19 +1828,19 @@  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,
+			    int key_flag, const u8 *seq, size_t seq_len,
 			    const u8 *key, size_t key_len)
 {
 	struct wpa_driver_wext_data *drv = priv;
 	struct iwreq iwr;
 	int ret = 0;
 
-	wpa_printf(MSG_DEBUG, "%s: alg=%d key_idx=%d set_tx=%d seq_len=%lu "
+	wpa_printf(MSG_DEBUG, "%s: alg=%d key_idx=%d key_flag=%d seq_len=%lu "
 		   "key_len=%lu",
-		   __FUNCTION__, alg, key_idx, set_tx,
+		   __FUNCTION__, alg, key_idx, key_flag,
 		   (unsigned long) seq_len, (unsigned long) key_len);
 
-	ret = wpa_driver_wext_set_key_ext(drv, alg, addr, key_idx, set_tx,
+	ret = wpa_driver_wext_set_key_ext(drv, alg, addr, key_idx, key_flag,
 					  seq, seq_len, key, key_len);
 	if (ret == 0)
 		return 0;
@@ -1870,7 +1871,7 @@  int wpa_driver_wext_set_key(const char *ifname, void *priv, enum wpa_alg alg,
 		ret = -1;
 	}
 
-	if (set_tx && alg != WPA_ALG_NONE) {
+	if (key_flag & KEY_FLAG_DEFAULT_KEY && alg != WPA_ALG_NONE) {
 		os_memset(&iwr, 0, sizeof(iwr));
 		os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
 		iwr.u.encoding.flags = key_idx + 1;
@@ -1879,7 +1880,7 @@  int wpa_driver_wext_set_key(const char *ifname, void *priv, enum wpa_alg alg,
 		iwr.u.encoding.length = 0;
 		if (ioctl(drv->ioctl_sock, SIOCSIWENCODE, &iwr) < 0) {
 			wpa_printf(MSG_ERROR,
-				   "ioctl[SIOCSIWENCODE] (set_tx): %s",
+				   "ioctl[SIOCSIWENCODE] (DEFAULT_KEY): %s",
 				   strerror(errno));
 			ret = -1;
 		}
diff --git a/src/drivers/nl80211_copy.h b/src/drivers/nl80211_copy.h
index 1766a12b2..d6c7fa72f 100644
--- a/src/drivers/nl80211_copy.h
+++ b/src/drivers/nl80211_copy.h
@@ -1033,6 +1033,9 @@ 
  *	%NL80211_ATTR_CHANNEL_WIDTH,%NL80211_ATTR_NSS attributes with its
  *	address(specified in %NL80211_ATTR_MAC).
  *
+ * @NL80211_CMD_GET_FTM_RESPONDER_STATS: Retrieve FTM responder statistics, in
+ *	the %NL80211_ATTR_FTM_RESPONDER_STATS attribute.
+ *
  * @NL80211_CMD_MAX: highest used command number
  * @__NL80211_CMD_AFTER_LAST: internal use
  */
@@ -1245,6 +1248,8 @@  enum nl80211_commands {
 
 	NL80211_CMD_CONTROL_PORT_FRAME,
 
+	NL80211_CMD_GET_FTM_RESPONDER_STATS,
+
 	/* add new commands above here */
 
 	/* used to define NL80211_CMD_MAX below */
@@ -2241,6 +2246,22 @@  enum nl80211_commands {
  *	association request when used with NL80211_CMD_NEW_STATION). Can be set
  *	only if %NL80211_STA_FLAG_WME is set.
  *
+ * @NL80211_ATTR_FTM_RESPONDER: nested attribute which user-space can include
+ *	in %NL80211_CMD_START_AP or %NL80211_CMD_SET_BEACON for fine timing
+ *	measurement (FTM) responder functionality and containing parameters as
+ *	possible, see &enum nl80211_ftm_responder_attr
+ *
+ * @NL80211_ATTR_FTM_RESPONDER_STATS: Nested attribute with FTM responder
+ *	statistics, see &enum nl80211_ftm_responder_stats.
+ *
+ * @NL80211_ATTR_KEY_RXONLY: Flag attribute to request RX key install only for
+ *      a pairwise key. Only supported for keyid's 0 and 1 when driver is
+ *      supporting Extended Key ID.
+ *
+ * @NL80211_ATTR_KEY_SETTX: Flag attribute to switch TX to a specified keyid.
+ *      Only supported for keyid's 0 and 1 when driver is supporting Extended
+ *      Key ID.
+ *
  * @NUM_NL80211_ATTR: total number of nl80211_attrs available
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
@@ -2682,6 +2703,13 @@  enum nl80211_attrs {
 
 	NL80211_ATTR_HE_CAPABILITY,
 
+	NL80211_ATTR_FTM_RESPONDER,
+
+	NL80211_ATTR_FTM_RESPONDER_STATS,
+
+	NL80211_ATTR_KEY_RXONLY,
+	NL80211_ATTR_KEY_SETTX,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,
@@ -3051,6 +3079,12 @@  enum nl80211_sta_bss_param {
  * @NL80211_STA_INFO_PAD: attribute used for padding for 64-bit alignment
  * @NL80211_STA_INFO_ACK_SIGNAL: signal strength of the last ACK frame(u8, dBm)
  * @NL80211_STA_INFO_ACK_SIGNAL_AVG: avg signal strength of ACK frames (s8, dBm)
+ * @NL80211_STA_INFO_RX_MPDUS: total number of received packets (MPDUs)
+ *	(u32, from this station)
+ * @NL80211_STA_INFO_FCS_ERROR_COUNT: total number of packets (MPDUs) received
+ *	with an FCS error (u32, from this station). This count may not include
+ *	some packets with an FCS error due to TA corruption. Hence this counter
+ *	might not be fully accurate.
  * @__NL80211_STA_INFO_AFTER_LAST: internal
  * @NL80211_STA_INFO_MAX: highest possible station info attribute
  */
@@ -3091,6 +3125,8 @@  enum nl80211_sta_info {
 	NL80211_STA_INFO_PAD,
 	NL80211_STA_INFO_ACK_SIGNAL,
 	NL80211_STA_INFO_ACK_SIGNAL_AVG,
+	NL80211_STA_INFO_RX_MPDUS,
+	NL80211_STA_INFO_FCS_ERROR_COUNT,
 
 	/* keep last */
 	__NL80211_STA_INFO_AFTER_LAST,
@@ -4031,6 +4067,22 @@  enum nl80211_channel_type {
 	NL80211_CHAN_HT40PLUS
 };
 
+/**
+ * enum key_params_flag - additional key flag for drivers
+ *
+ * Actions other than @NL80211_KEY_DEFAULT_RX_TX are only required from drivers
+ * supporting Extended Key ID for pairwise keys using keyid 0 or 1.
+ *
+ * @NL80211_KEY_DEFAULT_RX_TX: key can be immediately used for Rx and Tx
+ * @NL80211_KEY_RX_ONLY: key must be installed for Rx only
+ * @NL80211_KEY_SET_TX: switch Tx for sta to specified keyid
+ */
+enum key_params_flag {
+	NL80211_KEY_DEFAULT_RX_TX,
+	NL80211_KEY_RX_ONLY,
+	NL80211_KEY_SET_TX
+};
+
 /**
  * enum nl80211_chan_width - channel width definitions
  *
@@ -4274,6 +4326,10 @@  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_RXONLY: Flag attribute to request RX key install only for
+ *      a pairwise key.
+ * @NL80211_KEY_SETTX: Flag attribute to switch TX to a selected key.
+ *
  * @__NL80211_KEY_AFTER_LAST: internal
  * @NL80211_KEY_MAX: highest key attribute
  */
@@ -4287,6 +4343,8 @@  enum nl80211_key_attributes {
 	NL80211_KEY_DEFAULT_MGMT,
 	NL80211_KEY_TYPE,
 	NL80211_KEY_DEFAULT_TYPES,
+	NL80211_KEY_RXONLY,
+	NL80211_KEY_SETTX,
 
 	/* keep last */
 	__NL80211_KEY_AFTER_LAST,
@@ -5225,6 +5283,14 @@  enum nl80211_feature_flags {
  * @NL80211_EXT_FEATURE_SCAN_MIN_PREQ_CONTENT: Driver/device can omit all data
  *	except for supported rates from the probe request content if requested
  *	by the %NL80211_SCAN_FLAG_MIN_PREQ_CONTENT flag.
+ * @NL80211_EXT_FEATURE_CAN_REPLACE_PTK0: Driver/device confirm that they are
+ *      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_ENABLE_FTM_RESPONDER: Driver supports enabling fine
+ *	timing measurement responder role.
+ * @NL80211_EXT_FEATURE_EXT_KEY_ID: Driver supports "Extended Key ID for
+ *      Individually Addressed Frames" from IEEE802.11-2016.
  *
  * @NUM_NL80211_EXT_FEATURES: number of extended features.
  * @MAX_NL80211_EXT_FEATURES: highest extended feature index.
@@ -5263,6 +5329,9 @@  enum nl80211_ext_feature_index {
 	NL80211_EXT_FEATURE_TXQS,
 	NL80211_EXT_FEATURE_SCAN_RANDOM_SN,
 	NL80211_EXT_FEATURE_SCAN_MIN_PREQ_CONTENT,
+	NL80211_EXT_FEATURE_CAN_REPLACE_PTK0,
+	NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER,
+	NL80211_EXT_FEATURE_EXT_KEY_ID,
 
 	/* add new features before the definition below */
 	NUM_NL80211_EXT_FEATURES,
@@ -5802,4 +5871,74 @@  enum nl80211_external_auth_action {
 	NL80211_EXTERNAL_AUTH_ABORT,
 };
 
+/**
+ * enum nl80211_ftm_responder_attributes - fine timing measurement
+ *	responder attributes
+ * @__NL80211_FTM_RESP_ATTR_INVALID: Invalid
+ * @NL80211_FTM_RESP_ATTR_ENABLED: FTM responder is enabled
+ * @NL80211_FTM_RESP_ATTR_LCI: The content of Measurement Report Element
+ *	(9.4.2.22 in 802.11-2016) with type 8 - LCI (9.4.2.22.10)
+ * @NL80211_FTM_RESP_ATTR_CIVIC: The content of Measurement Report Element
+ *	(9.4.2.22 in 802.11-2016) with type 11 - Civic (Section 9.4.2.22.13)
+ * @__NL80211_FTM_RESP_ATTR_LAST: Internal
+ * @NL80211_FTM_RESP_ATTR_MAX: highest FTM responder attribute.
+ */
+enum nl80211_ftm_responder_attributes {
+	__NL80211_FTM_RESP_ATTR_INVALID,
+
+	NL80211_FTM_RESP_ATTR_ENABLED,
+	NL80211_FTM_RESP_ATTR_LCI,
+	NL80211_FTM_RESP_ATTR_CIVICLOC,
+
+	/* keep last */
+	__NL80211_FTM_RESP_ATTR_LAST,
+	NL80211_FTM_RESP_ATTR_MAX = __NL80211_FTM_RESP_ATTR_LAST - 1,
+};
+
+/*
+ * enum nl80211_ftm_responder_stats - FTM responder statistics
+ *
+ * These attribute types are used with %NL80211_ATTR_FTM_RESPONDER_STATS
+ * when getting FTM responder statistics.
+ *
+ * @__NL80211_FTM_STATS_INVALID: attribute number 0 is reserved
+ * @NL80211_FTM_STATS_SUCCESS_NUM: number of FTM sessions in which all frames
+ *	were ssfully answered (u32)
+ * @NL80211_FTM_STATS_PARTIAL_NUM: number of FTM sessions in which part of the
+ *	frames were successfully answered (u32)
+ * @NL80211_FTM_STATS_FAILED_NUM: number of failed FTM sessions (u32)
+ * @NL80211_FTM_STATS_ASAP_NUM: number of ASAP sessions (u32)
+ * @NL80211_FTM_STATS_NON_ASAP_NUM: number of non-ASAP sessions (u32)
+ * @NL80211_FTM_STATS_TOTAL_DURATION_MSEC: total sessions durations - gives an
+ *	indication of how much time the responder was busy (u64, msec)
+ * @NL80211_FTM_STATS_UNKNOWN_TRIGGERS_NUM: number of unknown FTM triggers -
+ *	triggers from initiators that didn't finish successfully the negotiation
+ *	phase with the responder (u32)
+ * @NL80211_FTM_STATS_RESCHEDULE_REQUESTS_NUM: number of FTM reschedule requests
+ *	- initiator asks for a new scheduling although it already has scheduled
+ *	FTM slot (u32)
+ * @NL80211_FTM_STATS_OUT_OF_WINDOW_TRIGGERS_NUM: number of FTM triggers out of
+ *	scheduled window (u32)
+ * @NL80211_FTM_STATS_PAD: used for padding, ignore
+ * @__NL80211_TXQ_ATTR_AFTER_LAST: Internal
+ * @NL80211_FTM_STATS_MAX: highest possible FTM responder stats attribute
+ */
+enum nl80211_ftm_responder_stats {
+	__NL80211_FTM_STATS_INVALID,
+	NL80211_FTM_STATS_SUCCESS_NUM,
+	NL80211_FTM_STATS_PARTIAL_NUM,
+	NL80211_FTM_STATS_FAILED_NUM,
+	NL80211_FTM_STATS_ASAP_NUM,
+	NL80211_FTM_STATS_NON_ASAP_NUM,
+	NL80211_FTM_STATS_TOTAL_DURATION_MSEC,
+	NL80211_FTM_STATS_UNKNOWN_TRIGGERS_NUM,
+	NL80211_FTM_STATS_RESCHEDULE_REQUESTS_NUM,
+	NL80211_FTM_STATS_OUT_OF_WINDOW_TRIGGERS_NUM,
+	NL80211_FTM_STATS_PAD,
+
+	/* keep last */
+	__NL80211_FTM_STATS_AFTER_LAST,
+	NL80211_FTM_STATS_MAX = __NL80211_FTM_STATS_AFTER_LAST - 1
+};
+
 #endif /* __LINUX_NL80211_H */