diff mbox series

[v3,01/17] nl80211: Migrate to current netlink key message format

Message ID 20190817211435.158335-2-alexander@wetzel-home.de
State Superseded
Headers show
Series Support seamless PTK rekeys with Extended Key ID | expand

Commit Message

Alexander Wetzel Aug. 17, 2019, 9:14 p.m. UTC
Linux 2.6.32 (December 2009) introduced an alternate netlink message
format for setting and querying key information, deprecating the older
one.

To allow hostapd/wpa_supplicant to use new features only provided via
the new format this patch migrates all key netlink messages for key
installs and queries to the new format.
Since some parts of the nl80211 driver do already use the new format
this should not change the minimal kernel requirement and only unify the
netlink API usage.

The following netlink attributes have been dropped from all key install
and query functions:

  NL80211_ATTR_KEY_DATA
  NL80211_ATTR_KEY_TYPE
  NL80211_ATTR_KEY_SEQ
  NL80211_ATTR_KEY_IDX
  NL80211_ATTR_KEY_CIPHER
  NL80211_ATTR_KEY_DEFAULT
  NL80211_ATTR_KEY_DEFAULT_MGMT
  NL80211_ATTR_KEY_DEFAULT_TYPES

And replaced by the following attributes nested in NL80211_ATTR_KEY:

  NL80211_KEY_DATA
  NL80211_KEY_TYPE
  NL80211_KEY_SEQ
  NL80211_KEY_IDX
  NL80211_KEY_CIPHER
  NL80211_KEY_DEFAULT
  NL80211_KEY_DEFAULT_MGMT
  NL80211_KEY_DEFAULT_TYPES

But when detecting and reporting michael mic_failures the kernel even
current kernels are still using:
  NL80211_ATTR_KEY_TYPE
  NL80211_ATTR_KEY_SEQ
  NL80211_ATTR_KEY_IDX

Therefore we still have to use them there when processing michael
mic_failures events.

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

There is not much to add to the commit log, most of it is straight
forward. But I tried to keep the existing logic and therefore start an
additional key netlink message to be still able to fill in the
information with the existing logic and not the more usual
nla_nest_start().

 src/drivers/driver_nl80211.c | 88 ++++++++++++++++++++++++------------
 1 file changed, 58 insertions(+), 30 deletions(-)

Comments

Alexander Wetzel Aug. 22, 2019, 7:51 p.m. UTC | #1
Am 17.08.19 um 23:14 schrieb Alexander Wetzel:
> @@ -6194,9 +6217,11 @@ static int get_key_handler(struct nl_msg *msg, void *arg)
>   	 * the kernel starts sending key notifications.
>   	 */
>   
> -	if (tb[NL80211_ATTR_KEY_SEQ])
> -		memcpy(arg, nla_data(tb[NL80211_ATTR_KEY_SEQ]),
> -		       min_int(nla_len(tb[NL80211_ATTR_KEY_SEQ]), 6));
> +	if (tb[NL80211_ATTR_KEY] &&
> +	    !nla_parse_nested(attrs, NL80211_KEY_MAX, tb[NL80211_ATTR_KEY],
> +			      key_policy))
> +		memcpy(arg, nla_data(attrs[NL80211_KEY_SEQ]),
> +		       min_int(nla_len(attrs[NL80211_KEY_SEQ]), 16));
>   	nl80211_nlmsg_clear(msg);
>   	return NL_SKIP;
>   }
> @@ -6208,16 +6233,19 @@ static int i802_get_seqnum(const char *iface, void *priv, const u8 *addr,
>   	struct i802_bss *bss = priv;
>   	struct wpa_driver_nl80211_data *drv = bss->drv;
>   	struct nl_msg *msg;
> +	struct nlattr *key_attr;
>   
>   	msg = nl80211_ifindex_msg(drv, if_nametoindex(iface), 0,
>   				  NL80211_CMD_GET_KEY);
>   	if (!msg ||
>   	    (addr && nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr)) ||
> -	    nla_put_u8(msg, NL80211_ATTR_KEY_IDX, idx)) {
> +	    (key_attr = nla_nest_start(msg, NL80211_ATTR_KEY)) ||
> +	    nla_put_u8(msg, NL80211_KEY_IDX, idx)) {
>   		nlmsg_free(msg);
>   		return -ENOBUFS;
>   	}
>   
> +	nla_nest_end(msg, key_attr);
>   	memset(seq, 0, 6);
>   
>   	return send_and_recv_msgs(drv, msg, get_key_handler, seq);

That part of the patch is wrong: The linux kernel is still only using 
the old netlink format here.

Guess it's now high time to send out V4...

Alexander
Johannes Berg Aug. 22, 2019, 7:53 p.m. UTC | #2
On Thu, 2019-08-22 at 21:51 +0200, Alexander Wetzel wrote:
> 
> Guess it's now high time to send out V4...

I think you can drop the workarounds - the patch you sent to fix the
things in nl80211 landed in Linus's tree and I CC'ed them to stable, so
IMHO we don't need to worry about that now. It's unlikely that anyone
who's picking up 5.2.9 now wouldn't upgrade to 5.2.10 relatively
quickly.

johannes
Johannes Berg Aug. 22, 2019, 7:57 p.m. UTC | #3
On Thu, 2019-08-22 at 21:53 +0200, Johannes Berg wrote:
> On Thu, 2019-08-22 at 21:51 +0200, Alexander Wetzel wrote:
> > Guess it's now high time to send out V4...
> 
> I think you can drop the workarounds - the patch you sent to fix the
> things in nl80211 landed in Linus's tree

Oops spoke too soon - only in net.git, but will be going further soon I
expect.

johannes
diff mbox series

Patch

diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 7b31b52c7..f6035a17c 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -3015,7 +3015,8 @@  static int wpa_driver_nl80211_set_key(const char *ifname, struct i802_bss *bss,
 {
 	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;
 
@@ -3049,26 +3050,31 @@  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);
 
+	key_msg = nlmsg_alloc();
+	if (!key_msg)
+		return -ENOBUFS;
+
 	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 (nla_put(key_msg, NL80211_KEY_SEQ, seq_len, seq))
 			goto fail;
 		wpa_hexdump(MSG_DEBUG, "nl80211: KEY_SEQ", seq, seq_len);
 	}
@@ -3080,7 +3086,7 @@  static int wpa_driver_nl80211_set_key(const char *ifname, struct i802_bss *bss,
 
 		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;
 		}
@@ -3089,13 +3095,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);
@@ -3115,34 +3122,43 @@  static int wpa_driver_nl80211_set_key(const char *ifname, struct i802_bss *bss,
 	    !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;
@@ -3154,6 +3170,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;
 }
 
@@ -6183,7 +6202,11 @@  static inline int min_int(int a, int b)
 static int get_key_handler(struct nl_msg *msg, void *arg)
 {
 	struct nlattr *tb[NL80211_ATTR_MAX + 1];
+	struct nlattr *attrs[NL80211_KEY_MAX + 1];
 	struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+	static struct nla_policy key_policy[NL80211_KEY_MAX + 1] = {
+		[NL80211_KEY_SEQ] = { .type = NLA_BINARY },
+	};
 
 	nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
 		  genlmsg_attrlen(gnlh, 0), NULL);
@@ -6194,9 +6217,11 @@  static int get_key_handler(struct nl_msg *msg, void *arg)
 	 * the kernel starts sending key notifications.
 	 */
 
-	if (tb[NL80211_ATTR_KEY_SEQ])
-		memcpy(arg, nla_data(tb[NL80211_ATTR_KEY_SEQ]),
-		       min_int(nla_len(tb[NL80211_ATTR_KEY_SEQ]), 6));
+	if (tb[NL80211_ATTR_KEY] &&
+	    !nla_parse_nested(attrs, NL80211_KEY_MAX, tb[NL80211_ATTR_KEY],
+			      key_policy))
+		memcpy(arg, nla_data(attrs[NL80211_KEY_SEQ]),
+		       min_int(nla_len(attrs[NL80211_KEY_SEQ]), 16));
 	nl80211_nlmsg_clear(msg);
 	return NL_SKIP;
 }
@@ -6208,16 +6233,19 @@  static int i802_get_seqnum(const char *iface, void *priv, const u8 *addr,
 	struct i802_bss *bss = priv;
 	struct wpa_driver_nl80211_data *drv = bss->drv;
 	struct nl_msg *msg;
+	struct nlattr *key_attr;
 
 	msg = nl80211_ifindex_msg(drv, if_nametoindex(iface), 0,
 				  NL80211_CMD_GET_KEY);
 	if (!msg ||
 	    (addr && nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr)) ||
-	    nla_put_u8(msg, NL80211_ATTR_KEY_IDX, idx)) {
+	    (key_attr = nla_nest_start(msg, NL80211_ATTR_KEY)) ||
+	    nla_put_u8(msg, NL80211_KEY_IDX, idx)) {
 		nlmsg_free(msg);
 		return -ENOBUFS;
 	}
 
+	nla_nest_end(msg, key_attr);
 	memset(seq, 0, 6);
 
 	return send_and_recv_msgs(drv, msg, get_key_handler, seq);