diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c index af4955184..8ef57e5aa 100644 --- a/hostapd/ctrl_iface.c +++ b/hostapd/ctrl_iface.c @@ -2155,7 +2155,8 @@ 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, 0, 1, NULL, 0, - zero, hapd->last_igtk_len) < 0) + zero, hapd->last_igtk_len, + KEY_FLAG_GROUP_TX_DEFAULT) < 0) return -1; /* Set the previously configured key to reset its TSC */ @@ -2164,7 +2165,8 @@ static int hostapd_ctrl_reset_pn(struct hostapd_data *hapd, const char *cmd) broadcast_ether_addr, hapd->last_igtk_key_idx, 0, 1, NULL, 0, hapd->last_igtk, - hapd->last_igtk_len); + hapd->last_igtk_len, + KEY_FLAG_GROUP_TX_DEFAULT); } if (is_broadcast_ether_addr(addr)) { @@ -2179,7 +2181,8 @@ 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, 0, 1, NULL, 0, - zero, hapd->last_gtk_len) < 0) + zero, hapd->last_gtk_len, + KEY_FLAG_GROUP_TX_DEFAULT) < 0) return -1; /* Set the previously configured key to reset its TSC */ @@ -2188,7 +2191,8 @@ static int hostapd_ctrl_reset_pn(struct hostapd_data *hapd, const char *cmd) broadcast_ether_addr, hapd->last_gtk_key_idx, 0, 1, NULL, 0, hapd->last_gtk, - hapd->last_gtk_len); + hapd->last_gtk_len, + KEY_FLAG_GROUP_TX_DEFAULT); } sta = ap_get_sta(hapd, addr); @@ -2205,13 +2209,15 @@ 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, 0, 1, NULL, 0, - zero, sta->last_tk_len) < 0) + zero, sta->last_tk_len, + KEY_FLAG_PAIRWISE_RX_TX) < 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); + 0, sta->last_tk, sta->last_tk_len, + KEY_FLAG_PAIRWISE_RX_TX); } @@ -2259,7 +2265,7 @@ static int hostapd_ctrl_set_key(struct hostapd_data *hapd, const char *cmd) 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); + set_tx, seq, 6, key, key_len, 0); } @@ -2275,7 +2281,8 @@ 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, 0, 1, NULL, 0, - sta->last_tk, sta->last_tk_len); + sta->last_tk, sta->last_tk_len, + KEY_FLAG_PAIRWISE_RX_TX); } @@ -2299,7 +2306,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, 0, NULL, - 0, NULL, 0); + 0, NULL, 0, KEY_FLAG_PAIRWISE); } wpa_printf(MSG_INFO, "TESTING: Send M1 to " MACSTR, MAC2STR(sta->addr)); @@ -2329,7 +2336,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, 0, NULL, - 0, NULL, 0); + 0, NULL, 0, KEY_FLAG_PAIRWISE); } wpa_printf(MSG_INFO, "TESTING: Send M3 to " MACSTR, MAC2STR(sta->addr)); @@ -2359,7 +2366,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, 0, NULL, - 0, NULL, 0); + 0, NULL, 0, KEY_FLAG_PAIRWISE); } wpa_printf(MSG_INFO, diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c index 74f011806..c217d9b24 100644 --- a/src/ap/ap_drv_ops.c +++ b/src/ap/ap_drv_ops.c @@ -682,7 +682,7 @@ 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) + const u8 *key, size_t key_len, enum key_flag key_flag) { struct wpa_driver_set_key_params params; @@ -700,6 +700,7 @@ int hostapd_drv_set_key(const char *ifname, struct hostapd_data *hapd, 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, ¶ms); } diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h index 30547b713..56d1ad862 100644 --- a/src/ap/ap_drv_ops.h +++ b/src/ap/ap_drv_ops.h @@ -91,7 +91,7 @@ int hostapd_drv_set_key(const char *ifname, 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); + const u8 *key, size_t key_len, enum key_flag key_flag); 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 3fb493ae5..b87663fe9 100644 --- a/src/ap/hostapd.c +++ b/src/ap/hostapd.c @@ -293,7 +293,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, - 0, NULL, 0, NULL, 0)) { + 0, NULL, 0, NULL, 0, KEY_FLAG_GROUP)) { wpa_printf(MSG_DEBUG, "Failed to clear default " "encryption keys (ifname=%s keyidx=%d)", ifname, i); @@ -303,7 +303,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, 0, NULL, - 0, NULL, 0)) { + 0, NULL, 0, KEY_FLAG_GROUP)) { wpa_printf(MSG_DEBUG, "Failed to clear " "default mgmt encryption keys " "(ifname=%s keyidx=%d)", ifname, i); @@ -330,7 +330,8 @@ 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, 0, 1, NULL, 0, ssid->wep.key[idx], - ssid->wep.len[idx])) { + ssid->wep.len[idx], + KEY_FLAG_GROUP_RX_TX_DEFAULT)) { wpa_printf(MSG_WARNING, "Could not set WEP encryption."); errors++; } @@ -556,7 +557,10 @@ static int hostapd_setup_encryption(char *iface, struct hostapd_data *hapd) 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])) { + hapd->conf->ssid.wep.len[i], + i == hapd->conf->ssid.wep.idx ? + KEY_FLAG_GROUP_RX_TX_DEFAULT : + KEY_FLAG_GROUP_RX_TX)) { wpa_printf(MSG_WARNING, "Could not set WEP " "encryption."); return -1; diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index aa8b828be..cd6107794 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -4912,7 +4912,10 @@ 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, 0, i == ssid->wep.idx, NULL, 0, - ssid->wep.key[i], ssid->wep.len[i])) { + ssid->wep.key[i], ssid->wep.len[i], + i == ssid->wep.idx ? + KEY_FLAG_GROUP_RX_TX_DEFAULT : + KEY_FLAG_GROUP_RX_TX)) { 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 4bcaec9da..001b26109 100644 --- a/src/ap/ieee802_1x.c +++ b/src/ap/ieee802_1x.c @@ -285,7 +285,8 @@ 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, 0, 1, NULL, 0, ikey, - hapd->conf->individual_wep_key_len)) { + hapd->conf->individual_wep_key_len, + KEY_FLAG_PAIRWISE_RX_TX)) { wpa_printf(MSG_ERROR, "Could not set individual WEP encryption"); } @@ -2179,7 +2180,8 @@ static void ieee802_1x_rekey(void *eloop_ctx, void *timeout_ctx) broadcast_ether_addr, eapol->default_wep_key_idx, 0, 1, NULL, 0, eapol->default_wep_key, - hapd->conf->default_wep_key_len)) { + hapd->conf->default_wep_key_len, + KEY_FLAG_GROUP_RX_TX_DEFAULT)) { hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE8021X, HOSTAPD_LEVEL_WARNING, "failed to configure a new broadcast key"); @@ -2471,7 +2473,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, 0, NULL, - 0, NULL, 0); + 0, NULL, 0, KEY_FLAG_GROUP_RX_TX); ieee802_1x_rekey(hapd, NULL); diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index 8103ef8a3..423528d12 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -136,12 +136,13 @@ 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, + enum key_flag 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); } @@ -1738,7 +1739,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, KEY_FLAG_PAIRWISE)) wpa_printf(MSG_DEBUG, "RSN: PTK removal from the driver failed"); sm->pairwise_set = FALSE; @@ -2771,7 +2772,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, KEY_FLAG_PAIRWISE_RX_TX)) { wpa_printf(MSG_DEBUG, "FILS: Failed to set TK to the driver"); return -1; } @@ -3396,7 +3397,8 @@ 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, + KEY_FLAG_PAIRWISE_RX_TX)) { wpa_sta_disconnect(sm->wpa_auth, sm->addr, WLAN_REASON_PREV_AUTH_NOT_VALID); return; @@ -3988,7 +3990,8 @@ 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, + KEY_FLAG_GROUP_TX_DEFAULT) < 0) ret = -1; if (wpa_auth->conf.ieee80211w != NO_MGMT_FRAME_PROTECTION) { @@ -4001,7 +4004,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, + KEY_FLAG_GROUP_TX_DEFAULT) < 0) ret = -1; } diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h index 3b4fd74e2..0b4b7297c 100644 --- a/src/ap/wpa_auth.h +++ b/src/ap/wpa_auth.h @@ -263,7 +263,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, + enum key_flag 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); diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c index d24feb560..462876195 100644 --- a/src/ap/wpa_auth_ft.c +++ b/src/ap/wpa_auth_ft.c @@ -2622,12 +2622,13 @@ 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, + enum key_flag 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); } @@ -2660,7 +2661,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, KEY_FLAG_PAIRWISE_RX_TX)) 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 e871cc900..e64304636 100644 --- a/src/ap/wpa_auth_glue.c +++ b/src/ap/wpa_auth_glue.c @@ -378,7 +378,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, enum key_flag key_flag) { struct hostapd_data *hapd = ctx; const char *ifname = hapd->conf->iface; @@ -423,7 +423,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, vlan_id, 1, - NULL, 0, key, key_len); + NULL, 0, key, key_len, key_flag); } diff --git a/src/common/defs.h b/src/common/defs.h index e2fa4b291..5e22278e6 100644 --- a/src/common/defs.h +++ b/src/common/defs.h @@ -423,4 +423,26 @@ enum chan_width { CHAN_WIDTH_UNKNOWN }; +enum key_flag { + KEY_FLAG_MODIFY = BIT(0), + KEY_FLAG_DEFAULT = BIT(1), + KEY_FLAG_RX = BIT(2), + KEY_FLAG_TX = BIT(3), + KEY_FLAG_GROUP = BIT(4), + KEY_FLAG_PAIRWISE = BIT(5), + KEY_FLAG_PMK = BIT(6), + /* Used flag combinations */ + KEY_FLAG_RX_TX = KEY_FLAG_RX | KEY_FLAG_TX, + KEY_FLAG_GROUP_RX_TX = KEY_FLAG_GROUP | KEY_FLAG_RX_TX, + KEY_FLAG_GROUP_RX_TX_DEFAULT = KEY_FLAG_GROUP_RX_TX | + KEY_FLAG_DEFAULT, + KEY_FLAG_GROUP_RX = KEY_FLAG_GROUP | KEY_FLAG_RX, + KEY_FLAG_GROUP_TX_DEFAULT = KEY_FLAG_GROUP | KEY_FLAG_TX | + KEY_FLAG_DEFAULT, + KEY_FLAG_PAIRWISE_RX_TX = KEY_FLAG_PAIRWISE | KEY_FLAG_RX_TX, + KEY_FLAG_PAIRWISE_RX = KEY_FLAG_PAIRWISE | KEY_FLAG_RX, + KEY_FLAG_PAIRWISE_RX_TX_MODIFY = KEY_FLAG_PAIRWISE_RX_TX | + KEY_FLAG_MODIFY, +}; + #endif /* DEFS_H */ diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 1301babd5..c37dd2fc9 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -1592,6 +1592,51 @@ struct wpa_driver_set_key_params { /** * vlan_id - VLAN index (0..4095) for VLAN offload cases */ int vlan_id; + + /** + * key_flag - Additional key flags + * + * %KEY_FLAG_MODIFY + * Set when an already installed key must be updated. + * So far the only use-case is changing RX/TX status of + * installed keys. Must not be set when deleting a key. + * %KEY_FLAG_DEFAULT + * Set when the key is also a default key. Must not be set when + * deleting a key. + * %KEY_FLAG_RX + * The key is valid for RX. Must not be set when deleting a key. + * %KEY_FLAG_TX + * The key is valid for TX. Must not be set when deleting a key. + * %KEY_FLAG_GROUP + * The key is a broadcast or group key. + * %KEY_FLAG_PAIRWISE + * The key is a pairwise key. + * %KEY_FLAG_PMK + * The key is a Pairwise Master Key (PMK). + * + * Valid and pre-defined combinations are: + * %KEY_FLAG_GROUP_RX_TX + * WEP key not to be installed as default key. + * %KEY_FLAG_GROUP_RX_TX_DEFAULT + * Default WEP or WPA-NONE key. + * %KEY_FLAG_GROUP_RX + * GTK key valid for RX only. + * %KEY_FLAG_GROUP_TX_DEFAULT + * GTK key valid for TX only, immediately taking over TX. + * %KEY_FLAG_PAIRWISE_RX_TX + * Pairwise key immediately becoming the active pairwise key. + * %KEY_FLAG_PAIRWISE_RX + * Pairwise key not yet valid for TX. (Only usable when Extended + * Key ID is supported by the driver.) + * %KEY_FLAG_PAIRWISE_RX_TX_MODIFY + * Enable TX for a pairwise key installed with + * KEY_FLAG_PAIRWISE_RX. + * + * Not a valid standalone key type but pre-defined to be combined + * with other key_flags: + * %KEY_FLAG_RX_TX + * RX/TX key. */ + enum key_flag key_flag; }; /** diff --git a/src/rsn_supp/tdls.c b/src/rsn_supp/tdls.c index 704c95e68..bb8973942 100644 --- a/src/rsn_supp/tdls.c +++ b/src/rsn_supp/tdls.c @@ -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, KEY_FLAG_PAIRWISE) < 0) { wpa_printf(MSG_WARNING, "TDLS: Failed to delete TPK-TK from " "the driver"); return -1; @@ -227,8 +227,9 @@ 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) { + 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) { 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 85c28401b..5f08d0e78 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -789,7 +789,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, + enum key_flag key_flag) { int keylen, rsclen; enum wpa_alg alg; @@ -834,7 +835,8 @@ 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_PAIRWISE | 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 ")", @@ -927,7 +929,8 @@ 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, + KEY_FLAG_GROUP_RX_TX_DEFAULT) < 0) { wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: Failed to set GTK to the driver " "(Group only)"); @@ -936,7 +939,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, 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)", @@ -1090,7 +1093,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, KEY_FLAG_GROUP_RX) < 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 @@ -1542,7 +1545,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, KEY_FLAG_RX_TX)) goto failed; } @@ -4574,7 +4577,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, KEY_FLAG_PAIRWISE_RX_TX) < 0) { wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "FILS: Failed to set PTK to the driver (alg=%d keylen=%d bssid=" MACSTR ")", diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h index 31a8bd0c6..85fedeeae 100644 --- a/src/rsn_supp/wpa.h +++ b/src/rsn_supp/wpa.h @@ -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, enum key_flag 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, diff --git a/src/rsn_supp/wpa_ft.c b/src/rsn_supp/wpa_ft.c index 2b8b41fa5..8a8c545d3 100644 --- a/src/rsn_supp/wpa_ft.c +++ b/src/rsn_supp/wpa_ft.c @@ -422,8 +422,9 @@ static int wpa_ft_install_ptk(struct wpa_sm *sm, const u8 *bssid) alg = wpa_cipher_to_alg(sm->pairwise_cipher); 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) { + 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) { wpa_printf(MSG_WARNING, "FT: Failed to set PTK to the driver"); return -1; } @@ -773,7 +774,8 @@ 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, + KEY_FLAG_GROUP_RX) < 0) { wpa_printf(MSG_WARNING, "WPA: Failed to set GTK to the " "driver."); return -1; @@ -840,7 +842,8 @@ 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, + KEY_FLAG_GROUP_RX) < 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 2a433425c..7d7c06ef2 100644 --- a/src/rsn_supp/wpa_i.h +++ b/src/rsn_supp/wpa_i.h @@ -198,11 +198,12 @@ static inline void wpa_sm_deauthenticate(struct wpa_sm *sm, u16 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, + enum key_flag 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) diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 339d8198c..65dcb90f1 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -5345,15 +5345,21 @@ 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, 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, 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); + 0, KEY_FLAG_PAIRWISE); /* MLME-SETPROTECTION.request(None) */ wpa_drv_mlme_setprotection(wpa_s, wpa_s->bssid, MLME_SETPROTECTION_PROTECT_TYPE_NONE, @@ -9351,13 +9357,15 @@ 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, + KEY_FLAG_PAIRWISE_RX_TX) < 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, + KEY_FLAG_PAIRWISE_RX_TX); } diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h index e425ea145..45b62bdea 100644 --- a/wpa_supplicant/driver_i.h +++ b/wpa_supplicant/driver_i.h @@ -147,7 +147,8 @@ 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, + enum key_flag key_flag) { struct wpa_driver_set_key_params params; @@ -161,6 +162,7 @@ static inline int wpa_drv_set_key(struct wpa_supplicant *wpa_s, 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) diff --git a/wpa_supplicant/ibss_rsn.c b/wpa_supplicant/ibss_rsn.c index a3b5164c0..37368c4cb 100644 --- a/wpa_supplicant/ibss_rsn.c +++ b/wpa_supplicant/ibss_rsn.c @@ -146,7 +146,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, enum key_flag key_flag) { struct ibss_rsn_peer *peer = ctx; @@ -173,7 +173,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); } @@ -306,7 +306,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, + enum key_flag key_flag) { struct ibss_rsn *ibss_rsn = ctx; u8 seq[6]; @@ -345,7 +346,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); } @@ -858,7 +859,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, KEY_FLAG_PAIRWISE); } if (peer && diff --git a/wpa_supplicant/mesh_mpm.c b/wpa_supplicant/mesh_mpm.c index c7c85929f..31dd1d3c6 100644 --- a/wpa_supplicant/mesh_mpm.c +++ b/wpa_supplicant/mesh_mpm.c @@ -877,7 +877,8 @@ 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, + KEY_FLAG_PAIRWISE_RX_TX); wpa_hexdump_key(MSG_DEBUG, "mesh: RX MGTK Key RSC", sta->mgtk_rsc, sizeof(sta->mgtk_rsc)); @@ -886,7 +887,8 @@ 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, + KEY_FLAG_GROUP_RX); if (sta->igtk_len) { wpa_hexdump_key(MSG_DEBUG, "mesh: RX IGTK Key RSC", @@ -898,7 +900,8 @@ 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, + KEY_FLAG_GROUP_RX); } } diff --git a/wpa_supplicant/mesh_rsn.c b/wpa_supplicant/mesh_rsn.c index e730b6336..f19bfbfc6 100644 --- a/wpa_supplicant/mesh_rsn.c +++ b/wpa_supplicant/mesh_rsn.c @@ -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, + enum key_flag 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, key_flag); } @@ -196,7 +197,8 @@ 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, + KEY_FLAG_GROUP_TX_DEFAULT); } /* group privacy / data frames */ @@ -204,7 +206,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, KEY_FLAG_GROUP_TX_DEFAULT); return 0; } diff --git a/wpa_supplicant/preauth_test.c b/wpa_supplicant/preauth_test.c index 3f2da34e5..a73282841 100644 --- a/wpa_supplicant/preauth_test.c +++ b/wpa_supplicant/preauth_test.c @@ -127,7 +127,8 @@ static int wpa_supplicant_get_bssid(void *wpa_s, 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, + enum key_flag key_flag) { printf("%s - not implemented\n", __func__); return -1; diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 0a9e37c3b..9f3d6ef60 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -142,7 +142,10 @@ 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], + i == ssid->wep_tx_keyidx ? + KEY_FLAG_GROUP_RX_TX_DEFAULT : + KEY_FLAG_GROUP_RX_TX); } return set; @@ -200,7 +203,8 @@ 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, + KEY_FLAG_GROUP_RX_TX_DEFAULT); os_memset(key, 0, sizeof(key)); return ret; } @@ -734,12 +738,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, KEY_FLAG_GROUP); } 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, KEY_FLAG_PAIRWISE); /* 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 240d61099..9d5d35607 100644 --- a/wpa_supplicant/wpas_glue.c +++ b/wpa_supplicant/wpas_glue.c @@ -250,7 +250,9 @@ 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, + unicast ? KEY_FLAG_PAIRWISE_RX_TX : + KEY_FLAG_GROUP_RX_TX_DEFAULT); } @@ -349,7 +351,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, KEY_FLAG_PMK)) { wpa_printf(MSG_DEBUG, "Failed to set PMK to the driver"); } @@ -500,7 +502,8 @@ 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, + enum key_flag key_flag) { struct wpa_supplicant *wpa_s = _wpa_s; if (alg == WPA_ALG_TKIP && key_idx == 0 && key_len == 32) { @@ -525,7 +528,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); } @@ -1169,7 +1172,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, KEY_FLAG_PMK); else return 0; }