[v5,07/16] nl80211: Switch to the new key_type API & cleanup
diff mbox series

Message ID 20190825163521.22625-8-alexander@wetzel-home.de
State Superseded
Headers show
Series
  • Support seamless PTK rekeys with Extended Key ID
Related show

Commit Message

Alexander Wetzel Aug. 25, 2019, 4:35 p.m. UTC
Installing WEP and broadcast keys requires an additional netlink call
(NL80211_CMD_SET_KEY) after the key has been installed.

wpa_driver_nl80211_set_key() had a overly complex and not always
correct method to detect that, heavily depending on set_tx.
But nl80211 can deduce the need to call NL80211_CMD_SET_KEY without
referring to the unpredictable set "boolean" set_tx.
Therefore stop using set_tx and throw out workarounds linked to it.

This also stops pointless NL80211_CMD_SET_KEY calls when installing
unicast keys in wpa_supplicant.

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

This simply is too big to put into the generic patch migrating the
drivers to key_type. Nl80211 is the driver supporting the most features
and also using the strangest hacks...

This patch is not only migrating to key_type, it's a general overhaul of
the key install logic.
The new logic works fine for all test cases and to my understanding all
dropped code pieces could not have had any function.  (Verified against
the kernel code.)

 src/drivers/driver_nl80211.c | 56 +++++++++++++++---------------------
 1 file changed, 23 insertions(+), 33 deletions(-)

Patch
diff mbox series

diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 290da9d5e..1e4ef80bc 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -3018,8 +3018,9 @@  static int wpa_driver_nl80211_set_key(const char *ifname, struct i802_bss *bss,
 	int ifindex;
 	struct nl_msg *msg;
 	struct nl_msg *key_msg;
+	struct nlattr *types;
+	int need_set_key = 0;
 	int ret;
-	int tdls = 0;
 
 	/* Ignore for P2P Device */
 	if (drv->nlmode == NL80211_IFTYPE_P2P_DEVICE)
@@ -3027,13 +3028,12 @@  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_type=%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_type);
 #ifdef CONFIG_TDLS
 	if (key_idx == -1) {
 		key_idx = 0;
-		tdls = 1;
 	}
 #endif /* CONFIG_TDLS */
 
@@ -3085,22 +3085,18 @@  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 (alg != WPA_ALG_WEP && key_type != KEY_TYPE_PAIRWISE) {
 			wpa_printf(MSG_DEBUG, "   RSN IBSS RX GTK");
 			if (nla_put_u32(key_msg, NL80211_KEY_TYPE,
 					NL80211_KEYTYPE_GROUP))
 				goto fail;
 		}
-	} else if (addr && is_broadcast_ether_addr(addr)) {
-		struct nlattr *types;
-
-		wpa_printf(MSG_DEBUG, "   broadcast key");
-
-		types = nla_nest_start(key_msg, NL80211_KEY_DEFAULT_TYPES);
-		if (!types ||
-		    nla_put_flag(key_msg, NL80211_KEY_DEFAULT_TYPE_MULTICAST))
-			goto fail;
-		nla_nest_end(key_msg, types);
+	} else if (alg != WPA_ALG_NONE) {
+		/* Default (WEP, GTK or IGTK) key */
+		if (alg != WPA_ALG_WEP || key_type == KEY_TYPE_DEFAULT) {
+			wpa_printf(MSG_DEBUG, "   require SET_KEY");
+			need_set_key = 1;
+		}
 	}
 	if (nla_put_u8(key_msg, NL80211_KEY_IDX, key_idx) ||
 	    nla_put_nested(msg, NL80211_ATTR_KEY, key_msg))
@@ -3114,13 +3110,10 @@  static int wpa_driver_nl80211_set_key(const char *ifname, struct i802_bss *bss,
 			   ret, strerror(-ret));
 
 	/*
-	 * If we failed or don't need to set the default TX key (below),
+	 * If we failed or don't need to set the key as default (below),
 	 * we're done here.
 	 */
-	if (ret || !set_tx || alg == WPA_ALG_NONE || tdls)
-		return ret;
-	if (is_ap_interface(drv->nlmode) && addr &&
-	    !is_broadcast_ether_addr(addr))
+	if (ret || !need_set_key)
 		return ret;
 
 	key_msg = nlmsg_alloc();
@@ -3140,29 +3133,26 @@  static int wpa_driver_nl80211_set_key(const char *ifname, struct i802_bss *bss,
 				   NL80211_KEY_DEFAULT))
 		goto fail;
 	if (addr && is_broadcast_ether_addr(addr)) {
-		struct nlattr *types;
-
+		wpa_printf(MSG_DEBUG, "   broadcast key");
 		types = nla_nest_start(key_msg, NL80211_KEY_DEFAULT_TYPES);
 		if (!types ||
 		    nla_put_flag(key_msg, NL80211_KEY_DEFAULT_TYPE_MULTICAST))
 			goto fail;
 		nla_nest_end(key_msg, types);
-	} else if (addr) {
-		struct nlattr *types;
-
-		types = nla_nest_start(key_msg, NL80211_KEY_DEFAULT_TYPES);
-		if (!types ||
-		    nla_put_flag(key_msg, NL80211_KEY_DEFAULT_TYPE_UNICAST))
-			goto fail;
-		nla_nest_end(key_msg, types);
+	} else if (!addr) {
+		wpa_printf(MSG_DEBUG, "   WEP key");
+	} else {
+		/* need_set_key must only be set for
+		 * zero or broadcast addresses
+		 */
+		wpa_printf(MSG_ERROR,
+			   "Unicast key when not expecting one, abort!");
+		goto fail;
 	}
 
 	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;
 	if (ret)
 		wpa_printf(MSG_DEBUG, "nl80211: set_key default failed; "
 			   "err=%d %s)", ret, strerror(-ret));