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