diff mbox series

Extend set_key() parameters in struct to all users

Message ID 20200109230459.199609-1-alexander@wetzel-home.de
State Deferred
Headers show
Series Extend set_key() parameters in struct to all users | expand

Commit Message

Alexander Wetzel Jan. 9, 2020, 11:04 p.m. UTC
Extend the set_key() parameters struct beyond only the driver API.
This makes it very trivial to add/use new parameters for set_key()
nearly anywhere in the code.

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

This is the "extended" version of converting set_key() funktions to a
parameter struct. Instead of translating the new params to the old
function parameter names I switched more or less everything to params.
This is of course changing quite some code but using only pretty simple
transformations. It has some drive-by fixes and unifications:
 - we zero the ram for structures in three or for different ways and
   when I added "my" ram zero around one existing I unified these.

 - I added a few loops, which are much more attractive with the new layout.

 - And I think you forgot passing through the key_flag in the privsep
   driver

Normally I would now split that into three or four patches and cross
check that all set_key calls in all tests are still called with the same
arguments. Sounds like you are leaning to not apply this, so I just send
you what I have at the moment. I can confirm that I do not have new failed
tests with that patch. (Not sure if you like my rename of the driver
struct, but since I added a very similar struct for the cases where we
have similar but different parameters these two looked too similar with
the original name...)

Alexander

 hostapd/ctrl_iface.c            | 149 +++++++++++++++++++-------------
 src/ap/ap_drv_ops.c             |  26 +-----
 src/ap/ap_drv_ops.h             |   8 +-
 src/ap/hostapd.c                |  67 +++++++++-----
 src/ap/ieee802_11.c             |  28 ++++--
 src/ap/ieee802_1x.c             |  55 ++++++++----
 src/ap/wpa_auth.c               |  78 ++++++++++-------
 src/ap/wpa_auth.h               |   5 +-
 src/ap/wpa_auth_ft.c            |  24 ++---
 src/ap/wpa_auth_glue.c          |  80 +++++++++--------
 src/common/privsep_commands.h   |   1 +
 src/drivers/driver.h            |  18 +++-
 src/drivers/driver_atheros.c    |  34 ++++----
 src/drivers/driver_bsd.c        |   2 +-
 src/drivers/driver_hostap.c     |  19 ++--
 src/drivers/driver_ndis.c       |  57 ++++++------
 src/drivers/driver_nl80211.c    |   6 +-
 src/drivers/driver_openbsd.c    |   6 +-
 src/drivers/driver_privsep.c    |  38 ++++----
 src/drivers/driver_wext.c       |  37 ++++----
 src/rsn_supp/tdls.c             |  27 ++++--
 src/rsn_supp/wpa.c              | 143 ++++++++++++++++++------------
 src/rsn_supp/wpa.h              |   8 +-
 src/rsn_supp/wpa_ft.c           |  92 ++++++++++++--------
 src/rsn_supp/wpa_i.h            |  10 +--
 wpa_supplicant/ctrl_iface.c     |  49 ++++++-----
 wpa_supplicant/driver_i.h       |  31 ++-----
 wpa_supplicant/ibss_rsn.c       |  72 ++++++++-------
 wpa_supplicant/mesh_mpm.c       |  60 ++++++++-----
 wpa_supplicant/mesh_rsn.c       |  63 +++++++++-----
 wpa_supplicant/wpa_priv.c       |   3 +-
 wpa_supplicant/wpa_supplicant.c |  74 ++++++++++------
 wpa_supplicant/wpas_glue.c      |  82 +++++++++++-------
 33 files changed, 829 insertions(+), 623 deletions(-)

Comments

Jouni Malinen March 1, 2020, 7:50 p.m. UTC | #1
On Fri, Jan 10, 2020 at 12:04:59AM +0100, Alexander Wetzel wrote:
> Extend the set_key() parameters struct beyond only the driver API.
> This makes it very trivial to add/use new parameters for set_key()
> nearly anywhere in the code.

> This is the "extended" version of converting set_key() funktions to a
> parameter struct. Instead of translating the new params to the old
> function parameter names I switched more or less everything to params.
> This is of course changing quite some code but using only pretty simple
> transformations. It has some drive-by fixes and unifications:

This does not look like a change that would make it easier to read the
code or maintain this, so unless there is a clear benefit that I've
missed, I think I'd rather not apply most of these changes.

>  - And I think you forgot passing through the key_flag in the privsep
>    driver

However, this is clearly something that should be done. I applied these
changes. Thanks.
diff mbox series

Patch

diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
index 5eef75bf7..11a4140cd 100644
--- a/hostapd/ctrl_iface.c
+++ b/hostapd/ctrl_iface.c
@@ -2135,38 +2135,40 @@  static int hostapd_ctrl_get_fail(struct hostapd_data *hapd,
 static int hostapd_ctrl_reset_pn(struct hostapd_data *hapd, const char *cmd)
 {
 	struct sta_info *sta;
+	struct driver_set_key_params params;
 	u8 addr[ETH_ALEN];
 	u8 zero[WPA_TK_MAX_LEN];
 
+	os_memset(&params, 0, sizeof(params));
 	os_memset(zero, 0, sizeof(zero));
 
 	if (hwaddr_aton(cmd, addr))
 		return -1;
 
+	params.ifname = hapd->conf->iface;
+	params.set_tx = 1;
+
 	if (is_broadcast_ether_addr(addr) && os_strstr(cmd, "IGTK")) {
 		if (hapd->last_igtk_alg == WPA_ALG_NONE)
 			return -1;
 
 		wpa_printf(MSG_INFO, "TESTING: Reset IPN for IGTK");
 
+		params.addr = broadcast_ether_addr;
+		params.alg = hapd->last_igtk_alg;
+		params.key_idx = hapd->last_igtk_key_idx;
+		params.key_len = hapd->last_igtk_len;
+		params.key_flag = KEY_FLAG_GROUP_TX_DEFAULT;
+
 		/* First, use a zero key to avoid any possible duplicate key
 		 * avoidance in the driver. */
-		if (hostapd_drv_set_key(hapd->conf->iface, hapd,
-					hapd->last_igtk_alg,
-					broadcast_ether_addr,
-					hapd->last_igtk_key_idx, 0, 1, NULL, 0,
-					zero, hapd->last_igtk_len,
-					KEY_FLAG_GROUP_TX_DEFAULT) < 0)
+		params.key = zero;
+		if (hostapd_drv_set_key(hapd, &params) < 0)
 			return -1;
 
 		/* Set the previously configured key to reset its TSC */
-		return hostapd_drv_set_key(hapd->conf->iface, hapd,
-					   hapd->last_igtk_alg,
-					   broadcast_ether_addr,
-					   hapd->last_igtk_key_idx, 0, 1, NULL,
-					   0, hapd->last_igtk,
-					   hapd->last_igtk_len,
-					   KEY_FLAG_GROUP_TX_DEFAULT);
+		params.key = hapd->last_igtk;
+		return hostapd_drv_set_key(hapd, &params);
 	}
 
 	if (is_broadcast_ether_addr(addr)) {
@@ -2175,24 +2177,21 @@  static int hostapd_ctrl_reset_pn(struct hostapd_data *hapd, const char *cmd)
 
 		wpa_printf(MSG_INFO, "TESTING: Reset PN for GTK");
 
+		params.addr = broadcast_ether_addr;
+		params.alg = hapd->last_gtk_alg;
+		params.key_idx = hapd->last_gtk_key_idx;
+		params.key_len = hapd->last_gtk_len;
+		params.key_flag = KEY_FLAG_GROUP_TX_DEFAULT;
+
 		/* First, use a zero key to avoid any possible duplicate key
 		 * avoidance in the driver. */
-		if (hostapd_drv_set_key(hapd->conf->iface, hapd,
-					hapd->last_gtk_alg,
-					broadcast_ether_addr,
-					hapd->last_gtk_key_idx, 0, 1, NULL, 0,
-					zero, hapd->last_gtk_len,
-					KEY_FLAG_GROUP_TX_DEFAULT) < 0)
+		params.key = zero;
+		if (hostapd_drv_set_key(hapd, &params) < 0)
 			return -1;
 
 		/* Set the previously configured key to reset its TSC */
-		return hostapd_drv_set_key(hapd->conf->iface, hapd,
-					   hapd->last_gtk_alg,
-					   broadcast_ether_addr,
-					   hapd->last_gtk_key_idx, 0, 1, NULL,
-					   0, hapd->last_gtk,
-					   hapd->last_gtk_len,
-					   KEY_FLAG_GROUP_TX_DEFAULT);
+		params.key = hapd->last_gtk;
+		return hostapd_drv_set_key(hapd, &params);
 	}
 
 	sta = ap_get_sta(hapd, addr);
@@ -2205,51 +2204,54 @@  static int hostapd_ctrl_reset_pn(struct hostapd_data *hapd, const char *cmd)
 	wpa_printf(MSG_INFO, "TESTING: Reset PN for " MACSTR,
 		   MAC2STR(sta->addr));
 
+	params.addr = sta->addr;
+	params.alg = sta->last_tk_alg;
+	params.key_idx = sta->last_tk_key_idx;
+	params.key_len = sta->last_tk_len;
+	params.key_flag = KEY_FLAG_PAIRWISE_RX_TX;
+
 	/* First, use a zero key to avoid any possible duplicate key avoidance
 	 * in the driver. */
-	if (hostapd_drv_set_key(hapd->conf->iface, hapd, sta->last_tk_alg,
-				sta->addr, sta->last_tk_key_idx, 0, 1, NULL, 0,
-				zero, sta->last_tk_len,
-				KEY_FLAG_PAIRWISE_RX_TX) < 0)
+	params.key = zero;
+	if (hostapd_drv_set_key(hapd, &params) < 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, 0, 1, NULL,
-				   0, sta->last_tk, sta->last_tk_len,
-				   KEY_FLAG_PAIRWISE_RX_TX);
+	params.key = sta->last_tk;
+	return hostapd_drv_set_key(hapd, &params);
 }
 
 
 static int hostapd_ctrl_set_key(struct hostapd_data *hapd, const char *cmd)
 {
+	struct driver_set_key_params params;
 	u8 addr[ETH_ALEN];
 	const char *pos = cmd;
-	enum wpa_alg alg;
-	enum key_flag key_flag;
-	int idx, set_tx;
 	u8 seq[6], key[WPA_TK_MAX_LEN];
-	size_t key_len;
+
+	os_memset(&params, 0, sizeof(params));
+	params.ifname = hapd->conf->iface;
 
 	/* parameters: alg addr idx set_tx seq key key_flag */
 
-	alg = atoi(pos);
+	params.alg = atoi(pos);
 	pos = os_strchr(pos, ' ');
 	if (!pos)
 		return -1;
 	pos++;
 	if (hwaddr_aton(pos, addr))
 		return -1;
+	params.addr = addr;
 	pos += 17;
 	if (*pos != ' ')
 		return -1;
 	pos++;
-	idx = atoi(pos);
+	params.key_idx = atoi(pos);
 	pos = os_strchr(pos, ' ');
 	if (!pos)
 		return -1;
 	pos++;
-	set_tx = atoi(pos);
+	params.set_tx = atoi(pos);
 	pos = os_strchr(pos, ' ');
 	if (!pos)
 		return -1;
@@ -2259,47 +2261,59 @@  static int hostapd_ctrl_set_key(struct hostapd_data *hapd, const char *cmd)
 	pos += 2 * 6;
 	if (*pos != ' ')
 		return -1;
+	params.seq = seq;
+	params.seq_len = 6;
 	pos++;
 	if (!os_strchr(pos, ' '))
 		return -1;
-	key_len = (os_strchr(pos, ' ') - pos) / 2;
-	if (hexstr2bin(pos, key, key_len) < 0)
+	params.key_len = (os_strchr(pos, ' ') - pos) / 2;
+	if (hexstr2bin(pos, key, params.key_len) < 0)
 		return -1;
-	pos += 2 * key_len;
+	params.key = key;
+	pos += 2 * params.key_len;
 	if (*pos != ' ')
 		return -1;
 
 	pos++;
-	key_flag = atoi(pos);
+	params.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, 0,
-				   set_tx, seq, 6, key, key_len, key_flag);
+	return hostapd_drv_set_key(hapd, &params);
 }
 
 
 static void restore_tk(void *ctx1, void *ctx2)
 {
 	struct hostapd_data *hapd = ctx1;
+	struct driver_set_key_params params;
 	struct sta_info *sta = ctx2;
 
+	os_memset(&params, 0, sizeof(params));
+
+	params.ifname = hapd->conf->iface;
+	params.set_tx = 1;
+	params.addr = sta->addr;
+	params.alg = sta->last_tk_alg;
+	params.key_idx = sta->last_tk_key_idx;
+	params.key = sta->last_tk;
+	params.key_len = sta->last_tk_len;
+	params.key_flag = KEY_FLAG_PAIRWISE_RX_TX;
+
 	wpa_printf(MSG_INFO, "TESTING: Restore TK for " MACSTR,
 		   MAC2STR(sta->addr));
 	/* This does not really restore the TSC properly, so this will result
 	 * in replay protection issues for now since there is no clean way of
 	 * 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, 0, 1, NULL, 0,
-			    sta->last_tk, sta->last_tk_len,
-			    KEY_FLAG_PAIRWISE_RX_TX);
+	hostapd_drv_set_key(hapd, &params);
 }
 
 
 static int hostapd_ctrl_resend_m1(struct hostapd_data *hapd, const char *cmd)
 {
+	struct driver_set_key_params params;
 	struct sta_info *sta;
 	u8 addr[ETH_ALEN];
 	int plain = os_strstr(cmd, "plaintext") != NULL;
@@ -2316,9 +2330,14 @@  static int hostapd_ctrl_resend_m1(struct hostapd_data *hapd, const char *cmd)
 	if (plain) {
 		wpa_printf(MSG_INFO, "TESTING: Clear TK for " MACSTR,
 			   MAC2STR(sta->addr));
-		hostapd_drv_set_key(hapd->conf->iface, hapd, WPA_ALG_NONE,
-				    sta->addr, sta->last_tk_key_idx, 0, 0, NULL,
-				    0, NULL, 0, KEY_FLAG_PAIRWISE);
+
+		os_memset(&params, 0, sizeof(params));
+		params.ifname = hapd->conf->iface;
+		params.addr = sta->addr;
+		params.key_idx = sta->last_tk_key_idx;
+		params.key_flag = KEY_FLAG_PAIRWISE;
+
+		hostapd_drv_set_key(hapd, &params);
 	}
 
 	wpa_printf(MSG_INFO, "TESTING: Send M1 to " MACSTR, MAC2STR(sta->addr));
@@ -2330,6 +2349,7 @@  static int hostapd_ctrl_resend_m1(struct hostapd_data *hapd, const char *cmd)
 
 static int hostapd_ctrl_resend_m3(struct hostapd_data *hapd, const char *cmd)
 {
+	struct driver_set_key_params params;
 	struct sta_info *sta;
 	u8 addr[ETH_ALEN];
 	int plain = os_strstr(cmd, "plaintext") != NULL;
@@ -2346,9 +2366,13 @@  static int hostapd_ctrl_resend_m3(struct hostapd_data *hapd, const char *cmd)
 	if (plain) {
 		wpa_printf(MSG_INFO, "TESTING: Clear TK for " MACSTR,
 			   MAC2STR(sta->addr));
-		hostapd_drv_set_key(hapd->conf->iface, hapd, WPA_ALG_NONE,
-				    sta->addr, sta->last_tk_key_idx, 0, 0, NULL,
-				    0, NULL, 0, KEY_FLAG_PAIRWISE);
+
+		os_memset(&params, 0, sizeof(params));
+		params.ifname = hapd->conf->iface;
+		params.addr = sta->addr;
+		params.key_idx = sta->last_tk_key_idx;
+		params.key_flag = KEY_FLAG_PAIRWISE;
+		hostapd_drv_set_key(hapd, &params);
 	}
 
 	wpa_printf(MSG_INFO, "TESTING: Send M3 to " MACSTR, MAC2STR(sta->addr));
@@ -2360,6 +2384,7 @@  static int hostapd_ctrl_resend_m3(struct hostapd_data *hapd, const char *cmd)
 static int hostapd_ctrl_resend_group_m1(struct hostapd_data *hapd,
 					const char *cmd)
 {
+	struct driver_set_key_params params;
 	struct sta_info *sta;
 	u8 addr[ETH_ALEN];
 	int plain = os_strstr(cmd, "plaintext") != NULL;
@@ -2376,9 +2401,13 @@  static int hostapd_ctrl_resend_group_m1(struct hostapd_data *hapd,
 	if (plain) {
 		wpa_printf(MSG_INFO, "TESTING: Clear TK for " MACSTR,
 			   MAC2STR(sta->addr));
-		hostapd_drv_set_key(hapd->conf->iface, hapd, WPA_ALG_NONE,
-				    sta->addr, sta->last_tk_key_idx, 0, 0, NULL,
-				    0, NULL, 0, KEY_FLAG_PAIRWISE);
+
+		os_memset(&params, 0, sizeof(params));
+		params.ifname = hapd->conf->iface;
+		params.addr = sta->addr;
+		params.key_idx = sta->last_tk_key_idx;
+		params.key_flag = KEY_FLAG_PAIRWISE;
+		hostapd_drv_set_key(hapd, &params);
 	}
 
 	wpa_printf(MSG_INFO,
diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
index c217d9b24..f367f8571 100644
--- a/src/ap/ap_drv_ops.c
+++ b/src/ap/ap_drv_ops.c
@@ -677,32 +677,12 @@  int hostapd_driver_set_noa(struct hostapd_data *hapd, u8 count, int start,
 	return -1;
 }
 
-
-int hostapd_drv_set_key(const char *ifname, struct hostapd_data *hapd,
-			enum wpa_alg alg, const u8 *addr,
-			int key_idx, int vlan_id, int set_tx,
-			const u8 *seq, size_t seq_len,
-			const u8 *key, size_t key_len, enum key_flag key_flag)
+int hostapd_drv_set_key(struct hostapd_data *hapd,
+			struct driver_set_key_params *params)
 {
-	struct wpa_driver_set_key_params params;
-
 	if (hapd->driver == NULL || hapd->driver->set_key == NULL)
 		return 0;
-
-	os_memset(&params, 0, sizeof(params));
-	params.ifname = ifname;
-	params.alg = alg;
-	params.addr = addr;
-	params.key_idx = key_idx;
-	params.set_tx = set_tx;
-	params.seq = seq;
-	params.seq_len = seq_len;
-	params.key = key;
-	params.key_len = key_len;
-	params.vlan_id = vlan_id;
-	params.key_flag = key_flag;
-
-	return hapd->driver->set_key(hapd->drv_priv, &params);
+	return hapd->driver->set_key(hapd->drv_priv, params);
 }
 
 
diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h
index 56d1ad862..a61cc972e 100644
--- a/src/ap/ap_drv_ops.h
+++ b/src/ap/ap_drv_ops.h
@@ -86,12 +86,8 @@  struct wpa_scan_results * hostapd_driver_get_scan_results(
 	struct hostapd_data *hapd);
 int hostapd_driver_set_noa(struct hostapd_data *hapd, u8 count, int start,
 			   int duration);
-int hostapd_drv_set_key(const char *ifname,
-			struct hostapd_data *hapd,
-			enum wpa_alg alg, const u8 *addr,
-			int key_idx, int vlan_id, int set_tx,
-			const u8 *seq, size_t seq_len,
-			const u8 *key, size_t key_len, enum key_flag key_flag);
+int hostapd_drv_set_key(struct hostapd_data *hapd,
+			struct driver_set_key_params *params);
 int hostapd_drv_send_mlme(struct hostapd_data *hapd,
 			  const void *msg, size_t len, int noack,
 			  const u16 *csa_offs, size_t csa_offs_len,
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index b87663fe9..8f0aa739d 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -287,13 +287,19 @@  int hostapd_reload_config(struct hostapd_iface *iface)
 static void hostapd_broadcast_key_clear_iface(struct hostapd_data *hapd,
 					      const char *ifname)
 {
+	struct driver_set_key_params params;
 	int i;
 
 	if (!ifname || !hapd->drv_priv)
 		return;
+
+	os_memset(&params, 0, sizeof(params));
+	params.ifname = ifname;
+	params.key_flag = KEY_FLAG_GROUP;
+
 	for (i = 0; i < NUM_WEP_KEYS; i++) {
-		if (hostapd_drv_set_key(ifname, hapd, WPA_ALG_NONE, NULL, i, 0,
-					0, NULL, 0, NULL, 0, KEY_FLAG_GROUP)) {
+		params.key_idx = i;
+		if (hostapd_drv_set_key(hapd, &params)) {
 			wpa_printf(MSG_DEBUG, "Failed to clear default "
 				   "encryption keys (ifname=%s keyidx=%d)",
 				   ifname, i);
@@ -301,9 +307,8 @@  static void hostapd_broadcast_key_clear_iface(struct hostapd_data *hapd,
 	}
 	if (hapd->conf->ieee80211w) {
 		for (i = NUM_WEP_KEYS; i < NUM_WEP_KEYS + 2; i++) {
-			if (hostapd_drv_set_key(ifname, hapd, WPA_ALG_NONE,
-						NULL, i, 0, 0, NULL,
-						0, NULL, 0, KEY_FLAG_GROUP)) {
+			params.key_idx = i;
+			if (hostapd_drv_set_key(hapd, &params)) {
 				wpa_printf(MSG_DEBUG, "Failed to clear "
 					   "default mgmt encryption keys "
 					   "(ifname=%s keyidx=%d)", ifname, i);
@@ -322,16 +327,23 @@  static int hostapd_broadcast_wep_clear(struct hostapd_data *hapd)
 
 static int hostapd_broadcast_wep_set(struct hostapd_data *hapd)
 {
-	int errors = 0, idx;
 	struct hostapd_ssid *ssid = &hapd->conf->ssid;
+	struct driver_set_key_params params;
+	int errors = 0;
+
+	os_memset(&params, 0, sizeof(params));
+	params.ifname = hapd->conf->iface;
+	params.set_tx = 1;
+
+	params.addr = broadcast_ether_addr;
+	params.alg = WPA_ALG_WEP;
+	params.key_idx = ssid->wep.idx;
+	params.key = ssid->wep.key[params.key_idx];
+	params.key_len = ssid->wep.len[params.key_idx];
+	params.key_flag = KEY_FLAG_GROUP_RX_TX_DEFAULT;
 
-	idx = ssid->wep.idx;
 	if (ssid->wep.default_len &&
-	    hostapd_drv_set_key(hapd->conf->iface,
-				hapd, WPA_ALG_WEP, broadcast_ether_addr, idx, 0,
-				1, NULL, 0, ssid->wep.key[idx],
-				ssid->wep.len[idx],
-				KEY_FLAG_GROUP_RX_TX_DEFAULT)) {
+	    hostapd_drv_set_key(hapd, &params)) {
 		wpa_printf(MSG_WARNING, "Could not set WEP encryption.");
 		errors++;
 	}
@@ -537,7 +549,11 @@  static void hostapd_clear_wep(struct hostapd_data *hapd)
 
 static int hostapd_setup_encryption(char *iface, struct hostapd_data *hapd)
 {
-	int i;
+	struct driver_set_key_params params;
+
+	os_memset(&params, 0, sizeof(params));
+	params.ifname = iface;
+	params.alg = WPA_ALG_WEP;
 
 	hostapd_broadcast_wep_set(hapd);
 
@@ -551,22 +567,25 @@  static int hostapd_setup_encryption(char *iface, struct hostapd_data *hapd)
 	 * set authentication algorithms for static WEP.
 	 */
 	hostapd_drv_set_authmode(hapd, hapd->conf->auth_algs);
+	for (; params.key_idx < 4; params.key_idx++) {
+		if (params.key_idx == hapd->conf->ssid.wep.idx) {
+			params.set_tx = 1;
+			params.key_flag = KEY_FLAG_GROUP_RX_TX_DEFAULT;
+		} else {
+			params.set_tx = 0;
+			params.key_flag = KEY_FLAG_GROUP_RX_TX;
+		}
+		params.key = hapd->conf->ssid.wep.key[params.key_idx];
+		params.key_len = hapd->conf->ssid.wep.len[params.key_idx];
 
-	for (i = 0; i < 4; i++) {
-		if (hapd->conf->ssid.wep.key[i] &&
-		    hostapd_drv_set_key(iface, hapd, WPA_ALG_WEP, NULL, i, 0,
-					i == hapd->conf->ssid.wep.idx, NULL, 0,
-					hapd->conf->ssid.wep.key[i],
-					hapd->conf->ssid.wep.len[i],
-					i == hapd->conf->ssid.wep.idx ?
-					KEY_FLAG_GROUP_RX_TX_DEFAULT :
-					KEY_FLAG_GROUP_RX_TX)) {
+		if (hapd->conf->ssid.wep.key[params.key_idx] &&
+		    hostapd_drv_set_key(hapd, &params)) {
 			wpa_printf(MSG_WARNING, "Could not set WEP "
 				   "encryption.");
 			return -1;
 		}
-		if (hapd->conf->ssid.wep.key[i] &&
-		    i == hapd->conf->ssid.wep.idx)
+		if (hapd->conf->ssid.wep.key[params.key_idx] &&
+		    params.key_idx == hapd->conf->ssid.wep.idx)
 			hostapd_set_privacy(hapd, 1);
 	}
 
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index cd6107794..38d23fd87 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -4902,20 +4902,30 @@  static void hostapd_set_wds_encryption(struct hostapd_data *hapd,
 				       struct sta_info *sta,
 				       char *ifname_wds)
 {
-	int i;
+	struct driver_set_key_params params;
 	struct hostapd_ssid *ssid = &hapd->conf->ssid;
 
 	if (hapd->conf->ieee802_1x || hapd->conf->wpa)
 		return;
 
-	for (i = 0; i < 4; i++) {
-		if (ssid->wep.key[i] &&
-		    hostapd_drv_set_key(ifname_wds, hapd, WPA_ALG_WEP, NULL, i,
-					0, i == ssid->wep.idx, NULL, 0,
-					ssid->wep.key[i], ssid->wep.len[i],
-					i == ssid->wep.idx ?
-					KEY_FLAG_GROUP_RX_TX_DEFAULT :
-					KEY_FLAG_GROUP_RX_TX)) {
+	os_memset(&params, 0, sizeof(params));
+	params.ifname = ifname_wds;
+	params.alg = WPA_ALG_WEP;
+
+	for (; params.key_idx < 4; params.key_idx++) {
+		if (params.key_idx == ssid->wep.idx) {
+			params.set_tx = 1;
+			params.key_flag = KEY_FLAG_GROUP_RX_TX_DEFAULT;
+		} else {
+			params.set_tx = 0;
+			params.key_flag = KEY_FLAG_GROUP_RX_TX;
+		}
+		params.key = ssid->wep.key[params.key_idx];
+		params.key_len = ssid->wep.len[params.key_idx];
+
+
+		if (ssid->wep.key[params.key_idx] &&
+		    hostapd_drv_set_key(hapd, &params)) {
 			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 001b26109..1bacf49c9 100644
--- a/src/ap/ieee802_1x.c
+++ b/src/ap/ieee802_1x.c
@@ -263,35 +263,43 @@  static void ieee802_1x_tx_key(struct hostapd_data *hapd, struct sta_info *sta)
 	}
 
 	if (hapd->conf->individual_wep_key_len > 0) {
+		struct driver_set_key_params params;
 		u8 *ikey;
 
-		ikey = os_malloc(hapd->conf->individual_wep_key_len);
+		os_memset(&params, 0, sizeof(params));
+		params.ifname = hapd->conf->iface;
+		params.set_tx = 1;
+		params.addr = sta->addr;
+		params.alg = WPA_ALG_WEP;
+		params.key_len = hapd->conf->individual_wep_key_len;
+		params.key_flag = KEY_FLAG_PAIRWISE_RX_TX;
+
+		ikey = os_malloc(params.key_len);
 		if (!ikey ||
-		    random_get_bytes(ikey, hapd->conf->individual_wep_key_len))
+		    random_get_bytes(ikey, params.key_len))
 		{
 			wpa_printf(MSG_ERROR,
 				   "Could not generate random individual WEP key");
 			os_free(ikey);
 			return;
 		}
+		params.key = ikey;
 
 		wpa_hexdump_key(MSG_DEBUG, "Individual WEP key",
-				ikey, hapd->conf->individual_wep_key_len);
+				params.key, params.key_len);
 
 		ieee802_1x_tx_key_one(hapd, sta, 0, 0, ikey,
-				      hapd->conf->individual_wep_key_len);
+				      params.key_len);
 
 		/* TODO: set encryption in TX callback, i.e., only after STA
 		 * has ACKed EAPOL-Key frame */
-		if (hostapd_drv_set_key(hapd->conf->iface, hapd, WPA_ALG_WEP,
-					sta->addr, 0, 0, 1, NULL, 0, ikey,
-					hapd->conf->individual_wep_key_len,
-					KEY_FLAG_PAIRWISE_RX_TX)) {
+		if (hostapd_drv_set_key(hapd, &params)) {
 			wpa_printf(MSG_ERROR,
 				   "Could not set individual WEP encryption");
 		}
 
 		os_free(ikey);
+		params.key = NULL;
 	}
 }
 
@@ -2153,6 +2161,7 @@  static int ieee802_1x_sta_key_available(struct hostapd_data *hapd,
 
 static void ieee802_1x_rekey(void *eloop_ctx, void *timeout_ctx)
 {
+	struct driver_set_key_params params;
 	struct hostapd_data *hapd = eloop_ctx;
 	struct eapol_authenticator *eapol = hapd->eapol_auth;
 
@@ -2174,14 +2183,20 @@  static void ieee802_1x_rekey(void *eloop_ctx, void *timeout_ctx)
 		return;
 	}
 
+	os_memset(&params, 0, sizeof(params));
+	params.ifname = hapd->conf->iface;
+	params.set_tx = 1;
+
+	params.addr = broadcast_ether_addr;
+	params.alg = WPA_ALG_WEP;
+	params.key_idx = eapol->default_wep_key_idx;
+	params.key = eapol->default_wep_key;
+	params.key_len = hapd->conf->default_wep_key_len;
+	params.key_flag = KEY_FLAG_GROUP_RX_TX_DEFAULT;
+
 	/* TODO: Could setup key for RX here, but change default TX keyid only
 	 * after new broadcast key has been sent to all stations. */
-	if (hostapd_drv_set_key(hapd->conf->iface, hapd, WPA_ALG_WEP,
-				broadcast_ether_addr,
-				eapol->default_wep_key_idx, 0, 1, NULL, 0,
-				eapol->default_wep_key,
-				hapd->conf->default_wep_key_len,
-				KEY_FLAG_GROUP_RX_TX_DEFAULT)) {
+	if (hostapd_drv_set_key(hapd, &params)) {
 		hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE8021X,
 			       HOSTAPD_LEVEL_WARNING,
 			       "failed to configure a new broadcast key");
@@ -2422,7 +2437,7 @@  static int ieee802_1x_erp_add_key(void *ctx, struct eap_server_erp_key *erp)
 
 int ieee802_1x_init(struct hostapd_data *hapd)
 {
-	int i;
+	struct driver_set_key_params params;
 	struct eapol_auth_config conf;
 	struct eapol_auth_cb cb;
 
@@ -2469,11 +2484,13 @@  int ieee802_1x_init(struct hostapd_data *hapd)
 		return -1;
 #endif /* CONFIG_NO_RADIUS */
 
+	os_memset(&params, 0, sizeof(params));
+	params.ifname = hapd->conf->iface;
+	params.key_flag = KEY_FLAG_GROUP;
+
 	if (hapd->conf->default_wep_key_len) {
-		for (i = 0; i < 4; i++)
-			hostapd_drv_set_key(hapd->conf->iface, hapd,
-					    WPA_ALG_NONE, NULL, i, 0, 0, NULL,
-					    0, NULL, 0, KEY_FLAG_GROUP_RX_TX);
+		for (; params.key_idx < 4; params.key_idx++)
+			hostapd_drv_set_key(hapd, &params);
 
 		ieee802_1x_rekey(hapd, NULL);
 
diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c
index 423528d12..0536e45cd 100644
--- a/src/ap/wpa_auth.c
+++ b/src/ap/wpa_auth.c
@@ -134,15 +134,11 @@  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,
-				   enum key_flag key_flag)
+				   struct wpa_set_key_params *wpa_params)
 {
 	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_flag);
+	return wpa_auth->cb->set_key(wpa_auth->cb_ctx, wpa_params);
 }
 
 
@@ -1736,10 +1732,17 @@  static int wpa_verify_key_mic(int akmp, size_t pmk_len, struct wpa_ptk *PTK,
 
 void wpa_remove_ptk(struct wpa_state_machine *sm)
 {
+	struct wpa_set_key_params wpa_params;
+
 	sm->PTK_valid = FALSE;
+	os_memset(&wpa_params, 0, sizeof(wpa_params));
 	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, KEY_FLAG_PAIRWISE))
+
+	wpa_params.alg = WPA_ALG_NONE;
+	wpa_params.addr = sm->addr;
+	wpa_params.key_flag = KEY_FLAG_PAIRWISE;
+
+	if (wpa_auth_set_key(sm->wpa_auth, &wpa_params))
 		wpa_printf(MSG_DEBUG,
 			   "RSN: PTK removal from the driver failed");
 	sm->pairwise_set = FALSE;
@@ -2755,8 +2758,7 @@  static struct wpabuf * fils_prepare_plainbuf(struct wpa_state_machine *sm,
 
 int fils_set_tk(struct wpa_state_machine *sm)
 {
-	enum wpa_alg alg;
-	int klen;
+	struct wpa_set_key_params wpa_params;
 
 	if (!sm || !sm->PTK_valid) {
 		wpa_printf(MSG_DEBUG, "FILS: No valid PTK available to set TK");
@@ -2767,12 +2769,15 @@  int fils_set_tk(struct wpa_state_machine *sm)
 		return -1;
 	}
 
-	alg = wpa_cipher_to_alg(sm->pairwise);
-	klen = wpa_cipher_key_len(sm->pairwise);
+	os_memset(&wpa_params, 0, sizeof(wpa_params));
+	wpa_params.alg = wpa_cipher_to_alg(sm->pairwise);
+	wpa_params.addr = sm->addr;
+	wpa_params.key = sm->PTK.tk;
+	wpa_params.key_len = wpa_cipher_key_len(sm->pairwise);
+	wpa_params.key_flag = KEY_FLAG_PAIRWISE_RX_TX;
 
 	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, KEY_FLAG_PAIRWISE_RX_TX)) {
+	if (wpa_auth_set_key(sm->wpa_auth, &wpa_params)) {
 		wpa_printf(MSG_DEBUG, "FILS: Failed to set TK to the driver");
 		return -1;
 	}
@@ -3394,11 +3399,15 @@  SM_STATE(WPA_PTK, PTKINITDONE)
 	SM_ENTRY_MA(WPA_PTK, PTKINITDONE, wpa_ptk);
 	sm->EAPOLKeyReceived = FALSE;
 	if (sm->Pair) {
-		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,
-				     KEY_FLAG_PAIRWISE_RX_TX)) {
+		struct wpa_set_key_params wpa_params;
+
+		os_memset(&wpa_params, 0, sizeof(wpa_params));
+		wpa_params.alg = wpa_cipher_to_alg(sm->pairwise);
+		wpa_params.addr = sm->addr;
+		wpa_params.key = sm->PTK.tk;
+		wpa_params.key_len = wpa_cipher_key_len(sm->pairwise);
+		wpa_params.key_flag = KEY_FLAG_PAIRWISE_RX_TX;
+		if (wpa_auth_set_key(sm->wpa_auth, &wpa_params)) {
 			wpa_sta_disconnect(sm->wpa_auth, sm->addr,
 					   WLAN_REASON_PREV_AUTH_NOT_VALID);
 			return;
@@ -3985,27 +3994,30 @@  static void wpa_group_setkeys(struct wpa_authenticator *wpa_auth,
 static int wpa_group_config_group_keys(struct wpa_authenticator *wpa_auth,
 				       struct wpa_group *group)
 {
+	struct wpa_set_key_params wpa_params;
 	int ret = 0;
 
-	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,
-			     KEY_FLAG_GROUP_TX_DEFAULT) < 0)
+	os_memset(&wpa_params, 0, sizeof(wpa_params));
+	wpa_params.vlan_id = group->vlan_id;
+	wpa_params.alg = wpa_cipher_to_alg(wpa_auth->conf.wpa_group);
+	wpa_params.key_idx = group->GN;
+	wpa_params.addr = broadcast_ether_addr;
+	wpa_params.key = group->GTK[group->GN - 1];
+	wpa_params.key_len = group->GTK_len;
+	wpa_params.key_flag = KEY_FLAG_GROUP_TX_DEFAULT;
+
+	if (wpa_auth_set_key(wpa_auth, &wpa_params) < 0)
 		ret = -1;
 
 	if (wpa_auth->conf.ieee80211w != NO_MGMT_FRAME_PROTECTION) {
-		enum wpa_alg alg;
-		size_t len;
-
-		alg = wpa_cipher_to_alg(wpa_auth->conf.group_mgmt_cipher);
-		len = wpa_cipher_key_len(wpa_auth->conf.group_mgmt_cipher);
+		wpa_params.alg = wpa_cipher_to_alg(wpa_auth->conf.group_mgmt_cipher);
+		wpa_params.key_idx = group->GN_igtk;
+		wpa_params.key = group->IGTK[group->GN_igtk - 4];
+		wpa_params.key_len = wpa_cipher_key_len(wpa_auth->conf.group_mgmt_cipher);
+		wpa_params.key_flag = KEY_FLAG_GROUP_TX_DEFAULT;
 
 		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,
-				     KEY_FLAG_GROUP_TX_DEFAULT) < 0)
+		    wpa_auth_set_key(wpa_auth, &wpa_params) < 0)
 			ret = -1;
 	}
 
diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h
index 0b4b7297c..5b8f5a1c7 100644
--- a/src/ap/wpa_auth.h
+++ b/src/ap/wpa_auth.h
@@ -146,6 +146,7 @@  struct rsn_pmksa_cache_entry;
 struct eapol_state_machine;
 struct ft_remote_seq;
 struct wpa_channel_info;
+struct wpa_set_key_params;
 
 
 struct ft_remote_r0kh {
@@ -262,9 +263,7 @@  struct wpa_auth_callbacks {
 			      const u8 *prev_psk, size_t *psk_len,
 			      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,
-		       enum key_flag key_flag);
+	int (*set_key)(void *ctx, struct wpa_set_key_params *wpa_params);
 	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 462876195..b10c773f8 100644
--- a/src/ap/wpa_auth_ft.c
+++ b/src/ap/wpa_auth_ft.c
@@ -2620,26 +2620,19 @@  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,
-				   enum key_flag key_flag)
+				   struct wpa_set_key_params *wpa_params)
 {
 	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_flag);
+	return wpa_auth->cb->set_key(wpa_auth->cb_ctx, wpa_params);
 }
 
 
 void wpa_ft_install_ptk(struct wpa_state_machine *sm)
 {
-	enum wpa_alg alg;
-	int klen;
+	struct wpa_set_key_params wpa_params;
 
 	/* MLME-SETKEYS.request(PTK) */
-	alg = wpa_cipher_to_alg(sm->pairwise);
-	klen = wpa_cipher_key_len(sm->pairwise);
 	if (!wpa_cipher_valid_pairwise(sm->pairwise)) {
 		wpa_printf(MSG_DEBUG, "FT: Unknown pairwise alg 0x%x - skip "
 			   "PTK configuration", sm->pairwise);
@@ -2660,8 +2653,15 @@  void wpa_ft_install_ptk(struct wpa_state_machine *sm)
 	 * again after association to get the PTK configured, but that could be
 	 * optimized by adding the STA entry earlier.
 	 */
-	if (wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr, 0,
-			     sm->PTK.tk, klen, KEY_FLAG_PAIRWISE_RX_TX))
+
+	os_memset(&wpa_params, 0, sizeof(wpa_params));
+	wpa_params.alg = wpa_cipher_to_alg(sm->pairwise);
+	wpa_params.addr = sm->addr;
+	wpa_params.key = sm->PTK.tk;
+	wpa_params.key_len = wpa_cipher_key_len(sm->pairwise);
+	wpa_params.key_flag = KEY_FLAG_PAIRWISE_RX_TX;
+
+	if (wpa_auth_set_key(sm->wpa_auth, &wpa_params))
 		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 e64304636..8694d296b 100644
--- a/src/ap/wpa_auth_glue.c
+++ b/src/ap/wpa_auth_glue.c
@@ -376,54 +376,62 @@  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, enum key_flag key_flag)
+static int hostapd_wpa_auth_set_key(void *ctx,
+				    struct wpa_set_key_params *wpa_params)
 {
+	struct driver_set_key_params params;
 	struct hostapd_data *hapd = ctx;
-	const char *ifname = hapd->conf->iface;
-
-	if (vlan_id > 0) {
-		ifname = hostapd_get_vlan_id_ifname(hapd->conf->vlan, vlan_id);
-		if (!ifname) {
-			if (!(hapd->iface->drv_flags &
-			      WPA_DRIVER_FLAGS_VLAN_OFFLOAD))
-				return -1;
-			ifname = hapd->conf->iface;
-		}
+
+	os_memset(&params, 0, sizeof(params));
+
+	if (wpa_params->vlan_id > 0) {
+		params.ifname = hostapd_get_vlan_id_ifname(hapd->conf->vlan,
+							   wpa_params->vlan_id);
+		if (params.ifname == NULL)
+			return -1;
+	} else {
+		params.ifname = hapd->conf->iface;
 	}
+	params.set_tx = 1;
+	params.addr = wpa_params->addr;
+	params.alg = wpa_params->alg;
+	params.key = wpa_params->key;
+	params.key_len = wpa_params->key_len;
+	params.key_idx = wpa_params->key_idx;
+	params.key_flag = wpa_params->key_flag;
 
 #ifdef CONFIG_TESTING_OPTIONS
-	if (addr && !is_broadcast_ether_addr(addr)) {
+	if (wpa_params->addr && !is_broadcast_ether_addr(wpa_params->addr)) {
 		struct sta_info *sta;
 
-		sta = ap_get_sta(hapd, addr);
+		sta = ap_get_sta(hapd, wpa_params->addr);
 		if (sta) {
-			sta->last_tk_alg = alg;
-			sta->last_tk_key_idx = idx;
-			if (key)
-				os_memcpy(sta->last_tk, key, key_len);
-			sta->last_tk_len = key_len;
+			sta->last_tk_alg = wpa_params->alg;
+			sta->last_tk_key_idx = wpa_params->key_idx;
+			if (wpa_params->key)
+				os_memcpy(sta->last_tk, wpa_params->key,
+					  wpa_params->key_len);
+			sta->last_tk_len = wpa_params->key_len;
 		}
-	} else if (alg == WPA_ALG_IGTK ||
-		   alg == WPA_ALG_BIP_GMAC_128 ||
-		   alg == WPA_ALG_BIP_GMAC_256 ||
-		   alg == WPA_ALG_BIP_CMAC_256) {
-		hapd->last_igtk_alg = alg;
-		hapd->last_igtk_key_idx = idx;
-		if (key)
-			os_memcpy(hapd->last_igtk, key, key_len);
-		hapd->last_igtk_len = key_len;
+	} else if (wpa_params->alg == WPA_ALG_IGTK ||
+		   wpa_params->alg == WPA_ALG_BIP_GMAC_128 ||
+		   wpa_params->alg == WPA_ALG_BIP_GMAC_256 ||
+		   wpa_params->alg == WPA_ALG_BIP_CMAC_256) {
+		hapd->last_igtk_alg = wpa_params->alg;
+		hapd->last_igtk_key_idx = wpa_params->key_idx;
+		if (wpa_params->key)
+			os_memcpy(hapd->last_igtk, wpa_params->key,
+				  wpa_params->key_len);
+		hapd->last_igtk_len = wpa_params->key_len;
 	} else {
-		hapd->last_gtk_alg = alg;
-		hapd->last_gtk_key_idx = idx;
-		if (key)
-			os_memcpy(hapd->last_gtk, key, key_len);
-		hapd->last_gtk_len = key_len;
+		hapd->last_gtk_alg = wpa_params->alg;
+		hapd->last_gtk_key_idx = wpa_params->key_idx;
+		if (wpa_params->key)
+			os_memcpy(hapd->last_gtk, wpa_params->key, wpa_params->key_len);
+		hapd->last_gtk_len = wpa_params->key_len;
 	}
 #endif /* CONFIG_TESTING_OPTIONS */
-	return hostapd_drv_set_key(ifname, hapd, alg, addr, idx, vlan_id, 1,
-				   NULL, 0, key, key_len, key_flag);
+	return hostapd_drv_set_key(hapd, &params);
 }
 
 
diff --git a/src/common/privsep_commands.h b/src/common/privsep_commands.h
index b85c6c347..d2c4bbd5e 100644
--- a/src/common/privsep_commands.h
+++ b/src/common/privsep_commands.h
@@ -82,6 +82,7 @@  struct privsep_cmd_set_key {
 	size_t seq_len;
 	u8 key[32];
 	size_t key_len;
+	enum key_flag key_flag;
 };
 
 enum privsep_event {
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index c37dd2fc9..1e4179e1a 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -1182,6 +1182,20 @@  struct wpa_driver_associate_params {
 	size_t fils_erp_rrk_len;
 };
 
+/**
+ * struct wpa_set_key_params - WPA set_key params
+ * Data for struct wpa_auth_callbacks::set_key().
+ */
+struct wpa_set_key_params {
+	int vlan_id;
+	enum wpa_alg alg;
+	const u8 *addr;
+	int key_idx;
+	u8 *key;
+	size_t key_len;
+	enum key_flag key_flag;
+};
+
 enum hide_ssid {
 	NO_SSID_HIDING,
 	HIDDEN_SSID_ZERO_LEN,
@@ -1524,7 +1538,7 @@  struct wpa_driver_mesh_join_params {
 	unsigned int flags;
 };
 
-struct wpa_driver_set_key_params {
+struct driver_set_key_params {
 	/**
 	 * ifname - Interface name (for multi-SSID/VLAN support) */
 	const char *ifname;
@@ -2446,7 +2460,7 @@  struct wpa_driver_ops {
 	 * in driver_*.c set_key() implementation, see driver_ndis.c for an
 	 * example on how this can be done.
 	 */
-	int (*set_key)(void *priv, struct wpa_driver_set_key_params *params);
+	int (*set_key)(void *priv, struct driver_set_key_params *params);
 
 	/**
 	 * init - Initialize driver interface
diff --git a/src/drivers/driver_atheros.c b/src/drivers/driver_atheros.c
index 2014f9db4..b207aec4a 100644
--- a/src/drivers/driver_atheros.c
+++ b/src/drivers/driver_atheros.c
@@ -492,7 +492,7 @@  atheros_del_key(void *priv, const u8 *addr, int key_idx)
 }
 
 static int
-atheros_set_key(void *priv, struct wpa_driver_set_key_params *params)
+atheros_set_key(void *priv, struct driver_set_key_params *params)
 {
 	struct atheros_driver_data *drv = priv;
 	struct ieee80211req_key wk;
@@ -505,13 +505,14 @@  atheros_set_key(void *priv, struct wpa_driver_set_key_params *params)
 	const u8 *key = params->key;
 	size_t key_len = params->key_len;
 
-	if (alg == WPA_ALG_NONE)
-		return atheros_del_key(drv, addr, key_idx);
+	if (params->alg == WPA_ALG_NONE)
+		return atheros_del_key(drv, params->addr, params->key_idx);
 
 	wpa_printf(MSG_DEBUG, "%s: alg=%d addr=%s key_idx=%d",
-		   __func__, alg, ether_sprintf(addr), key_idx);
+		   __func__, params->alg, ether_sprintf(params->addr),
+		   params->key_idx);
 
-	switch (alg) {
+	switch (params->alg) {
 	case WPA_ALG_WEP:
 		cipher = IEEE80211_CIPHER_WEP;
 		break;
@@ -548,37 +549,38 @@  atheros_set_key(void *priv, struct wpa_driver_set_key_params *params)
 #endif /* ATH_GCM_SUPPORT */
 	default:
 		wpa_printf(MSG_INFO, "%s: unknown/unsupported algorithm %d",
-			   __func__, alg);
+			   __func__, params->alg);
 		return -1;
 	}
 
-	if (key_len > sizeof(wk.ik_keydata)) {
+	if (params->key_len > sizeof(wk.ik_keydata)) {
 		wpa_printf(MSG_INFO, "%s: key length %lu too big", __func__,
-			   (unsigned long) key_len);
+			   (unsigned long) params->key_len);
 		return -3;
 	}
 
 	os_memset(&wk, 0, sizeof(wk));
 	wk.ik_type = cipher;
 	wk.ik_flags = IEEE80211_KEY_RECV | IEEE80211_KEY_XMIT;
-	if (addr == NULL || is_broadcast_ether_addr(addr)) {
+	if (params->addr == NULL || is_broadcast_ether_addr(params->addr)) {
 		os_memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN);
-		wk.ik_keyix = key_idx;
-		if (set_tx)
+		wk.ik_keyix = params->key_idx;
+		if (params->set_tx)
 			wk.ik_flags |= IEEE80211_KEY_DEFAULT;
 	} else {
-		os_memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN);
+		os_memcpy(wk.ik_macaddr, params->addr, IEEE80211_ADDR_LEN);
 		wk.ik_keyix = IEEE80211_KEYIX_NONE;
 	}
-	wk.ik_keylen = key_len;
-	os_memcpy(wk.ik_keydata, key, key_len);
+	wk.ik_keylen = params->key_len;
+	os_memcpy(wk.ik_keydata, params->key, params->key_len);
 
 	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)",
-			   __func__, ether_sprintf(wk.ik_macaddr), key_idx,
-			   alg, (unsigned long) key_len, set_tx);
+			   __func__, ether_sprintf(wk.ik_macaddr),
+			   params->key_idx, params->alg, (unsigned long)
+			   params->key_len, params->set_tx);
 	}
 
 	return ret;
diff --git a/src/drivers/driver_bsd.c b/src/drivers/driver_bsd.c
index a9b5d002d..f4dbe7755 100644
--- a/src/drivers/driver_bsd.c
+++ b/src/drivers/driver_bsd.c
@@ -331,7 +331,7 @@  bsd_ctrl_iface(void *priv, int enable)
 }
 
 static int
-bsd_set_key(void *priv, struct wpa_driver_set_key_params *params)
+bsd_set_key(void *priv, struct driver_set_key_params *params)
 {
 	struct ieee80211req_key wk;
 #ifdef IEEE80211_KEY_NOREPLAY
diff --git a/src/drivers/driver_hostap.c b/src/drivers/driver_hostap.c
index cfc52c7f3..31f9fa447 100644
--- a/src/drivers/driver_hostap.c
+++ b/src/drivers/driver_hostap.c
@@ -397,7 +397,7 @@  static int hostapd_ioctl(void *priv, struct prism2_hostapd_param *param,
 
 
 static int wpa_driver_hostap_set_key(void *priv,
-				     struct wpa_driver_set_key_params *params)
+				     struct driver_set_key_params *params)
 {
 	struct hostap_driver_data *drv = priv;
 	struct prism2_hostapd_param *param;
@@ -411,18 +411,18 @@  static int wpa_driver_hostap_set_key(void *priv,
 	const u8 *key = params->key;
 	size_t key_len = params->key_len;
 
-	blen = sizeof(*param) + key_len;
+	blen = sizeof(*param) + params->key_len;
 	buf = os_zalloc(blen);
 	if (buf == NULL)
 		return -1;
 
 	param = (struct prism2_hostapd_param *) buf;
 	param->cmd = PRISM2_SET_ENCRYPTION;
-	if (addr == NULL)
+	if (params->addr == NULL)
 		memset(param->sta_addr, 0xff, ETH_ALEN);
 	else
-		memcpy(param->sta_addr, addr, ETH_ALEN);
-	switch (alg) {
+		memcpy(param->sta_addr, params->addr, ETH_ALEN);
+	switch (params->alg) {
 	case WPA_ALG_NONE:
 		os_strlcpy((char *) param->u.crypt.alg, "NONE",
 			   HOSTAP_CRYPT_ALG_NAME_LEN);
@@ -443,10 +443,11 @@  static int wpa_driver_hostap_set_key(void *priv,
 		os_free(buf);
 		return -1;
 	}
-	param->u.crypt.flags = set_tx ? 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);
+	param->u.crypt.flags = params->set_tx ?
+			       HOSTAP_CRYPT_FLAG_SET_TX_KEY : 0;
+	param->u.crypt.idx = params->key_idx;
+	param->u.crypt.key_len = params->key_len;
+	memcpy((u8 *) (param + 1), params->key, params->key_len);
 
 	if (hostapd_ioctl(drv, param, blen)) {
 		printf("Failed to set encryption.\n");
diff --git a/src/drivers/driver_ndis.c b/src/drivers/driver_ndis.c
index 529fc3bc6..db99522d7 100644
--- a/src/drivers/driver_ndis.c
+++ b/src/drivers/driver_ndis.c
@@ -963,11 +963,8 @@  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,
-				   const u8 *seq, size_t seq_len,
-				   const u8 *key, size_t key_len)
+static int wpa_driver_ndis_set_key(void *priv,
+				   struct driver_set_key_params *params)
 {
 	struct wpa_driver_ndis_data *drv = priv;
 	size_t len, i;
@@ -975,7 +972,7 @@  static int wpa_driver_ndis_set_key(const char *ifname, void *priv,
 	int res, pairwise;
 	u8 bssid[ETH_ALEN];
 
-	if (addr == NULL || is_broadcast_ether_addr(addr)) {
+	if (params->addr == NULL || is_broadcast_ether_addr(params->addr)) {
 		/* Group Key */
 		pairwise = 0;
 		if (wpa_driver_ndis_get_bssid(drv, bssid) < 0)
@@ -983,45 +980,47 @@  static int wpa_driver_ndis_set_key(const char *ifname, void *priv,
 	} else {
 		/* Pairwise Key */
 		pairwise = 1;
-		os_memcpy(bssid, addr, ETH_ALEN);
+		os_memcpy(bssid, params->addr, ETH_ALEN);
 	}
 
-	if (alg == WPA_ALG_NONE || key_len == 0) {
-		return wpa_driver_ndis_remove_key(drv, key_idx, addr, bssid,
+	if (params->alg == WPA_ALG_NONE || params->key_len == 0) {
+		return wpa_driver_ndis_remove_key(drv, params->key_idx,
+						  params->addr, bssid,
 						  pairwise);
 	}
 
-	if (alg == WPA_ALG_WEP) {
-		return wpa_driver_ndis_add_wep(drv, pairwise, key_idx, set_tx,
-					       key, key_len);
+	if (params->alg == WPA_ALG_WEP) {
+		return wpa_driver_ndis_add_wep(drv, pairwise, params->key_idx,
+					       params->set_tx, params->key,
+					       params->key_len);
 	}
 
-	len = 12 + 6 + 6 + 8 + key_len;
+	len = 12 + 6 + 6 + 8 + params->key_len;
 
 	nkey = os_zalloc(len);
 	if (nkey == NULL)
 		return -1;
 
 	nkey->Length = len;
-	nkey->KeyIndex = key_idx;
-	if (set_tx)
+	nkey->KeyIndex = params->key_idx;
+	if (params->set_tx)
 		nkey->KeyIndex |= 1 << 31;
 	if (pairwise)
 		nkey->KeyIndex |= 1 << 30;
-	if (seq && seq_len)
+	if (params->seq && params->seq_len)
 		nkey->KeyIndex |= 1 << 29;
-	nkey->KeyLength = key_len;
+	nkey->KeyLength = params->key_len;
 	os_memcpy(nkey->BSSID, bssid, ETH_ALEN);
-	if (seq && seq_len) {
-		for (i = 0; i < seq_len; i++)
-			nkey->KeyRSC |= (ULONGLONG) seq[i] << (i * 8);
-	}
-	if (alg == WPA_ALG_TKIP && key_len == 32) {
-		os_memcpy(nkey->KeyMaterial, key, 16);
-		os_memcpy(nkey->KeyMaterial + 16, key + 24, 8);
-		os_memcpy(nkey->KeyMaterial + 24, key + 16, 8);
+	if (params->seq && params->seq_len) {
+		for (i = 0; i < params->seq_len; i++)
+			nkey->KeyRSC |= (ULONGLONG) params->seq[i] << (i * 8);
+	}
+	if (params->alg == WPA_ALG_TKIP && params->key_len == 32) {
+		os_memcpy(nkey->KeyMaterial, params->key, 16);
+		os_memcpy(nkey->KeyMaterial + 16, params->key + 24, 8);
+		os_memcpy(nkey->KeyMaterial + 24, params->key + 16, 8);
 	} else {
-		os_memcpy(nkey->KeyMaterial, key, key_len);
+		os_memcpy(nkey->KeyMaterial, params->key, params->key_len);
 	}
 
 	wpa_hexdump_key(MSG_MSGDUMP, "NDIS: OID_802_11_ADD_KEY",
@@ -1035,7 +1034,7 @@  static int wpa_driver_ndis_set_key(const char *ifname, void *priv,
 
 static int
 wpa_driver_ndis_set_key_wrapper(void *priv,
-				struct wpa_driver_set_key_params *params)
+				struct driver_set_key_params *params)
 {
 	return wpa_driver_ndis_set_key(params->ifname, priv,
 				       params->alg, params->addr,
@@ -1087,7 +1086,7 @@  wpa_driver_ndis_associate(void *priv,
 						bcast, i,
 						i == params->wep_tx_keyidx,
 						NULL, 0, params->wep_key[i],
-						params->wep_key_len[i]);
+						params->wep_key_len[i], 0);
 		}
 	}
 
@@ -1124,7 +1123,7 @@  wpa_driver_ndis_associate(void *priv,
 			wpa_driver_ndis_set_key(drv->ifname, drv, WPA_ALG_WEP,
 						bcast, 0, 1,
 						NULL, 0, dummy_key,
-						sizeof(dummy_key));
+						sizeof(dummy_key), 0);
 		}
 #endif /* CONFIG_WPS */
 	} else {
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 64bea49e1..679051f47 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -3012,7 +3012,7 @@  static int nl80211_set_pmk(struct wpa_driver_nl80211_data *drv,
 
 
 static int wpa_driver_nl80211_set_key(struct i802_bss *bss,
-				      struct wpa_driver_set_key_params *params)
+				      struct driver_set_key_params *params)
 {
 	struct wpa_driver_nl80211_data *drv = bss->drv;
 	int ifindex;
@@ -3478,7 +3478,7 @@  static int wpa_driver_nl80211_authenticate(
 	enum nl80211_iftype nlmode;
 	int count = 0;
 	int is_retry;
-	struct wpa_driver_set_key_params p;
+	struct driver_set_key_params p;
 
 	nl80211_unmask_11b_rates(bss);
 
@@ -8730,7 +8730,7 @@  nl80211_tdls_disable_channel_switch(void *priv, const u8 *addr)
 
 
 static int driver_nl80211_set_key(void *priv,
-				  struct wpa_driver_set_key_params *params)
+				  struct driver_set_key_params *params)
 {
 	struct i802_bss *bss = priv;
 
diff --git a/src/drivers/driver_openbsd.c b/src/drivers/driver_openbsd.c
index e0eede96b..0c63721e8 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(void *priv, struct wpa_driver_set_key_params *params)
+wpa_driver_openbsd_set_key(void *priv, struct driver_set_key_params *params)
 {
 	struct openbsd_driver_data *drv = priv;
 	struct ieee80211_keyavail keyavail;
@@ -77,14 +77,14 @@  wpa_driver_openbsd_set_key(void *priv, struct wpa_driver_set_key_params *params)
 	const u8 *key = params->key;
 	size_t key_len = params->key_len;
 
-	if (alg != WPA_ALG_PMK || key_len > IEEE80211_PMK_LEN)
+	if (params->alg != WPA_ALG_PMK || params->key_len > IEEE80211_PMK_LEN)
 		return -1;
 
 	memset(&keyavail, 0, sizeof(keyavail));
 	os_strlcpy(keyavail.i_name, drv->ifname, sizeof(keyavail.i_name));
 	if (wpa_driver_openbsd_get_bssid(priv, keyavail.i_macaddr) < 0)
 		return -1;
-	memcpy(keyavail.i_key, key, key_len);
+	memcpy(keyavail.i_key, params->key, params->key_len);
 
 	if (ioctl(drv->sock, SIOCS80211KEYAVAIL, &keyavail) < 0)
 		return -1;
diff --git a/src/drivers/driver_privsep.c b/src/drivers/driver_privsep.c
index 807657ebc..9f2b016bf 100644
--- a/src/drivers/driver_privsep.c
+++ b/src/drivers/driver_privsep.c
@@ -206,37 +206,31 @@  wpa_driver_privsep_get_scan_results2(void *priv)
 
 
 static int wpa_driver_privsep_set_key(void *priv,
-				      struct wpa_driver_set_key_params *params)
+				      struct driver_set_key_params *params)
 {
 	struct wpa_driver_privsep_data *drv = priv;
 	struct privsep_cmd_set_key cmd;
-	enum wpa_alg alg = params->alg;
-	const u8 *addr = params->addr;
-	int key_idx = params->key_idx;
-	int set_tx = params->set_tx;
-	const u8 *seq = params->seq;
-	size_t seq_len = params->seq_len;
-	const u8 *key = params->key;
-	size_t key_len = params->key_len;
 
 	wpa_printf(MSG_DEBUG, "%s: priv=%p alg=%d key_idx=%d set_tx=%d",
-		   __func__, priv, alg, key_idx, set_tx);
+		   __func__, priv, params->alg, params->key_idx, set_tx);
 
 	os_memset(&cmd, 0, sizeof(cmd));
-	cmd.alg = alg;
-	if (addr)
-		os_memcpy(cmd.addr, addr, ETH_ALEN);
+	cmd.alg = params->alg;
+	if (params->addr)
+		os_memcpy(cmd.addr, params->addr, ETH_ALEN);
 	else
 		os_memset(cmd.addr, 0xff, ETH_ALEN);
-	cmd.key_idx = key_idx;
-	cmd.set_tx = set_tx;
-	if (seq && seq_len > 0 && seq_len < sizeof(cmd.seq)) {
-		os_memcpy(cmd.seq, seq, seq_len);
-		cmd.seq_len = seq_len;
-	}
-	if (key && key_len > 0 && key_len < sizeof(cmd.key)) {
-		os_memcpy(cmd.key, key, key_len);
-		cmd.key_len = key_len;
+	cmd.set_tx = params->set_tx;
+	cmd.key_flag = params->key_flag;
+	if (params->seq && params->seq_len > 0 &&
+	    params->seq_len < sizeof(cmd.seq)) {
+		os_memcpy(cmd.seq, params->seq, params->seq_len);
+		cmd.seq_len = params->seq_len;
+	}
+	if (params->key && params->key_len > 0 &&
+	    params->key_len < sizeof(cmd.key)) {
+		os_memcpy(cmd.key, params->key, params->key_len);
+		cmd.key_len = params->key_len;
 	}
 
 	return wpa_priv_cmd(drv, PRIVSEP_CMD_SET_KEY, &cmd, sizeof(cmd),
diff --git a/src/drivers/driver_wext.c b/src/drivers/driver_wext.c
index 776eff72d..4917e864a 100644
--- a/src/drivers/driver_wext.c
+++ b/src/drivers/driver_wext.c
@@ -1810,32 +1810,27 @@  static int wpa_driver_wext_set_key_ext(void *priv, enum wpa_alg alg,
  * SIOCSIWENCODE if the extended ioctl fails when configuring a WEP key.
  */
 static int wpa_driver_wext_set_key(void *priv,
-				   struct wpa_driver_set_key_params *params)
+				   struct driver_set_key_params *params)
 {
 	struct wpa_driver_wext_data *drv = priv;
 	struct iwreq iwr;
 	int ret = 0;
-	enum wpa_alg alg = params->alg;
-	const u8 *addr = params->addr;
-	int key_idx = params->key_idx;
-	int set_tx = params->set_tx;
-	const u8 *seq = params->seq;
-	size_t seq_len = params->seq_len;
-	const u8 *key = params->key;
-	size_t key_len = params->key_len;
 
 	wpa_printf(MSG_DEBUG, "%s: alg=%d key_idx=%d set_tx=%d seq_len=%lu "
 		   "key_len=%lu",
-		   __FUNCTION__, alg, key_idx, set_tx,
-		   (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);
+		   __FUNCTION__, params->alg, params->key_idx, params->set_tx,
+		   (unsigned long) params->seq_len,
+		   (unsigned long) params->key_len);
+
+	ret = wpa_driver_wext_set_key_ext(drv, params->alg, params->addr,
+					  params->key_idx, params->set_tx,
+					  params->seq, params->seq_len,
+					  params->key, params->key_len);
 	if (ret == 0)
 		return 0;
 
 	if (ret == -2 &&
-	    (alg == WPA_ALG_NONE || alg == WPA_ALG_WEP)) {
+	    (params->alg == WPA_ALG_NONE || params->alg == WPA_ALG_WEP)) {
 		wpa_printf(MSG_DEBUG, "Driver did not support "
 			   "SIOCSIWENCODEEXT, trying SIOCSIWENCODE");
 		ret = 0;
@@ -1847,12 +1842,12 @@  static int wpa_driver_wext_set_key(void *priv,
 
 	os_memset(&iwr, 0, sizeof(iwr));
 	os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
-	iwr.u.encoding.flags = key_idx + 1;
+	iwr.u.encoding.flags = params->key_idx + 1;
 	iwr.u.encoding.flags |= IW_ENCODE_TEMP;
-	if (alg == WPA_ALG_NONE)
+	if (params->alg == WPA_ALG_NONE)
 		iwr.u.encoding.flags |= IW_ENCODE_DISABLED;
-	iwr.u.encoding.pointer = (caddr_t) key;
-	iwr.u.encoding.length = key_len;
+	iwr.u.encoding.pointer = (caddr_t) params->key;
+	iwr.u.encoding.length = params->key_len;
 
 	if (ioctl(drv->ioctl_sock, SIOCSIWENCODE, &iwr) < 0) {
 		wpa_printf(MSG_ERROR, "ioctl[SIOCSIWENCODE]: %s",
@@ -1860,10 +1855,10 @@  static int wpa_driver_wext_set_key(void *priv,
 		ret = -1;
 	}
 
-	if (set_tx && alg != WPA_ALG_NONE) {
+	if (params->set_tx && params->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;
+		iwr.u.encoding.flags = params->key_idx + 1;
 		iwr.u.encoding.flags |= IW_ENCODE_TEMP;
 		iwr.u.encoding.pointer = (caddr_t) NULL;
 		iwr.u.encoding.length = 0;
diff --git a/src/rsn_supp/tdls.c b/src/rsn_supp/tdls.c
index bb8973942..7cddc5e68 100644
--- a/src/rsn_supp/tdls.c
+++ b/src/rsn_supp/tdls.c
@@ -177,8 +177,13 @@  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, KEY_FLAG_PAIRWISE) < 0) {
+	struct driver_set_key_params params;
+
+	os_memset(&params, 0, sizeof(params));
+	params.addr = peer->addr;
+	params.key_flag = KEY_FLAG_PAIRWISE;
+
+	if (wpa_sm_set_key(sm, &params) < 0) {
 		wpa_printf(MSG_WARNING, "TDLS: Failed to delete TPK-TK from "
 			   "the driver");
 		return -1;
@@ -190,9 +195,9 @@  static int wpa_tdls_del_key(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
 
 static int wpa_tdls_set_key(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
 {
+	struct driver_set_key_params params;
 	u8 key_len;
 	u8 rsc[6];
-	enum wpa_alg alg;
 
 	if (peer->tk_set) {
 		/*
@@ -209,10 +214,11 @@  static int wpa_tdls_set_key(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
 	}
 
 	os_memset(rsc, 0, 6);
+	os_memset(&params, 0, sizeof(params));
 
 	switch (peer->cipher) {
 	case WPA_CIPHER_CCMP:
-		alg = WPA_ALG_CCMP;
+		params.alg = WPA_ALG_CCMP;
 		key_len = 16;
 		break;
 	case WPA_CIPHER_NONE:
@@ -225,11 +231,18 @@  static int wpa_tdls_set_key(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
 		return -1;
 	}
 
+	params.set_tx = 1;
+	params.addr = peer->addr;
+	params.key_idx = -1;
+	params.seq = rsc;
+	params.seq_len = sizeof(rsc);
+	params.key = peer->tpk.tk;
+	params.key_len = key_len;
+	params.key_flag = KEY_FLAG_PAIRWISE_RX_TX;
+
 	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,
-			   KEY_FLAG_PAIRWISE_RX_TX) < 0) {
+	if (wpa_sm_set_key(sm, &params) < 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 5f08d0e78..cff8daa5e 100644
--- a/src/rsn_supp/wpa.c
+++ b/src/rsn_supp/wpa.c
@@ -792,9 +792,7 @@  static int wpa_supplicant_install_ptk(struct wpa_sm *sm,
 				      const struct wpa_eapol_key *key,
 				      enum key_flag key_flag)
 {
-	int keylen, rsclen;
-	enum wpa_alg alg;
-	const u8 *key_rsc;
+	struct driver_set_key_params params;
 
 	if (sm->ptk.installed) {
 		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
@@ -818,29 +816,34 @@  static int wpa_supplicant_install_ptk(struct wpa_sm *sm,
 		return -1;
 	}
 
-	alg = wpa_cipher_to_alg(sm->pairwise_cipher);
-	keylen = wpa_cipher_key_len(sm->pairwise_cipher);
-	if (keylen <= 0 || (unsigned int) keylen != sm->ptk.tk_len) {
-		wpa_printf(MSG_DEBUG, "WPA: TK length mismatch: %d != %lu",
-			   keylen, (long unsigned int) sm->ptk.tk_len);
+	os_memset(&params, 0, sizeof(params));
+	params.set_tx = 1;
+	params.addr = sm->bssid;
+	params.alg = wpa_cipher_to_alg(sm->pairwise_cipher);
+	params.seq_len = wpa_cipher_rsc_len(sm->pairwise_cipher);
+	params.key_len = wpa_cipher_key_len(sm->pairwise_cipher);
+	params.key = sm->ptk.tk;
+	params.key_flag = KEY_FLAG_PAIRWISE | key_flag;
+
+	if (params.key_len <= 0 ||
+	    (unsigned int) params.key_len != sm->ptk.tk_len) {
+		wpa_printf(MSG_DEBUG, "WPA: TK length mismatch: %lu != %lu",
+			   params.key_len, (long unsigned int) sm->ptk.tk_len);
 		return -1;
 	}
-	rsclen = wpa_cipher_rsc_len(sm->pairwise_cipher);
 
 	if (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) {
-		key_rsc = null_rsc;
+		params.seq = null_rsc;
 	} else {
-		key_rsc = key->key_rsc;
-		wpa_hexdump(MSG_DEBUG, "WPA: RSC", key_rsc, rsclen);
+		params.seq = key->key_rsc;
+		wpa_hexdump(MSG_DEBUG, "WPA: RSC", params.seq, params.seq_len);
 	}
 
-	if (wpa_sm_set_key(sm, alg, sm->bssid, 0, 1, key_rsc, rsclen,
-			   sm->ptk.tk, keylen,
-			   KEY_FLAG_PAIRWISE | key_flag) < 0) {
+	if (wpa_sm_set_key(sm, &params) < 0) {
 		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
 			"WPA: Failed to set PTK to the "
-			"driver (alg=%d keylen=%d bssid=" MACSTR ")",
-			alg, keylen, MAC2STR(sm->bssid));
+			"driver (alg=%d keylen=%lu bssid=" MACSTR ")",
+			params.alg, params.key_len, MAC2STR(sm->bssid));
 		return -1;
 	}
 
@@ -899,6 +902,7 @@  static int wpa_supplicant_install_gtk(struct wpa_sm *sm,
 				      const struct wpa_gtk_data *gd,
 				      const u8 *key_rsc, int wnm_sleep)
 {
+	struct driver_set_key_params params;
 	const u8 *_gtk = gd->gtk;
 	u8 gtk_buf[32];
 
@@ -926,26 +930,37 @@  static int wpa_supplicant_install_gtk(struct wpa_sm *sm,
 		os_memcpy(gtk_buf + 24, gd->gtk + 16, 8);
 		_gtk = gtk_buf;
 	}
+
+	os_memset(&params, 0, sizeof(params));
+	params.alg = gd->alg;
+	params.key_idx = gd->keyidx;
+	params.seq = key_rsc;
+	params.seq_len = gd->key_rsc_len;
+	params.key = _gtk;
+	params.key_len = gd->gtk_len;
+	params.key_flag = KEY_FLAG_GROUP_RX_TX_DEFAULT;
+
 	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,
-				   KEY_FLAG_GROUP_RX_TX_DEFAULT) < 0) {
+		params.set_tx = 1;
+		if (wpa_sm_set_key(sm, &params) < 0) {
 			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
 				"WPA: Failed to set GTK to the driver "
 				"(Group only)");
 			forced_memzero(gtk_buf, sizeof(gtk_buf));
 			return -1;
 		}
-	} 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, KEY_FLAG_GROUP_RX) < 0) {
-		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
-			"WPA: Failed to set GTK to "
-			"the driver (alg=%d keylen=%d keyidx=%d)",
-			gd->alg, gd->gtk_len, gd->keyidx);
+	} else {
+		params.set_tx = gd->tx;
+		params.addr = broadcast_ether_addr;
+		params.key_flag = KEY_FLAG_GROUP_RX;
+		if (wpa_sm_set_key(sm, &params) < 0) {
+			wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
+				"WPA: Failed to set GTK to "
+				"the driver (alg=%d keylen=%d keyidx=%d)",
+				gd->alg, gd->gtk_len, gd->keyidx);
 		forced_memzero(gtk_buf, sizeof(gtk_buf));
 		return -1;
+		}
 	}
 	forced_memzero(gtk_buf, sizeof(gtk_buf));
 
@@ -1066,35 +1081,43 @@  static int wpa_supplicant_install_igtk(struct wpa_sm *sm,
 				       const struct wpa_igtk_kde *igtk,
 				       int wnm_sleep)
 {
-	size_t len = wpa_cipher_key_len(sm->mgmt_group_cipher);
-	u16 keyidx = WPA_GET_LE16(igtk->keyid);
+	struct driver_set_key_params params;
+
+	os_memset(&params, 0, sizeof(params));
+	params.key_idx = WPA_GET_LE16(igtk->keyid);
+	params.key_len = wpa_cipher_key_len(sm->mgmt_group_cipher);
 
 	/* Detect possible key reinstallation */
-	if ((sm->igtk.igtk_len == len &&
+	if ((sm->igtk.igtk_len == params.key_len &&
 	     os_memcmp(sm->igtk.igtk, igtk->igtk, sm->igtk.igtk_len) == 0) ||
-	    (sm->igtk_wnm_sleep.igtk_len == len &&
+	    (sm->igtk_wnm_sleep.igtk_len == params.key_len &&
 	     os_memcmp(sm->igtk_wnm_sleep.igtk, igtk->igtk,
 		       sm->igtk_wnm_sleep.igtk_len) == 0)) {
 		wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
 			"WPA: Not reinstalling already in-use IGTK to the driver (keyidx=%d)",
-			keyidx);
+			params.key_idx);
 		return  0;
 	}
 
 	wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
 		"WPA: IGTK keyid %d pn " COMPACT_MACSTR,
-		keyidx, MAC2STR(igtk->pn));
-	wpa_hexdump_key(MSG_DEBUG, "WPA: IGTK", igtk->igtk, len);
-	if (keyidx > 4095) {
+		params.key_idx, MAC2STR(igtk->pn));
+	wpa_hexdump_key(MSG_DEBUG, "WPA: IGTK", igtk->igtk, params.key_len);
+	if (params.key_idx > 4095) {
 		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
-			"WPA: Invalid IGTK KeyID %d", keyidx);
+			"WPA: Invalid IGTK KeyID %d", params.key_idx);
 		return -1;
 	}
-	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, KEY_FLAG_GROUP_RX) < 0) {
-		if (keyidx == 0x0400 || keyidx == 0x0500) {
+
+	params.alg = wpa_cipher_to_alg(sm->mgmt_group_cipher);
+	params.addr = broadcast_ether_addr;
+	params.seq = igtk->pn;
+	params.seq_len = sizeof(igtk->pn);
+	params.key = igtk->igtk;
+	params.key_flag = KEY_FLAG_GROUP_RX;
+
+	if (wpa_sm_set_key(sm, &params) < 0) {
+		if (params.key_idx == 0x0400 || params.key_idx == 0x0500) {
 			/* Assume the AP has broken PMF implementation since it
 			 * seems to have swapped the KeyID bytes. The AP cannot
 			 * be trusted to implement BIP correctly or provide a
@@ -1118,11 +1141,11 @@  static int wpa_supplicant_install_igtk(struct wpa_sm *sm,
 	}
 
 	if (wnm_sleep) {
-		sm->igtk_wnm_sleep.igtk_len = len;
+		sm->igtk_wnm_sleep.igtk_len = params.key_len;
 		os_memcpy(sm->igtk_wnm_sleep.igtk, igtk->igtk,
 			  sm->igtk_wnm_sleep.igtk_len);
 	} else {
-		sm->igtk.igtk_len = len;
+		sm->igtk.igtk_len = params.key_len;
 		os_memcpy(sm->igtk.igtk, igtk->igtk, sm->igtk.igtk_len);
 	}
 
@@ -4383,11 +4406,10 @@  static void fils_process_hlp_container(struct wpa_sm *sm, const u8 *pos,
 
 int fils_process_assoc_resp(struct wpa_sm *sm, const u8 *resp, size_t len)
 {
+	struct driver_set_key_params params;
 	const struct ieee80211_mgmt *mgmt;
 	const u8 *end, *ie_start;
 	struct ieee802_11_elems elems;
-	int keylen, rsclen;
-	enum wpa_alg alg;
 	struct wpa_gtk_data gd;
 	int maxkeylen;
 	struct wpa_eapol_ie_parse kde;
@@ -4566,22 +4588,29 @@  int fils_process_assoc_resp(struct wpa_sm *sm, const u8 *resp, size_t len)
 		goto fail;
 	}
 
-	alg = wpa_cipher_to_alg(sm->pairwise_cipher);
-	keylen = wpa_cipher_key_len(sm->pairwise_cipher);
-	if (keylen <= 0 || (unsigned int) keylen != sm->ptk.tk_len) {
-		wpa_printf(MSG_DEBUG, "FILS: TK length mismatch: %u != %lu",
-			   keylen, (long unsigned int) sm->ptk.tk_len);
+	os_memset(&params, 0, sizeof(params));
+	params.set_tx = 1;
+	params.addr = sm->bssid;
+	params.alg = wpa_cipher_to_alg(sm->pairwise_cipher);
+	params.key_len = wpa_cipher_key_len(sm->pairwise_cipher);
+	if (params.key_len <= 0 ||
+	    (unsigned int) params.key_len != sm->ptk.tk_len) {
+		wpa_printf(MSG_DEBUG, "FILS: TK length mismatch: %lu != %lu",
+			   params.key_len, (long unsigned int) sm->ptk.tk_len);
 		goto fail;
 	}
-	rsclen = wpa_cipher_rsc_len(sm->pairwise_cipher);
+	params.key = sm->ptk.tk;
+	params.seq = null_rsc;
+	params.seq_len = wpa_cipher_rsc_len(sm->pairwise_cipher);
+	params.key_flag = KEY_FLAG_PAIRWISE_RX_TX;
+
 	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, KEY_FLAG_PAIRWISE_RX_TX) < 0) {
+			sm->ptk.tk, params.key_len);
+	if (wpa_sm_set_key(sm, &params) < 0) {
 		wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
-			"FILS: Failed to set PTK to the driver (alg=%d keylen=%d bssid="
+			"FILS: Failed to set PTK to the driver (alg=%d keylen=%lu bssid="
 			MACSTR ")",
-			alg, keylen, MAC2STR(sm->bssid));
+			params.alg, params.key_len, MAC2STR(sm->bssid));
 		goto fail;
 	}
 
diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h
index 85fedeeae..a0aab1b4b 100644
--- a/src/rsn_supp/wpa.h
+++ b/src/rsn_supp/wpa.h
@@ -19,6 +19,7 @@  struct eapol_sm;
 struct wpa_config_blob;
 struct hostapd_freq_params;
 struct wpa_channel_info;
+struct driver_set_key_params;
 
 struct wpa_sm_ctx {
 	void *ctx; /* pointer to arbitrary upper level context */
@@ -26,11 +27,8 @@  struct wpa_sm_ctx {
 
 	void (*set_state)(void *ctx, enum wpa_states state);
 	enum wpa_states (*get_state)(void *ctx);
-	void (*deauthenticate)(void * ctx, u16 reason_code);
-	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, enum key_flag key_flag);
+	void (*deauthenticate)(void *ctx, u16 reason_code);
+	int (*set_key)(void *ctx, struct driver_set_key_params *params);
 	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 8a8c545d3..f4cb118dc 100644
--- a/src/rsn_supp/wpa_ft.c
+++ b/src/rsn_supp/wpa_ft.c
@@ -407,9 +407,10 @@  static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len,
 
 static int wpa_ft_install_ptk(struct wpa_sm *sm, const u8 *bssid)
 {
-	int keylen;
-	enum wpa_alg alg;
-	u8 null_rsc[6] = { 0, 0, 0, 0, 0, 0 };
+	struct driver_set_key_params params;
+	u8 null_rsc[6];
+
+	os_memset(&null_rsc, 0, sizeof(null_rsc));
 
 	wpa_printf(MSG_DEBUG, "FT: Installing PTK to the driver.");
 
@@ -419,12 +420,18 @@  static int wpa_ft_install_ptk(struct wpa_sm *sm, const u8 *bssid)
 		return -1;
 	}
 
-	alg = wpa_cipher_to_alg(sm->pairwise_cipher);
-	keylen = wpa_cipher_key_len(sm->pairwise_cipher);
+	os_memset(&params, 0, sizeof(params));
+
+	params.set_tx = 1;
+	params.addr = bssid;
+	params.alg = wpa_cipher_to_alg(sm->pairwise_cipher);
+	params.seq = null_rsc;
+	params.seq_len = sizeof(null_rsc);
+	params.key = (u8 *) sm->ptk.tk;
+	params.key_len = wpa_cipher_key_len(sm->pairwise_cipher);
+	params.key_flag = KEY_FLAG_PAIRWISE_RX_TX;
 
-	if (wpa_sm_set_key(sm, alg, bssid, 0, 1, null_rsc, sizeof(null_rsc),
-			   (u8 *) sm->ptk.tk, keylen,
-			   KEY_FLAG_PAIRWISE_RX_TX) < 0) {
+	if (wpa_sm_set_key(sm, &params) < 0) {
 		wpa_printf(MSG_WARNING, "FT: Failed to set PTK to the driver");
 		return -1;
 	}
@@ -704,13 +711,15 @@  void wpa_reset_ft_completed(struct wpa_sm *sm)
 static int wpa_ft_process_gtk_subelem(struct wpa_sm *sm, const u8 *gtk_elem,
 				      size_t gtk_elem_len)
 {
+	struct driver_set_key_params params;
 	u8 gtk[32];
-	int keyidx;
-	enum wpa_alg alg;
-	size_t gtk_len, keylen, rsc_len;
+	size_t gtk_len;
 	const u8 *kek;
 	size_t kek_len;
 
+	os_memset(&params, 0, sizeof(params));
+
+
 	if (wpa_key_mgmt_fils(sm->key_mgmt)) {
 		kek = sm->ptk.kek2;
 		kek_len = sm->ptk.kek2_len;
@@ -740,32 +749,33 @@  static int wpa_ft_process_gtk_subelem(struct wpa_sm *sm, const u8 *gtk_elem,
 		return -1;
 	}
 
-	keylen = wpa_cipher_key_len(sm->group_cipher);
-	rsc_len = wpa_cipher_rsc_len(sm->group_cipher);
-	alg = wpa_cipher_to_alg(sm->group_cipher);
-	if (alg == WPA_ALG_NONE) {
+	params.key_len = wpa_cipher_key_len(sm->group_cipher);
+	params.seq_len = wpa_cipher_rsc_len(sm->group_cipher);
+	params.alg = wpa_cipher_to_alg(sm->group_cipher);
+	if (params.alg == WPA_ALG_NONE) {
 		wpa_printf(MSG_WARNING, "WPA: Unsupported Group Cipher %d",
 			   sm->group_cipher);
 		return -1;
 	}
 
-	if (gtk_len < keylen) {
+	if (gtk_len < params.key_len) {
 		wpa_printf(MSG_DEBUG, "FT: Too short GTK in FTIE");
 		return -1;
 	}
 
 	/* Key Info[2] | Key Length[1] | RSC[8] | Key[5..32]. */
 
-	keyidx = WPA_GET_LE16(gtk_elem) & 0x03;
+	params.key_idx = WPA_GET_LE16(gtk_elem) & 0x03;
 
-	if (gtk_elem[2] != keylen) {
+	if (gtk_elem[2] != params.key_len) {
 		wpa_printf(MSG_DEBUG, "FT: GTK length mismatch: received %d "
 			   "negotiated %lu",
-			   gtk_elem[2], (unsigned long) keylen);
+			   gtk_elem[2], (unsigned long) params.key_len);
 		return -1;
 	}
 
-	wpa_hexdump_key(MSG_DEBUG, "FT: GTK from Reassoc Resp", gtk, keylen);
+	wpa_hexdump_key(MSG_DEBUG, "FT: GTK from Reassoc Resp",
+			gtk, params.key_len);
 	if (sm->group_cipher == WPA_CIPHER_TKIP) {
 		/* Swap Tx/Rx keys for Michael MIC */
 		u8 tmp[8];
@@ -773,9 +783,13 @@  static int wpa_ft_process_gtk_subelem(struct wpa_sm *sm, const u8 *gtk_elem,
 		os_memcpy(gtk + 16, gtk + 24, 8);
 		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,
-			   KEY_FLAG_GROUP_RX) < 0) {
+
+	params.addr = broadcast_ether_addr;
+	params.seq = gtk_elem + 3;
+	params.key = gtk;
+	params.key_flag = KEY_FLAG_GROUP_RX;
+
+	if (wpa_sm_set_key(sm, &params) < 0) {
 		wpa_printf(MSG_WARNING, "WPA: Failed to set GTK to the "
 			   "driver.");
 		return -1;
@@ -788,9 +802,8 @@  static int wpa_ft_process_gtk_subelem(struct wpa_sm *sm, const u8 *gtk_elem,
 static int wpa_ft_process_igtk_subelem(struct wpa_sm *sm, const u8 *igtk_elem,
 				       size_t igtk_elem_len)
 {
+	struct driver_set_key_params params;
 	u8 igtk[WPA_IGTK_MAX_LEN];
-	size_t igtk_len;
-	u16 keyidx;
 	const u8 *kek;
 	size_t kek_len;
 
@@ -816,19 +829,21 @@  static int wpa_ft_process_igtk_subelem(struct wpa_sm *sm, const u8 *igtk_elem,
 	wpa_hexdump_key(MSG_DEBUG, "FT: Received IGTK in Reassoc Resp",
 			igtk_elem, igtk_elem_len);
 
-	igtk_len = wpa_cipher_key_len(sm->mgmt_group_cipher);
-	if (igtk_elem_len != 2 + 6 + 1 + igtk_len + 8) {
+	os_memset(&params, 0, sizeof(params));
+	params.key_len = wpa_cipher_key_len(sm->mgmt_group_cipher);
+
+	if (igtk_elem_len != 2 + 6 + 1 + params.key_len + 8) {
 		wpa_printf(MSG_DEBUG, "FT: Invalid IGTK sub-elem "
 			   "length %lu", (unsigned long) igtk_elem_len);
 		return -1;
 	}
-	if (igtk_elem[8] != igtk_len) {
+	if (igtk_elem[8] != params.key_len) {
 		wpa_printf(MSG_DEBUG, "FT: Invalid IGTK sub-elem Key Length "
 			   "%d", igtk_elem[8]);
 		return -1;
 	}
 
-	if (aes_unwrap(kek, kek_len, igtk_len / 8, igtk_elem + 9, igtk)) {
+	if (aes_unwrap(kek, kek_len, params.key_len / 8, igtk_elem + 9, igtk)) {
 		wpa_printf(MSG_WARNING, "FT: AES unwrap failed - could not "
 			   "decrypt IGTK");
 		return -1;
@@ -836,14 +851,17 @@  static int wpa_ft_process_igtk_subelem(struct wpa_sm *sm, const u8 *igtk_elem,
 
 	/* KeyID[2] | IPN[6] | Key Length[1] | Key[16+8] */
 
-	keyidx = WPA_GET_LE16(igtk_elem);
-
-	wpa_hexdump_key(MSG_DEBUG, "FT: IGTK from Reassoc Resp", igtk,
-			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,
-			   KEY_FLAG_GROUP_RX) < 0) {
+	params.addr = broadcast_ether_addr;
+	params.alg = wpa_cipher_to_alg(sm->mgmt_group_cipher);
+	params.seq = igtk_elem + 2;
+	params.seq_len = 6;
+	params.key = igtk;
+	params.key_idx = WPA_GET_LE16(igtk_elem);
+	params.key_flag = KEY_FLAG_GROUP_RX;
+
+	wpa_hexdump_key(MSG_DEBUG, "FT: IGTK from Reassoc Resp",
+			params.key, params.key_len);
+	if (wpa_sm_set_key(sm, &params) < 0) {
 		wpa_printf(MSG_WARNING, "WPA: Failed to set IGTK to the "
 			   "driver.");
 		forced_memzero(igtk, sizeof(igtk));
diff --git a/src/rsn_supp/wpa_i.h b/src/rsn_supp/wpa_i.h
index 7d7c06ef2..3991e7b63 100644
--- a/src/rsn_supp/wpa_i.h
+++ b/src/rsn_supp/wpa_i.h
@@ -195,15 +195,11 @@  static inline void wpa_sm_deauthenticate(struct wpa_sm *sm, u16 reason_code)
 	sm->ctx->deauthenticate(sm->ctx->ctx, 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,
-				 enum key_flag key_flag)
+static inline int wpa_sm_set_key(struct wpa_sm *sm,
+				 struct driver_set_key_params *params)
 {
 	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, key_flag);
+	return sm->ctx->set_key(sm->ctx->ctx, params);
 }
 
 static inline void * wpa_sm_get_network_ctx(struct wpa_sm *sm)
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index 65dcb90f1..27c22110c 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -5343,23 +5343,19 @@  static void wpa_supplicant_ctrl_iface_bss_flush(
 #ifdef CONFIG_TESTING_OPTIONS
 static void wpa_supplicant_ctrl_iface_drop_sa(struct wpa_supplicant *wpa_s)
 {
+	struct driver_set_key_params params;
+
 	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, KEY_FLAG_GROUP);
-	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 1, 0, NULL, 0, NULL,
-			0, KEY_FLAG_GROUP);
-	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 2, 0, NULL, 0, NULL,
-			0, KEY_FLAG_GROUP);
-	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 3, 0, NULL, 0, NULL,
-			0, KEY_FLAG_GROUP);
-	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 4, 0, NULL, 0, NULL,
-			0, KEY_FLAG_GROUP);
-	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 5, 0, NULL, 0, NULL,
-			0, KEY_FLAG_GROUP);
-
-	wpa_drv_set_key(wpa_s, WPA_ALG_NONE, wpa_s->bssid, 0, 0, NULL, 0, NULL,
-			0, KEY_FLAG_PAIRWISE);
+	os_memset(&params, 0, sizeof(params));
+	params.key_flag = KEY_FLAG_GROUP;
+	for (; params.key_idx <= 5; params.key_idx++)
+		/* MLME-DELETEKEYS.request */
+		wpa_drv_set_key(wpa_s, &params);
+
+	params.addr = wpa_s->bssid;
+	params.key_idx = 0;
+	params.key_flag = KEY_FLAG_PAIRWISE;
+	wpa_drv_set_key(wpa_s, &params);
 	/* MLME-SETPROTECTION.request(None) */
 	wpa_drv_mlme_setprotection(wpa_s, wpa_s->bssid,
 				   MLME_SETPROTECTION_PROTECT_TYPE_NONE,
@@ -9345,6 +9341,7 @@  static int wpas_ctrl_test_assoc_ie(struct wpa_supplicant *wpa_s,
 
 static int wpas_ctrl_reset_pn(struct wpa_supplicant *wpa_s)
 {
+	struct driver_set_key_params params;
 	u8 zero[WPA_TK_MAX_LEN];
 
 	if (wpa_s->last_tk_alg == WPA_ALG_NONE)
@@ -9352,20 +9349,24 @@  static int wpas_ctrl_reset_pn(struct wpa_supplicant *wpa_s)
 
 	wpa_printf(MSG_INFO, "TESTING: Reset PN");
 	os_memset(zero, 0, sizeof(zero));
+	os_memset(&params, 0, sizeof(params));
+	params.set_tx = 1;
+	params.alg = wpa_s->last_tk_alg;
+	params.addr = wpa_s->last_tk_addr;
+	params.key_idx = wpa_s->last_tk_key_idx;
+	params.seq = params.key = zero;
+	params.seq_len = 6;
+	params.key_len = wpa_s->last_tk_len;
+	params.key_flag = KEY_FLAG_PAIRWISE_RX_TX;
 
 	/* First, use a zero key to avoid any possible duplicate key avoidance
 	 * 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,
-			    KEY_FLAG_PAIRWISE_RX_TX) < 0)
+	if (wpa_drv_set_key(wpa_s, &params) < 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,
-			       KEY_FLAG_PAIRWISE_RX_TX);
+	params.key = wpa_s->last_tk;
+	return wpa_drv_set_key(wpa_s, &params);
 }
 
 
diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h
index 45b62bdea..f06240681 100644
--- a/wpa_supplicant/driver_i.h
+++ b/wpa_supplicant/driver_i.h
@@ -144,34 +144,17 @@  static inline int wpa_drv_get_ssid(struct wpa_supplicant *wpa_s, u8 *ssid)
 }
 
 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,
-				  enum key_flag key_flag)
-{
-	struct wpa_driver_set_key_params params;
-
-	os_memset(&params, 0, sizeof(params));
-	params.ifname = wpa_s->ifname;
-	params.alg = alg;
-	params.addr = addr;
-	params.key_idx = key_idx;
-	params.set_tx = set_tx;
-	params.seq = seq;
-	params.seq_len = seq_len;
-	params.key = key;
-	params.key_len = key_len;
-	params.key_flag = key_flag;
-
-	if (alg != WPA_ALG_NONE) {
-		if (key_idx >= 0 && key_idx <= 6)
-			wpa_s->keys_cleared &= ~BIT(key_idx);
+				  struct driver_set_key_params *params)
+{
+	if (params->alg != WPA_ALG_NONE) {
+		if (params->key_idx >= 0 && params->key_idx <= 6)
+			wpa_s->keys_cleared &= ~BIT(params->key_idx);
 		else
 			wpa_s->keys_cleared = 0;
 	}
 	if (wpa_s->driver->set_key) {
-		return wpa_s->driver->set_key(wpa_s->drv_priv, &params);
+		params->ifname = wpa_s->ifname;
+		return wpa_s->driver->set_key(wpa_s->drv_priv, params);
 	}
 	return -1;
 }
diff --git a/wpa_supplicant/ibss_rsn.c b/wpa_supplicant/ibss_rsn.c
index 37368c4cb..9855845a7 100644
--- a/wpa_supplicant/ibss_rsn.c
+++ b/wpa_supplicant/ibss_rsn.c
@@ -143,20 +143,20 @@  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, enum key_flag key_flag)
+static int supp_set_key(void *ctx, struct driver_set_key_params *params)
 {
 	struct ibss_rsn_peer *peer = ctx;
 
 	wpa_printf(MSG_DEBUG, "SUPP: %s(alg=%d addr=" MACSTR " key_idx=%d "
 		   "set_tx=%d)",
-		   __func__, alg, MAC2STR(addr), key_idx, set_tx);
-	wpa_hexdump(MSG_DEBUG, "SUPP: set_key - seq", seq, seq_len);
-	wpa_hexdump_key(MSG_DEBUG, "SUPP: set_key - key", key, key_len);
-
-	if (key_idx == 0) {
+		   __func__, params->alg, MAC2STR(params->addr),
+		   params->key_idx, params->set_tx);
+	wpa_hexdump(MSG_DEBUG, "SUPP: set_key - seq",
+		    params->seq, params->seq_len);
+	wpa_hexdump_key(MSG_DEBUG, "SUPP: set_key - key",
+			params->key, params->key_len);
+
+	if (params->key_idx == 0) {
 		peer->authentication_status |= IBSS_RSN_SET_PTK_SUPP;
 		ibss_check_rsn_completed(peer);
 		/*
@@ -170,10 +170,9 @@  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, key_flag);
+	if (is_broadcast_ether_addr(params->addr))
+		params->addr = peer->addr;
+	return wpa_drv_set_key(peer->ibss_rsn->wpa_s, params);
 }
 
 
@@ -305,29 +304,39 @@  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,
-			enum key_flag key_flag)
+static int auth_set_key(void *ctx, struct wpa_set_key_params *wpa_params)
 {
+	struct driver_set_key_params params;
 	struct ibss_rsn *ibss_rsn = ctx;
 	u8 seq[6];
 
 	os_memset(seq, 0, sizeof(seq));
-
-	if (addr) {
+	os_memset(&params, 0, sizeof(params));
+	params.set_tx = 1;
+	params.addr = wpa_params->addr;
+	params.alg = wpa_params->alg;
+	params.key_idx = wpa_params->key_idx;
+	params.seq = seq;
+	params.seq_len = 6;
+	params.key = wpa_params->key;
+	params.key_len = wpa_params->key_len;
+
+	if (params.addr) {
 		wpa_printf(MSG_DEBUG, "AUTH: %s(alg=%d addr=" MACSTR
 			   " key_idx=%d)",
-			   __func__, alg, MAC2STR(addr), idx);
+			   __func__, params.alg, MAC2STR(params.addr),
+			   params.key_idx);
 	} else {
 		wpa_printf(MSG_DEBUG, "AUTH: %s(alg=%d key_idx=%d)",
-			   __func__, alg, idx);
+			   __func__, params.alg, params.key_idx);
 	}
-	wpa_hexdump_key(MSG_DEBUG, "AUTH: set_key - key", key, key_len);
+	wpa_hexdump_key(MSG_DEBUG, "AUTH: set_key - key",
+			params.key, params.key_len);
 
-	if (idx == 0) {
-		if (addr) {
+	if (params.key_idx == 0) {
+		if (params.addr) {
 			struct ibss_rsn_peer *peer;
-			peer = ibss_rsn_get_peer(ibss_rsn, addr);
+			peer = ibss_rsn_get_peer(ibss_rsn, params.addr);
 			if (peer) {
 				peer->authentication_status |=
 					IBSS_RSN_SET_PTK_AUTH;
@@ -338,15 +347,15 @@  static int auth_set_key(void *ctx, int vlan_id, enum wpa_alg alg,
 		 * In IBSS RSN, the pairwise key from the 4-way handshake
 		 * initiated by the peer with highest MAC address is used.
 		 */
-		if (addr == NULL ||
-		    os_memcmp(ibss_rsn->wpa_s->own_addr, addr, ETH_ALEN) < 0) {
+		if (params.addr == NULL ||
+		    os_memcmp(ibss_rsn->wpa_s->own_addr,
+			      params.addr, ETH_ALEN) < 0) {
 			wpa_printf(MSG_DEBUG, "AUTH: Do not use this PTK");
 			return 0;
 		}
 	}
 
-	return wpa_drv_set_key(ibss_rsn->wpa_s, alg, addr, idx,
-			       1, seq, 6, key, key_len, key_flag);
+	return wpa_drv_set_key(ibss_rsn->wpa_s, &params);
 }
 
 
@@ -847,6 +856,7 @@  static void ibss_rsn_handle_auth_1_of_2(struct ibss_rsn *ibss_rsn,
 					struct ibss_rsn_peer *peer,
 					const u8* addr)
 {
+	struct driver_set_key_params params;
 	wpa_printf(MSG_DEBUG, "RSN: IBSS RX Auth frame (SEQ 1) from " MACSTR,
 		   MAC2STR(addr));
 
@@ -856,10 +866,12 @@  static void ibss_rsn_handle_auth_1_of_2(struct ibss_rsn *ibss_rsn,
 		/* Clear the TK for this pair to allow recovery from the case
 		 * where the peer STA has restarted and lost its key while we
 		 * still have a pairwise key configured. */
+		os_memset(&params, 0, sizeof(params));
+		params.addr = addr;
+		params.key_flag = KEY_FLAG_PAIRWISE;
 		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, KEY_FLAG_PAIRWISE);
+		wpa_drv_set_key(ibss_rsn->wpa_s, &params);
 	}
 
 	if (peer &&
diff --git a/wpa_supplicant/mesh_mpm.c b/wpa_supplicant/mesh_mpm.c
index 31dd1d3c6..4b075a396 100644
--- a/wpa_supplicant/mesh_mpm.c
+++ b/wpa_supplicant/mesh_mpm.c
@@ -866,42 +866,58 @@  void mesh_mpm_mgmt_rx(struct wpa_supplicant *wpa_s, struct rx_mgmt *rx_mgmt)
 static void mesh_mpm_plink_estab(struct wpa_supplicant *wpa_s,
 				 struct sta_info *sta)
 {
+	struct driver_set_key_params params;
 	struct hostapd_data *hapd = wpa_s->ifmsh->bss[0];
 	struct mesh_conf *conf = wpa_s->ifmsh->mconf;
-	u8 seq[6] = {};
+	u8 seq[6];
+
+	os_memset(seq, 0, sizeof(seq));
+	os_memset(&params, 0, sizeof(params));
+	params.addr = sta->addr;
 
 	wpa_msg(wpa_s, MSG_INFO, "mesh plink with " MACSTR " established",
 		MAC2STR(sta->addr));
 
 	if (conf->security & MESH_CONF_SEC_AMPE) {
-		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,
-				KEY_FLAG_PAIRWISE_RX_TX);
+		params.alg = wpa_cipher_to_alg(conf->pairwise_cipher);
+		params.seq = seq;
+		params.seq_len = sizeof(seq);
+		params.key = sta->mtk;
+		params.key_len = sta->mtk_len;
+		params.key_flag = KEY_FLAG_PAIRWISE_RX_TX;
+
+		wpa_hexdump_key(MSG_DEBUG, "mesh: MTK",
+				params.key, params.key_len);
+		wpa_drv_set_key(wpa_s, &params);
+
+		params.alg = wpa_cipher_to_alg(conf->group_cipher);
+		params.key_idx = sta->mgtk_key_id;
+		params.seq = sta->mgtk_rsc;
+		params.seq_len = sizeof(sta->mgtk_rsc);
+		params.key = sta->mgtk;
+		params.key_len = sta->mgtk_len;
+		params.key_flag = KEY_FLAG_GROUP_RX;
 
 		wpa_hexdump_key(MSG_DEBUG, "mesh: RX MGTK Key RSC",
-				sta->mgtk_rsc, sizeof(sta->mgtk_rsc));
+				params.seq, params.seq_len);
 		wpa_hexdump_key(MSG_DEBUG, "mesh: RX MGTK",
-				sta->mgtk, sta->mgtk_len);
-		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,
-				KEY_FLAG_GROUP_RX);
+				params.key, params.key_len);
+		wpa_drv_set_key(wpa_s, &params);
 
 		if (sta->igtk_len) {
+			params.alg = wpa_cipher_to_alg(conf->mgmt_group_cipher);
+			params.key_idx = sta->igtk_key_id;
+			params.seq = sta->igtk_rsc;
+			params.seq_len = sizeof(sta->igtk_rsc);
+			params.key = sta->igtk;
+			params.key_len = sta->igtk_len;
+			params.key_flag = KEY_FLAG_GROUP_RX;
+
 			wpa_hexdump_key(MSG_DEBUG, "mesh: RX IGTK Key RSC",
-					sta->igtk_rsc, sizeof(sta->igtk_rsc));
+					params.seq, params.seq_len);
 			wpa_hexdump_key(MSG_DEBUG, "mesh: RX IGTK",
-					sta->igtk, sta->igtk_len);
-			wpa_drv_set_key(
-				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,
-				KEY_FLAG_GROUP_RX);
+					params.key, params.key_len);
+			wpa_drv_set_key(wpa_s, &params);
 		}
 	}
 
diff --git a/wpa_supplicant/mesh_rsn.c b/wpa_supplicant/mesh_rsn.c
index f19bfbfc6..d712c8423 100644
--- a/wpa_supplicant/mesh_rsn.c
+++ b/wpa_supplicant/mesh_rsn.c
@@ -99,27 +99,36 @@  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,
-			enum key_flag key_flag)
+static int auth_set_key(void *ctx, struct wpa_set_key_params *wpa_params)
 {
+	struct driver_set_key_params params;
 	struct mesh_rsn *mesh_rsn = ctx;
 	u8 seq[6];
 
 	os_memset(seq, 0, sizeof(seq));
-
-	if (addr) {
+	os_memset(&params, 0, sizeof(params));
+	params.set_tx = 1;
+	params.addr = wpa_params->addr;
+	params.alg = wpa_params->alg;
+	params.key_idx = wpa_params->key_idx;
+	params.seq = seq;
+	params.seq_len = 6;
+	params.key = wpa_params->key;
+	params.key_len = wpa_params->key_len;
+
+	if (params.addr) {
 		wpa_printf(MSG_DEBUG, "AUTH: %s(alg=%d addr=" MACSTR
 			   " key_idx=%d)",
-			   __func__, alg, MAC2STR(addr), idx);
+			   __func__, params.alg, MAC2STR(params.addr),
+			   params.key_idx);
 	} else {
 		wpa_printf(MSG_DEBUG, "AUTH: %s(alg=%d key_idx=%d)",
-			   __func__, alg, idx);
+			   __func__, params.alg, params.key_idx);
 	}
-	wpa_hexdump_key(MSG_DEBUG, "AUTH: set_key - key", key, key_len);
+	wpa_hexdump_key(MSG_DEBUG, "AUTH: set_key - key",
+			params.key, params.key_len);
 
-	return wpa_drv_set_key(mesh_rsn->wpa_s, alg, addr, idx,
-			       1, seq, 6, key, key_len, key_flag);
+	return wpa_drv_set_key(mesh_rsn->wpa_s, &params);
 }
 
 
@@ -145,6 +154,7 @@  static int auth_start_ampe(void *ctx, const u8 *addr)
 static int __mesh_rsn_auth_init(struct mesh_rsn *rsn, const u8 *addr,
 				enum mfp_options ieee80211w, int ocv)
 {
+	struct driver_set_key_params params;
 	struct wpa_auth_config conf;
 	static const struct wpa_auth_callbacks cb = {
 		.logger = auth_logger,
@@ -152,7 +162,9 @@  static int __mesh_rsn_auth_init(struct mesh_rsn *rsn, const u8 *addr,
 		.set_key = auth_set_key,
 		.start_ampe = auth_start_ampe,
 	};
-	u8 seq[6] = {};
+	u8 seq[6];
+
+	os_memset(seq, 0, sizeof(seq));
 
 	wpa_printf(MSG_DEBUG, "AUTH: Initializing group state machine");
 
@@ -185,6 +197,11 @@  static int __mesh_rsn_auth_init(struct mesh_rsn *rsn, const u8 *addr,
 		return -1;
 	rsn->mgtk_key_id = 1;
 
+	os_memset(&params, 0, sizeof(params));
+	params.set_tx = 1;
+	params.seq = seq;
+	params.seq_len = sizeof(seq);
+
 	if (ieee80211w != NO_MGMT_FRAME_PROTECTION) {
 		rsn->igtk_len = wpa_cipher_key_len(conf.group_mgmt_cipher);
 		if (random_get_bytes(rsn->igtk, rsn->igtk_len) < 0)
@@ -192,21 +209,27 @@  static int __mesh_rsn_auth_init(struct mesh_rsn *rsn, const u8 *addr,
 		rsn->igtk_key_id = 4;
 
 		/* group mgmt */
+		params.alg = wpa_cipher_to_alg(rsn->mgmt_group_cipher);
+		params.key_idx = rsn->igtk_key_id;
+		params.key = rsn->igtk;
+		params.key_len = rsn->igtk_len;
+		params.key_flag = KEY_FLAG_GROUP_TX_DEFAULT;
+
 		wpa_hexdump_key(MSG_DEBUG, "mesh: Own TX IGTK",
-				rsn->igtk, rsn->igtk_len);
-		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,
-				KEY_FLAG_GROUP_TX_DEFAULT);
+				params.key, params.key_len);
+		wpa_drv_set_key(rsn->wpa_s, &params);
 	}
 
 	/* group privacy / data frames */
+	params.alg = wpa_cipher_to_alg(rsn->group_cipher);
+	params.key_idx = rsn->mgtk_key_id;
+	params.key = rsn->mgtk;
+	params.key_len = rsn->mgtk_len;
+	params.key_flag = KEY_FLAG_GROUP_TX_DEFAULT;
+
 	wpa_hexdump_key(MSG_DEBUG, "mesh: Own TX MGTK",
 			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, KEY_FLAG_GROUP_TX_DEFAULT);
+	wpa_drv_set_key(rsn->wpa_s, &params);
 
 	return 0;
 }
diff --git a/wpa_supplicant/wpa_priv.c b/wpa_supplicant/wpa_priv.c
index f42840610..4c8388150 100644
--- a/wpa_supplicant/wpa_priv.c
+++ b/wpa_supplicant/wpa_priv.c
@@ -391,7 +391,7 @@  static void wpa_priv_cmd_set_key(struct wpa_priv_interface *iface,
 {
 	struct privsep_cmd_set_key *params;
 	int res;
-	struct wpa_driver_set_key_params p;
+	struct driver_set_key_params p;
 
 	if (iface->drv_priv == NULL || iface->driver->set_key == NULL)
 		return;
@@ -413,6 +413,7 @@  static void wpa_priv_cmd_set_key(struct wpa_priv_interface *iface,
 	p.seq_len = params->seq_len;
 	p.key = params->key_len ? params->key : NULL;
 	p.key_len = params->key_len;
+	p.key_flag = params->key_flag;
 
 	res = iface->driver->set_key(iface->drv_priv, &p);
 	wpa_printf(MSG_DEBUG, "drv->set_key: res=%d", res);
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 9f3d6ef60..f17b43fe2 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -133,19 +133,27 @@  static void wpas_update_owe_connect_params(struct wpa_supplicant *wpa_s);
 /* Configure default/group WEP keys for static WEP */
 int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
 {
-	int i, set = 0;
+	struct driver_set_key_params params;
+	int set = 0;
 
-	for (i = 0; i < NUM_WEP_KEYS; i++) {
-		if (ssid->wep_key_len[i] == 0)
+	os_memset(&params, 0, sizeof(params));
+	params.alg = WPA_ALG_WEP;
+
+
+	for (; params.key_idx < NUM_WEP_KEYS; params.key_idx++) {
+		if (ssid->wep_key_len[params.key_idx] == 0)
 			continue;
 
 		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],
-				i == ssid->wep_tx_keyidx ?
-				KEY_FLAG_GROUP_RX_TX_DEFAULT :
-				KEY_FLAG_GROUP_RX_TX);
+		if (params.key_idx == ssid->wep_tx_keyidx) {
+			params.set_tx = 1;
+			params.key_flag = KEY_FLAG_GROUP_RX_TX_DEFAULT;
+		} else {
+			params.key_flag = KEY_FLAG_GROUP_RX_TX;
+		}
+		params.key = ssid->wep_key[params.key_idx];
+		params.key_len = ssid->wep_key_len[params.key_idx];
+		wpa_drv_set_key(wpa_s, &params);
 	}
 
 	return set;
@@ -155,12 +163,13 @@  int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
 int wpa_supplicant_set_wpa_none_key(struct wpa_supplicant *wpa_s,
 				    struct wpa_ssid *ssid)
 {
+	struct driver_set_key_params params;
 	u8 key[32];
-	size_t keylen;
-	enum wpa_alg alg;
-	u8 seq[6] = { 0 };
+	u8 seq[6];
 	int ret;
 
+	os_memset(seq, 0, sizeof(seq));
+
 	/* IBSS/WPA-None uses only one key (Group) for both receiving and
 	 * sending unicast and multicast packets. */
 
@@ -176,23 +185,25 @@  int wpa_supplicant_set_wpa_none_key(struct wpa_supplicant *wpa_s,
 		return -1;
 	}
 
+	os_memset(&params, 0, sizeof(params));
+
 	switch (wpa_s->group_cipher) {
 	case WPA_CIPHER_CCMP:
 		os_memcpy(key, ssid->psk, 16);
-		keylen = 16;
-		alg = WPA_ALG_CCMP;
+		params.key_len = 16;
+		params.alg = WPA_ALG_CCMP;
 		break;
 	case WPA_CIPHER_GCMP:
 		os_memcpy(key, ssid->psk, 16);
-		keylen = 16;
-		alg = WPA_ALG_GCMP;
+		params.key_len = 16;
+		params.alg = WPA_ALG_GCMP;
 		break;
 	case WPA_CIPHER_TKIP:
 		/* WPA-None uses the same Michael MIC key for both TX and RX */
 		os_memcpy(key, ssid->psk, 16 + 8);
 		os_memcpy(key + 16 + 8, ssid->psk + 16, 8);
-		keylen = 32;
-		alg = WPA_ALG_TKIP;
+		params.key_len = 32;
+		params.alg = WPA_ALG_TKIP;
 		break;
 	default:
 		wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid group cipher %d for "
@@ -200,11 +211,15 @@  int wpa_supplicant_set_wpa_none_key(struct wpa_supplicant *wpa_s,
 		return -1;
 	}
 
+	params.set_tx = 1;
+	params.seq = seq;
+	params.seq_len = 6;
+	params.key = key;
+
 	/* 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,
-			      KEY_FLAG_GROUP_RX_TX_DEFAULT);
+	ret = wpa_drv_set_key(wpa_s, &params);
 	os_memset(key, 0, sizeof(key));
 	return ret;
 }
@@ -731,19 +746,24 @@  static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
  */
 void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr)
 {
-	int i, max = 6;
+	struct driver_set_key_params params;
+	int max = 6;
 
 	/* MLME-DELETEKEYS.request */
-	for (i = 0; i < max; i++) {
-		if (wpa_s->keys_cleared & BIT(i))
+	os_memset(&params, 0, sizeof(params));
+	params.key_flag = KEY_FLAG_GROUP;
+
+	for (; params.key_idx < max; params.key_idx++) {
+		if (wpa_s->keys_cleared & BIT(params.key_idx))
 			continue;
-		wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, i, 0, NULL, 0,
-				NULL, 0, KEY_FLAG_GROUP);
+		wpa_drv_set_key(wpa_s, &params);
 	}
 	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, KEY_FLAG_PAIRWISE);
+		params.addr = addr;
+		params.key_idx = 0;
+		params.key_flag = KEY_FLAG_PAIRWISE;
+		wpa_drv_set_key(wpa_s, &params);
 		/* 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 9d5d35607..9dcf50b5f 100644
--- a/wpa_supplicant/wpas_glue.c
+++ b/wpa_supplicant/wpas_glue.c
@@ -239,7 +239,9 @@  static int wpa_supplicant_eapol_send(void *ctx, int type, const u8 *buf,
 static int wpa_eapol_set_wep_key(void *ctx, int unicast, int keyidx,
 				 const u8 *key, size_t keylen)
 {
+	struct driver_set_key_params params;
 	struct wpa_supplicant *wpa_s = ctx;
+
 	if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
 		int cipher = (keylen == 5) ? WPA_CIPHER_WEP40 :
 			WPA_CIPHER_WEP104;
@@ -248,11 +250,18 @@  static int wpa_eapol_set_wep_key(void *ctx, int unicast, int keyidx,
 		else
 			wpa_s->group_cipher = cipher;
 	}
-	return wpa_drv_set_key(wpa_s, WPA_ALG_WEP,
-			       unicast ? wpa_s->bssid : NULL,
-			       keyidx, unicast, NULL, 0, key, keylen,
-			       unicast ? KEY_FLAG_PAIRWISE_RX_TX :
-			       KEY_FLAG_GROUP_RX_TX_DEFAULT);
+
+	os_memset(&params, 0, sizeof(params));
+	params.set_tx = unicast;
+	params.addr = unicast ? wpa_s->bssid : NULL;
+	params.alg = WPA_ALG_WEP;
+	params.key_idx = keyidx;
+	params.key = key;
+	params.key_len = keylen;
+	params.key_flag = unicast ? KEY_FLAG_PAIRWISE_RX_TX :
+				    KEY_FLAG_GROUP_RX_TX_DEFAULT;
+
+	return wpa_drv_set_key(wpa_s, &params);
 }
 
 
@@ -281,6 +290,7 @@  static void wpa_supplicant_eapol_cb(struct eapol_sm *eapol,
 				    enum eapol_supp_result result,
 				    void *ctx)
 {
+	struct driver_set_key_params params;
 	struct wpa_supplicant *wpa_s = ctx;
 	int res, pmk_len;
 	u8 pmk[PMK_LEN];
@@ -350,10 +360,14 @@  static void wpa_supplicant_eapol_cb(struct eapol_sm *eapol,
 	wpa_hexdump_key(MSG_DEBUG, "RSN: Configure PMK for driver-based 4-way "
 			"handshake", pmk, pmk_len);
 
-	if (wpa_drv_set_key(wpa_s, WPA_ALG_PMK, NULL, 0, 0, NULL, 0, pmk,
-			    pmk_len, KEY_FLAG_PMK)) {
+	os_memset(&params, 0, sizeof(params));
+	params.alg = WPA_ALG_PMK;
+	params.key = pmk;
+	params.key_len = pmk_len;
+	params.key_flag = KEY_FLAG_PMK;
+
+	if (wpa_drv_set_key(wpa_s, &params))
 		wpa_printf(MSG_DEBUG, "Failed to set PMK to the driver");
-	}
 
 	wpa_supplicant_cancel_scan(wpa_s);
 	wpa_supplicant_cancel_auth_timeout(wpa_s);
@@ -499,36 +513,36 @@  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,
-				  enum key_flag key_flag)
+static int wpa_supplicant_set_key(void *_wpa_s,
+				  struct driver_set_key_params *params)
 {
 	struct wpa_supplicant *wpa_s = _wpa_s;
-	if (alg == WPA_ALG_TKIP && key_idx == 0 && key_len == 32) {
+
+	if (params->alg == WPA_ALG_TKIP &&
+	    params->key_idx == 0 && params->key_len == 32) {
 		/* Clear the MIC error counter when setting a new PTK. */
 		wpa_s->mic_errors_seen = 0;
 	}
 #ifdef CONFIG_TESTING_GET_GTK
-	if (key_idx > 0 && addr && is_broadcast_ether_addr(addr) &&
-	    alg != WPA_ALG_NONE && key_len <= sizeof(wpa_s->last_gtk)) {
-		os_memcpy(wpa_s->last_gtk, key, key_len);
-		wpa_s->last_gtk_len = key_len;
+	if (params->key_idx > 0 && params->addr &&
+	    is_broadcast_ether_addr(params->addr) &&
+	    params->alg != WPA_ALG_NONE &&
+	    params->key_len <= sizeof(wpa_s->last_gtk)) {
+		os_memcpy(wpa_s->last_gtk, params->key, params->key_len);
+		wpa_s->last_gtk_len = params->key_len;
 	}
 #endif /* CONFIG_TESTING_GET_GTK */
 #ifdef CONFIG_TESTING_OPTIONS
-	if (addr && !is_broadcast_ether_addr(addr)) {
-		wpa_s->last_tk_alg = alg;
-		os_memcpy(wpa_s->last_tk_addr, addr, ETH_ALEN);
-		wpa_s->last_tk_key_idx = key_idx;
-		if (key)
-			os_memcpy(wpa_s->last_tk, key, key_len);
-		wpa_s->last_tk_len = key_len;
+	if (params->addr && !is_broadcast_ether_addr(params->addr)) {
+		wpa_s->last_tk_alg = params->alg;
+		os_memcpy(wpa_s->last_tk_addr, params->addr, ETH_ALEN);
+		wpa_s->last_tk_key_idx = params->key_idx;
+		if (params->key)
+			os_memcpy(wpa_s->last_tk, params->key, params->key_len);
+		wpa_s->last_tk_len = params->key_len;
 	}
 #endif /* CONFIG_TESTING_OPTIONS */
-	return wpa_drv_set_key(wpa_s, alg, addr, key_idx, set_tx, seq, seq_len,
-			       key, key_len, key_flag);
+	return wpa_drv_set_key(wpa_s, params);
 }
 
 
@@ -1167,14 +1181,20 @@  static void wpa_supplicant_set_rekey_offload(void *ctx,
 static int wpa_supplicant_key_mgmt_set_pmk(void *ctx, const u8 *pmk,
 					   size_t pmk_len)
 {
+	struct driver_set_key_params params;
 	struct wpa_supplicant *wpa_s = ctx;
 
+
 	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, KEY_FLAG_PMK);
-	else
+	    (wpa_s->drv_flags & WPA_DRIVER_FLAGS_KEY_MGMT_OFFLOAD)) {
+		os_memset(&params, 0, sizeof(params));
+		params.alg = WPA_ALG_PMK;
+		params.key = pmk;
+		params.key_len = pmk_len;
+		return wpa_drv_set_key(wpa_s, &params);
+	} else {
 		return 0;
+	}
 }