diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2019-06-05 11:35:39 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2019-06-05 14:16:00 +0200 |
commit | 705e362ea5d6f711e987f5d370467b8873fc2255 (patch) | |
tree | bb2152c95b76783069419dcd1c24014ba0eb3a1b | |
parent | Add RTEMS-specific getcredhostuuid() (diff) | |
download | rtems-libbsd-705e362ea5d6f711e987f5d370467b8873fc2255.tar.bz2 |
Update to FreeBSD stable/12 2019-06-05
Git mirror commit 78576620f2689e23144a1cf1bf55106cc6abe2b7.
368 files changed, 34630 insertions, 7508 deletions
diff --git a/freebsd-org b/freebsd-org -Subproject 43a38f188ca2e936ec78104c30ea3e24d9c1606 +Subproject 78576620f2689e23144a1cf1bf55106cc6abe2b diff --git a/freebsd/contrib/tcpdump/tcpdump.c b/freebsd/contrib/tcpdump/tcpdump.c index e3d57f1c..d48ad1b0 100644 --- a/freebsd/contrib/tcpdump/tcpdump.c +++ b/freebsd/contrib/tcpdump/tcpdump.c @@ -2204,7 +2204,8 @@ main(int argc, char **argv) } #ifdef HAVE_CAPSICUM - cansandbox = (VFileName == NULL && zflag == NULL); + cansandbox = (VFileName == NULL && zflag == NULL && + ndo->ndo_espsecret == NULL); #ifdef HAVE_CASPER cansandbox = (cansandbox && (ndo->ndo_nflag || capdns != NULL)); #else diff --git a/freebsd/contrib/wpa/src/ap/ap_config.h b/freebsd/contrib/wpa/src/ap/ap_config.h index 8c8f7e28..509677a4 100644 --- a/freebsd/contrib/wpa/src/ap/ap_config.h +++ b/freebsd/contrib/wpa/src/ap/ap_config.h @@ -42,6 +42,7 @@ struct mesh_conf { #define MESH_CONF_SEC_AMPE BIT(2) unsigned int security; enum mfp_options ieee80211w; + int ocv; unsigned int pairwise_cipher; unsigned int group_cipher; unsigned int mgmt_group_cipher; @@ -122,6 +123,7 @@ struct hostapd_vlan { int vlan_id; /* VLAN ID or -1 (VLAN_ID_WILDCARD) for wildcard entry */ struct vlan_description vlan_desc; char ifname[IFNAMSIZ + 1]; + char bridge[IFNAMSIZ + 1]; int configured; int dynamic_vlan; #ifdef CONFIG_FULL_DYNAMIC_VLAN @@ -132,6 +134,7 @@ struct hostapd_vlan { }; #define PMK_LEN 32 +#define KEYID_LEN 32 #define MIN_PASSPHRASE_LEN 8 #define MAX_PASSPHRASE_LEN 63 struct hostapd_sta_wpa_psk_short { @@ -145,9 +148,11 @@ struct hostapd_sta_wpa_psk_short { struct hostapd_wpa_psk { struct hostapd_wpa_psk *next; int group; + char keyid[KEYID_LEN]; u8 psk[PMK_LEN]; u8 addr[ETH_ALEN]; u8 p2p_dev_addr[ETH_ALEN]; + int vlan_id; }; struct hostapd_eap_user { @@ -160,6 +165,8 @@ struct hostapd_eap_user { } methods[EAP_MAX_METHODS]; u8 *password; size_t password_len; + u8 *salt; + size_t salt_len; /* non-zero when password is salted */ int phase2; int force_version; unsigned int wildcard_prefix:1; @@ -169,6 +176,7 @@ struct hostapd_eap_user { unsigned int macacl:1; int ttls_auth; /* EAP_TTLS_AUTH_* bitfield */ struct hostapd_radius_attr *accept_attr; + u32 t_c_timestamp; }; struct hostapd_radius_attr { @@ -201,6 +209,12 @@ struct hostapd_lang_string { u8 name[252]; }; +struct hostapd_venue_url { + u8 venue_number; + u8 url_len; + u8 url[254]; +}; + #define MAX_NAI_REALMS 10 #define MAX_NAI_REALMLEN 255 #define MAX_NAI_EAP_METHODS 5 @@ -224,6 +238,19 @@ struct anqp_element { struct wpabuf *payload; }; +struct fils_realm { + struct dl_list list; + u8 hash[2]; + char realm[]; +}; + +struct sae_password_entry { + struct sae_password_entry *next; + char *password; + char *identifier; + u8 peer_addr[ETH_ALEN]; + int vlan_id; +}; /** * struct hostapd_bss_config - Per-BSS configuration @@ -242,7 +269,8 @@ struct hostapd_bss_config { int max_num_sta; /* maximum number of STAs in station table */ int dtim_period; - int bss_load_update_period; + unsigned int bss_load_update_period; + unsigned int chan_util_avg_period; int ieee802_1x; /* use IEEE 802.1X */ int eapol_version; @@ -287,7 +315,7 @@ struct hostapd_bss_config { char iapp_iface[IFNAMSIZ + 1]; /* interface used with IAPP broadcast * frames */ - enum { + enum macaddr_acl { ACCEPT_UNLESS_DENIED = 0, DENY_UNLESS_ACCEPTED = 1, USE_EXTERNAL_RADIUS_AUTH = 2 @@ -313,33 +341,46 @@ struct hostapd_bss_config { /* dot11AssociationSAQueryRetryTimeout (in TUs) */ int assoc_sa_query_retry_timeout; #endif /* CONFIG_IEEE80211W */ +#ifdef CONFIG_OCV + int ocv; /* Operating Channel Validation */ +#endif /* CONFIG_OCV */ enum { PSK_RADIUS_IGNORED = 0, PSK_RADIUS_ACCEPTED = 1, PSK_RADIUS_REQUIRED = 2 } wpa_psk_radius; int wpa_pairwise; + int group_cipher; /* wpa_group value override from configuation */ int wpa_group; int wpa_group_rekey; + int wpa_group_rekey_set; int wpa_strict_rekey; int wpa_gmk_rekey; int wpa_ptk_rekey; + u32 wpa_group_update_count; + u32 wpa_pairwise_update_count; + int wpa_disable_eapol_key_retries; int rsn_pairwise; int rsn_preauth; char *rsn_preauth_interfaces; - int peerkey; -#ifdef CONFIG_IEEE80211R +#ifdef CONFIG_IEEE80211R_AP /* IEEE 802.11r - Fast BSS Transition */ u8 mobility_domain[MOBILITY_DOMAIN_ID_LEN]; u8 r1_key_holder[FT_R1KH_ID_LEN]; - u32 r0_key_lifetime; + u32 r0_key_lifetime; /* PMK-R0 lifetime seconds */ + int rkh_pos_timeout; + int rkh_neg_timeout; + int rkh_pull_timeout; /* ms */ + int rkh_pull_retries; u32 reassociation_deadline; struct ft_remote_r0kh *r0kh_list; struct ft_remote_r1kh *r1kh_list; int pmk_r1_push; int ft_over_ds; -#endif /* CONFIG_IEEE80211R */ + int ft_psk_generate_local; + int r1_max_key_lifetime; +#endif /* CONFIG_IEEE80211R_AP */ char *ctrl_interface; /* directory for UNIX domain sockets */ #ifndef CONFIG_NATIVE_WINDOWS @@ -351,12 +392,17 @@ struct hostapd_bss_config { char *server_cert; char *private_key; char *private_key_passwd; + char *check_cert_subject; int check_crl; + int check_crl_strict; + unsigned int crl_reload_interval; unsigned int tls_session_lifetime; + unsigned int tls_flags; char *ocsp_stapling_response; char *ocsp_stapling_response_multi; char *dh_file; char *openssl_ciphers; + char *openssl_ecdh_curves; u8 *pac_opaque_encr_key; u8 *eap_fast_a_id; size_t eap_fast_a_id_len; @@ -419,9 +465,11 @@ struct hostapd_bss_config { u8 *extra_cred; size_t extra_cred_len; int wps_cred_processing; + int wps_cred_add_sae; int force_per_enrollee_psk; u8 *ap_settings; size_t ap_settings_len; + struct hostapd_ssid multi_ap_backhaul_ssid; char *upnp_iface; char *friendly_name; char *manufacturer_url; @@ -464,6 +512,7 @@ struct hostapd_bss_config { int time_advertisement; char *time_zone; int wnm_sleep_mode; + int wnm_sleep_mode_no_keys; int bss_transition; /* IEEE 802.11u - Interworking */ @@ -486,6 +535,10 @@ struct hostapd_bss_config { unsigned int venue_name_count; struct hostapd_lang_string *venue_name; + /* Venue URL duples */ + unsigned int venue_url_count; + struct hostapd_venue_url *venue_url; + /* IEEE 802.11u - Network Authentication Type */ u8 *network_auth_type; size_t network_auth_type_len; @@ -508,7 +561,7 @@ struct hostapd_bss_config { struct dl_list anqp_elem; /* list of struct anqp_element */ u16 gas_comeback_delay; - int gas_frag_limit; + size_t gas_frag_limit; int gas_address3; u8 qos_map_set[16 + 2 * 21]; @@ -519,6 +572,7 @@ struct hostapd_bss_config { int na_mcast_to_ucast; #ifdef CONFIG_HS20 int hs20; + int hs20_release; int disable_dgaf; u16 anqp_domain_id; unsigned int hs20_oper_friendly_name_count; @@ -547,13 +601,21 @@ struct hostapd_bss_config { char **icons; size_t icons_count; char *osu_nai; + char *osu_nai2; unsigned int service_desc_count; struct hostapd_lang_string *service_desc; } *hs20_osu_providers, *last_osu; size_t hs20_osu_providers_count; + size_t hs20_osu_providers_nai_count; + char **hs20_operator_icon; + size_t hs20_operator_icon_count; unsigned int hs20_deauth_req_timeout; char *subscr_remediation_url; u8 subscr_remediation_method; + char *hs20_sim_provisioning_url; + char *t_c_filename; + u32 t_c_timestamp; + char *t_c_server_url; #endif /* CONFIG_HS20 */ u8 wps_rf_bands; /* RF bands for WPS (WPS_RF_*) */ @@ -566,7 +628,10 @@ struct hostapd_bss_config { struct wpabuf *assocresp_elements; unsigned int sae_anti_clogging_threshold; + unsigned int sae_sync; + int sae_require_mfp; int *sae_groups; + struct sae_password_entry *sae_passwords; char *wowlan_triggers; /* Wake-on-WLAN triggers */ @@ -574,6 +639,8 @@ struct hostapd_bss_config { u8 bss_load_test[5]; u8 bss_load_test_set; struct wpabuf *own_ie_override; + int sae_reflection_attack; + struct wpabuf *sae_commit_override; #endif /* CONFIG_TESTING_OPTIONS */ #define MESH_ENABLED BIT(0) @@ -591,12 +658,77 @@ struct hostapd_bss_config { #ifdef CONFIG_MBO int mbo_enabled; + /** + * oce - Enable OCE in AP and/or STA-CFON mode + * - BIT(0) is Reserved + * - Set BIT(1) to enable OCE in STA-CFON mode + * - Set BIT(2) to enable OCE in AP mode + */ + unsigned int oce; + int mbo_cell_data_conn_pref; #endif /* CONFIG_MBO */ int ftm_responder; int ftm_initiator; + +#ifdef CONFIG_FILS + u8 fils_cache_id[FILS_CACHE_ID_LEN]; + int fils_cache_id_set; + struct dl_list fils_realms; /* list of struct fils_realm */ + int fils_dh_group; + struct hostapd_ip_addr dhcp_server; + int dhcp_rapid_commit_proxy; + unsigned int fils_hlp_wait_time; + u16 dhcp_server_port; + u16 dhcp_relay_port; +#endif /* CONFIG_FILS */ + + int multicast_to_unicast; + + int broadcast_deauth; + +#ifdef CONFIG_DPP + char *dpp_connector; + struct wpabuf *dpp_netaccesskey; + unsigned int dpp_netaccesskey_expiry; + struct wpabuf *dpp_csign; +#endif /* CONFIG_DPP */ + +#ifdef CONFIG_OWE + macaddr owe_transition_bssid; + u8 owe_transition_ssid[SSID_MAX_LEN]; + size_t owe_transition_ssid_len; + char owe_transition_ifname[IFNAMSIZ + 1]; + int *owe_groups; +#endif /* CONFIG_OWE */ + + int coloc_intf_reporting; + + u8 send_probe_response; + +#define BACKHAUL_BSS 1 +#define FRONTHAUL_BSS 2 + int multi_ap; /* bitmap of BACKHAUL_BSS, FRONTHAUL_BSS */ }; +/** + * struct he_phy_capabilities_info - HE PHY capabilities + */ +struct he_phy_capabilities_info { + Boolean he_su_beamformer; + Boolean he_su_beamformee; + Boolean he_mu_beamformer; +}; + +/** + * struct he_operation - HE operation + */ +struct he_operation { + u8 he_bss_color; + u8 he_default_pe_duration; + u8 he_twt_required; + u8 he_rts_threshold; +}; /** * struct hostapd_config - Per-radio interface configuration @@ -608,10 +740,10 @@ struct hostapd_config { u16 beacon_int; int rts_threshold; int fragm_threshold; - u8 send_probe_response; u8 channel; u8 acs; struct wpa_freq_range_list acs_ch_list; + int acs_exclude_dfs; enum hostapd_hw_mode hw_mode; /* HOSTAPD_MODE_IEEE80211A, .. */ enum { LONG_PREAMBLE = 0, @@ -620,6 +752,8 @@ struct hostapd_config { int *supported_rates; int *basic_rates; + unsigned int beacon_rate; + enum beacon_rate_type rate_type; const struct wpa_driver_ops *driver; char *driver_params; @@ -635,6 +769,9 @@ struct hostapd_config { * ' ' (ascii 32): all environments * 'O': Outdoor environemnt only * 'I': Indoor environment only + * 'X': Used with noncountry entity ("XXX") + * 0x00..0x31: identifying IEEE 802.11 standard + * Annex E table (0x04 = global table) */ int ieee80211d; @@ -675,6 +812,7 @@ struct hostapd_config { u8 vht_oper_chwidth; u8 vht_oper_centr_freq_seg0_idx; u8 vht_oper_centr_freq_seg1_idx; + u8 ht40_plus_minus_allowed; /* Use driver-generated interface addresses when adding multiple BSSs */ u8 use_driver_iface_addr; @@ -707,6 +845,22 @@ struct hostapd_config { struct wpabuf *lci; struct wpabuf *civic; + int stationary_ap; + + int ieee80211ax; +#ifdef CONFIG_IEEE80211AX + struct he_phy_capabilities_info he_phy_capab; + struct he_operation he_op; + struct ieee80211_he_mu_edca_parameter_set he_mu_edca; +#endif /* CONFIG_IEEE80211AX */ + + /* VHT enable/disable config from CHAN_SWITCH */ +#define CH_SWITCH_VHT_ENABLED BIT(0) +#define CH_SWITCH_VHT_DISABLED BIT(1) + unsigned int ch_switch_vht_config; + + int rssi_reject_assoc_rssi; + int rssi_reject_assoc_timeout; }; @@ -714,6 +868,7 @@ int hostapd_mac_comp(const void *a, const void *b); struct hostapd_config * hostapd_config_defaults(void); void hostapd_config_defaults_bss(struct hostapd_bss_config *bss); void hostapd_config_free_eap_user(struct hostapd_eap_user *user); +void hostapd_config_free_eap_users(struct hostapd_eap_user *user); void hostapd_config_clear_wpa_psk(struct hostapd_wpa_psk **p); void hostapd_config_free_bss(struct hostapd_bss_config *conf); void hostapd_config_free(struct hostapd_config *conf); @@ -722,7 +877,7 @@ int hostapd_maclist_found(struct mac_acl_entry *list, int num_entries, int hostapd_rate_found(int *list, int rate); const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf, const u8 *addr, const u8 *p2p_dev_addr, - const u8 *prev_psk); + const u8 *prev_psk, int *vlan_id); int hostapd_setup_wpa_psk(struct hostapd_bss_config *conf); int hostapd_vlan_valid(struct hostapd_vlan *vlan, struct vlan_description *vlan_desc); @@ -733,5 +888,6 @@ hostapd_config_get_radius_attr(struct hostapd_radius_attr *attr, u8 type); int hostapd_config_check(struct hostapd_config *conf, int full_config); void hostapd_set_security_params(struct hostapd_bss_config *bss, int full_config); +int hostapd_sae_pw_id_in_use(struct hostapd_bss_config *conf); #endif /* HOSTAPD_CONFIG_H */ diff --git a/freebsd/contrib/wpa/src/ap/ap_drv_ops.c b/freebsd/contrib/wpa/src/ap/ap_drv_ops.c index c0111c37..09a61882 100644 --- a/freebsd/contrib/wpa/src/ap/ap_drv_ops.c +++ b/freebsd/contrib/wpa/src/ap/ap_drv_ops.c @@ -21,6 +21,7 @@ #include "ap_config.h" #include "p2p_hostapd.h" #include "hs20.h" +#include "wpa_auth.h" #include "ap_drv_ops.h" @@ -101,6 +102,13 @@ int hostapd_build_ap_extra_ies(struct hostapd_data *hapd, goto fail; #endif /* CONFIG_FST */ +#ifdef CONFIG_FILS + pos = hostapd_eid_fils_indic(hapd, buf, 0); + if (add_buf_data(&beacon, buf, pos - buf) < 0 || + add_buf_data(&proberesp, buf, pos - buf) < 0) + goto fail; +#endif /* CONFIG_FILS */ + if (add_buf(&beacon, hapd->wps_beacon_ie) < 0 || add_buf(&proberesp, hapd->wps_probe_resp_ie) < 0) goto fail; @@ -170,7 +178,8 @@ int hostapd_build_ap_extra_ies(struct hostapd_data *hapd, #endif /* CONFIG_HS20 */ #ifdef CONFIG_MBO - if (hapd->conf->mbo_enabled) { + if (hapd->conf->mbo_enabled || + OCE_STA_CFON_ENABLED(hapd) || OCE_AP_ENABLED(hapd)) { pos = hostapd_eid_mbo(hapd, buf, sizeof(buf)); if (add_buf_data(&beacon, buf, pos - buf) < 0 || add_buf_data(&proberesp, buf, pos - buf) < 0 || @@ -179,6 +188,13 @@ int hostapd_build_ap_extra_ies(struct hostapd_data *hapd, } #endif /* CONFIG_MBO */ +#ifdef CONFIG_OWE + pos = hostapd_eid_owe_trans(hapd, buf, sizeof(buf)); + if (add_buf_data(&beacon, buf, pos - buf) < 0 || + add_buf_data(&proberesp, buf, pos - buf) < 0) + goto fail; +#endif /* CONFIG_OWE */ + add_buf(&beacon, hapd->conf->vendor_elements); add_buf(&proberesp, hapd->conf->vendor_elements); add_buf(&assocresp, hapd->conf->assocresp_elements); @@ -342,10 +358,44 @@ int hostapd_add_sta_node(struct hostapd_data *hapd, const u8 *addr, int hostapd_sta_auth(struct hostapd_data *hapd, const u8 *addr, u16 seq, u16 status, const u8 *ie, size_t len) { + struct wpa_driver_sta_auth_params params; +#ifdef CONFIG_FILS + struct sta_info *sta; +#endif /* CONFIG_FILS */ + if (hapd->driver == NULL || hapd->driver->sta_auth == NULL) return 0; - return hapd->driver->sta_auth(hapd->drv_priv, hapd->own_addr, addr, - seq, status, ie, len); + + os_memset(¶ms, 0, sizeof(params)); + +#ifdef CONFIG_FILS + sta = ap_get_sta(hapd, addr); + if (!sta) { + wpa_printf(MSG_DEBUG, "Station " MACSTR + " not found for sta_auth processing", + MAC2STR(addr)); + return 0; + } + + if (sta->auth_alg == WLAN_AUTH_FILS_SK || + sta->auth_alg == WLAN_AUTH_FILS_SK_PFS || + sta->auth_alg == WLAN_AUTH_FILS_PK) { + params.fils_auth = 1; + wpa_auth_get_fils_aead_params(sta->wpa_sm, params.fils_anonce, + params.fils_snonce, + params.fils_kek, + ¶ms.fils_kek_len); + } +#endif /* CONFIG_FILS */ + + params.own_addr = hapd->own_addr; + params.addr = addr; + params.seq = seq; + params.status = status; + params.ie = ie; + params.len = len; + + return hapd->driver->sta_auth(hapd->drv_priv, ¶ms); } @@ -556,13 +606,13 @@ int hostapd_set_tx_queue_params(struct hostapd_data *hapd, int queue, int aifs, struct hostapd_hw_modes * hostapd_get_hw_feature_data(struct hostapd_data *hapd, u16 *num_modes, - u16 *flags) + u16 *flags, u8 *dfs_domain) { if (hapd->driver == NULL || hapd->driver->get_hw_feature_data == NULL) return NULL; return hapd->driver->get_hw_feature_data(hapd->drv_priv, num_modes, - flags); + flags, dfs_domain); } @@ -696,6 +746,15 @@ int hostapd_drv_send_action(struct hostapd_data *hapd, unsigned int freq, sta = ap_get_sta(hapd, dst); if (!sta || !(sta->flags & WLAN_STA_ASSOC)) bssid = wildcard_bssid; + } else if (is_broadcast_ether_addr(dst) && + len > 0 && data[0] == WLAN_ACTION_PUBLIC) { + /* + * The only current use case of Public Action frames with + * broadcast destination address is DPP PKEX. That case is + * directing all devices and not just the STAs within the BSS, + * so have to use the wildcard BSSID value. + */ + bssid = wildcard_bssid; } return hapd->driver->send_action(hapd->drv_priv, freq, wait, dst, hapd->own_addr, bssid, data, len, 0); @@ -776,7 +835,9 @@ static void hostapd_get_hw_mode_any_channels(struct hostapd_data *hapd, if ((acs_ch_list_all || freq_range_list_includes(&hapd->iface->conf->acs_ch_list, chan->chan)) && - !(chan->flag & HOSTAPD_CHAN_DISABLED)) + !(chan->flag & HOSTAPD_CHAN_DISABLED) && + !(hapd->iface->conf->acs_exclude_dfs && + (chan->flag & HOSTAPD_CHAN_RADAR))) int_array_add_unique(freq_list, chan->freq); } } @@ -831,6 +892,9 @@ int hostapd_drv_do_acs(struct hostapd_data *hapd) &hapd->iface->conf->acs_ch_list, chan->chan)) continue; + if (hapd->iface->conf->acs_exclude_dfs && + (chan->flag & HOSTAPD_CHAN_RADAR)) + continue; if (!(chan->flag & HOSTAPD_CHAN_DISABLED)) { channels[num_channels++] = chan->chan; int_array_add_unique(&freq_list, chan->freq); diff --git a/freebsd/contrib/wpa/src/ap/ap_drv_ops.h b/freebsd/contrib/wpa/src/ap/ap_drv_ops.h index 0bb7954e..de40171e 100644 --- a/freebsd/contrib/wpa/src/ap/ap_drv_ops.h +++ b/freebsd/contrib/wpa/src/ap/ap_drv_ops.h @@ -72,7 +72,7 @@ int hostapd_set_tx_queue_params(struct hostapd_data *hapd, int queue, int aifs, int cw_min, int cw_max, int burst_time); struct hostapd_hw_modes * hostapd_get_hw_feature_data(struct hostapd_data *hapd, u16 *num_modes, - u16 *flags); + u16 *flags, u8 *dfs_domain); int hostapd_driver_commit(struct hostapd_data *hapd); int hostapd_drv_none(struct hostapd_data *hapd); int hostapd_driver_scan(struct hostapd_data *hapd, @@ -103,6 +103,14 @@ int hostapd_drv_send_action_addr3_ap(struct hostapd_data *hapd, unsigned int freq, unsigned int wait, const u8 *dst, const u8 *data, size_t len); +static inline void +hostapd_drv_send_action_cancel_wait(struct hostapd_data *hapd) +{ + if (!hapd->driver || !hapd->driver->send_action_cancel_wait || + !hapd->drv_priv) + return; + hapd->driver->send_action_cancel_wait(hapd->drv_priv); +} int hostapd_add_sta_node(struct hostapd_data *hapd, const u8 *addr, u16 auth_alg); int hostapd_sta_auth(struct hostapd_data *hapd, const u8 *addr, @@ -274,8 +282,9 @@ static inline const char * hostapd_drv_get_radio_name(struct hostapd_data *hapd) static inline int hostapd_drv_switch_channel(struct hostapd_data *hapd, struct csa_settings *settings) { - if (hapd->driver == NULL || hapd->driver->switch_channel == NULL) - return -ENOTSUP; + if (hapd->driver == NULL || hapd->driver->switch_channel == NULL || + hapd->drv_priv == NULL) + return -1; return hapd->driver->switch_channel(hapd->drv_priv, settings); } @@ -347,4 +356,22 @@ static inline int hostapd_drv_stop_ap(struct hostapd_data *hapd) return hapd->driver->stop_ap(hapd->drv_priv); } +static inline int hostapd_drv_channel_info(struct hostapd_data *hapd, + struct wpa_channel_info *ci) +{ + if (!hapd->driver || !hapd->driver->channel_info) + return -1; + return hapd->driver->channel_info(hapd->drv_priv, ci); +} + +static inline int +hostapd_drv_send_external_auth_status(struct hostapd_data *hapd, + struct external_auth *params) +{ + if (!hapd->driver || !hapd->drv_priv || + !hapd->driver->send_external_auth_status) + return -1; + return hapd->driver->send_external_auth_status(hapd->drv_priv, params); +} + #endif /* AP_DRV_OPS */ diff --git a/freebsd/contrib/wpa/src/ap/hostapd.h b/freebsd/contrib/wpa/src/ap/hostapd.h index dec46f69..790d3775 100644 --- a/freebsd/contrib/wpa/src/ap/hostapd.h +++ b/freebsd/contrib/wpa/src/ap/hostapd.h @@ -14,6 +14,13 @@ #include "ap_config.h" #include "drivers/driver.h" +#define OCE_STA_CFON_ENABLED(hapd) \ + ((hapd->conf->oce & OCE_STA_CFON) && \ + (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_OCE_STA_CFON)) +#define OCE_AP_ENABLED(hapd) \ + ((hapd->conf->oce & OCE_AP) && \ + (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_OCE_AP)) + struct wpa_ctrl_dst; struct radius_server_data; struct upnp_wps_device_sm; @@ -53,7 +60,14 @@ struct hapd_interfaces { #ifndef CONFIG_NO_VLAN struct dynamic_iface *vlan_priv; #endif /* CONFIG_NO_VLAN */ +#ifdef CONFIG_ETH_P_OUI + struct dl_list eth_p_oui; /* OUI Extended EtherType handlers */ +#endif /* CONFIG_ETH_P_OUI */ int eloop_initialized; + +#ifdef CONFIG_DPP + struct dpp_global *dpp; +#endif /* CONFIG_DPP */ }; enum hostapd_chan_status { @@ -76,6 +90,7 @@ struct hostapd_rate_data { }; struct hostapd_frame_info { + unsigned int freq; u32 channel; u32 datarate; int ssi_signal; /* dBm */ @@ -109,6 +124,14 @@ struct hostapd_neighbor_entry { struct wpabuf *civic; /* LCI update time */ struct os_time lci_date; + int stationary; +}; + +struct hostapd_sae_commit_queue { + struct dl_list list; + int rssi; + size_t len; + u8 msg[]; }; /** @@ -184,6 +207,17 @@ struct hostapd_data { #endif /* CONFIG_FULL_DYNAMIC_VLAN */ struct l2_packet_data *l2; + +#ifdef CONFIG_IEEE80211R_AP + struct dl_list l2_queue; + struct dl_list l2_oui_queue; + struct eth_p_oui_ctx *oui_pull; + struct eth_p_oui_ctx *oui_resp; + struct eth_p_oui_ctx *oui_push; + struct eth_p_oui_ctx *oui_sreq; + struct eth_p_oui_ctx *oui_sresp; +#endif /* CONFIG_IEEE80211R_AP */ + struct wps_context *wps; int beacon_set_done; @@ -242,9 +276,6 @@ struct hostapd_data { unsigned int cs_c_off_ecsa_beacon; unsigned int cs_c_off_ecsa_proberesp; - /* BSS Load */ - unsigned int bss_load_update_timeout; - #ifdef CONFIG_P2P struct p2p_data *p2p; struct p2p_group *p2p_group; @@ -259,9 +290,6 @@ struct hostapd_data { int noa_start; int noa_duration; #endif /* CONFIG_P2P */ -#ifdef CONFIG_INTERWORKING - size_t gas_frag_limit; -#endif /* CONFIG_INTERWORKING */ #ifdef CONFIG_PROXYARP struct l2_packet_data *sock_dhcp; struct l2_packet_data *sock_ndisc; @@ -284,7 +312,10 @@ struct hostapd_data { /** Key used for generating SAE anti-clogging tokens */ u8 sae_token_key[8]; struct os_reltime last_sae_token_key_update; + u16 sae_token_idx; + u16 sae_pending_token_idx[256]; int dot11RSNASAERetransPeriod; /* msec */ + struct dl_list sae_commit_queue; /* struct hostapd_sae_commit_queue */ #endif /* CONFIG_SAE */ #ifdef CONFIG_TESTING_OPTIONS @@ -292,6 +323,18 @@ struct hostapd_data { unsigned int ext_eapol_frame_io:1; struct l2_packet_data *l2_test; + + enum wpa_alg last_gtk_alg; + int last_gtk_key_idx; + u8 last_gtk[WPA_GTK_MAX_LEN]; + size_t last_gtk_len; + +#ifdef CONFIG_IEEE80211W + enum wpa_alg last_igtk_alg; + int last_igtk_key_idx; + u8 last_igtk[WPA_IGTK_MAX_LEN]; + size_t last_igtk_len; +#endif /* CONFIG_IEEE80211W */ #endif /* CONFIG_TESTING_OPTIONS */ #ifdef CONFIG_MBO @@ -300,10 +343,42 @@ struct hostapd_data { struct dl_list nr_db; + u8 beacon_req_token; u8 lci_req_token; u8 range_req_token; unsigned int lci_req_active:1; unsigned int range_req_active:1; + + int dhcp_sock; /* UDP socket used with the DHCP server */ + +#ifdef CONFIG_DPP + int dpp_init_done; + struct dpp_authentication *dpp_auth; + u8 dpp_allowed_roles; + int dpp_qr_mutual; + int dpp_auth_ok_on_ack; + int dpp_in_response_listen; + struct gas_query_ap *gas; + struct dpp_pkex *dpp_pkex; + struct dpp_bootstrap_info *dpp_pkex_bi; + char *dpp_pkex_code; + char *dpp_pkex_identifier; + char *dpp_pkex_auth_cmd; + char *dpp_configurator_params; + struct os_reltime dpp_last_init; + struct os_reltime dpp_init_iter_start; + unsigned int dpp_init_max_tries; + unsigned int dpp_init_retry_time; + unsigned int dpp_resp_wait_time; + unsigned int dpp_resp_max_tries; + unsigned int dpp_resp_retry_time; +#ifdef CONFIG_TESTING_OPTIONS + char *dpp_config_obj_override; + char *dpp_discovery_override; + char *dpp_groups_override; + unsigned int dpp_ignore_netaccesskey_mismatch:1; +#endif /* CONFIG_TESTING_OPTIONS */ +#endif /* CONFIG_DPP */ }; @@ -311,6 +386,7 @@ struct hostapd_sta_info { struct dl_list list; u8 addr[ETH_ALEN]; struct os_reltime last_seen; + int ssi_signal; #ifdef CONFIG_TAXONOMY struct wpabuf *probe_ie_taxonomy; #endif /* CONFIG_TAXONOMY */ @@ -440,6 +516,10 @@ struct hostapd_iface { u64 last_channel_time_busy; u8 channel_utilization; + unsigned int chan_util_samples_sum; + unsigned int chan_util_num_sample_periods; + unsigned int chan_util_average; + /* eCSA IE will be added only if operating class is specified */ u8 cs_oper_class; @@ -459,6 +539,8 @@ struct hostapd_iface { struct dl_list sta_seen; /* struct hostapd_sta_info */ unsigned int num_sta_seen; + + u8 dfs_domain; }; /* hostapd.c */ @@ -466,6 +548,7 @@ int hostapd_for_each_interface(struct hapd_interfaces *interfaces, int (*cb)(struct hostapd_iface *iface, void *ctx), void *ctx); int hostapd_reload_config(struct hostapd_iface *iface); +void hostapd_reconfig_encryption(struct hostapd_data *hapd); struct hostapd_data * hostapd_alloc_bss_data(struct hostapd_iface *hapd_iface, struct hostapd_config *conf, @@ -492,6 +575,7 @@ void hostapd_channel_list_updated(struct hostapd_iface *iface, int initiator); void hostapd_set_state(struct hostapd_iface *iface, enum hostapd_iface_state s); const char * hostapd_state_text(enum hostapd_iface_state s); int hostapd_csa_in_progress(struct hostapd_iface *iface); +void hostapd_chan_switch_vht_config(struct hostapd_data *hapd, int vht_enabled); int hostapd_switch_channel(struct hostapd_data *hapd, struct csa_settings *settings); void @@ -499,6 +583,7 @@ hostapd_switch_channel_fallback(struct hostapd_iface *iface, const struct hostapd_freq_params *freq_params); void hostapd_cleanup_cs_params(struct hostapd_data *hapd); void hostapd_periodic_iface(struct hostapd_iface *iface); +int hostapd_owe_trans_get_info(struct hostapd_data *hapd); /* utils.c */ int hostapd_register_probereq_cb(struct hostapd_data *hapd, @@ -510,6 +595,8 @@ int hostapd_register_probereq_cb(struct hostapd_data *hapd, void hostapd_prune_associations(struct hostapd_data *hapd, const u8 *addr); /* drv_callbacks.c (TODO: move to somewhere else?) */ +void hostapd_notify_assoc_fils_finish(struct hostapd_data *hapd, + struct sta_info *sta); int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr, const u8 *ie, size_t ielen, int reassoc); void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr); @@ -533,6 +620,9 @@ hostapd_get_eap_user(struct hostapd_data *hapd, const u8 *identity, struct hostapd_data * hostapd_get_iface(struct hapd_interfaces *interfaces, const char *ifname); +void hostapd_event_sta_opmode_changed(struct hostapd_data *hapd, const u8 *addr, + enum smps_mode smps_mode, + enum chan_width chan_width, u8 rx_nss); #ifdef CONFIG_FST void fst_hostapd_fill_iface_obj(struct hostapd_data *hapd, diff --git a/freebsd/contrib/wpa/src/ap/hs20.c b/freebsd/contrib/wpa/src/ap/hs20.c index 1a836666..dd96efaa 100644 --- a/freebsd/contrib/wpa/src/ap/hs20.c +++ b/freebsd/contrib/wpa/src/ap/hs20.c @@ -13,9 +13,11 @@ #include "common.h" #include "common/ieee802_11_defs.h" +#include "common/wpa_ctrl.h" #include "hostapd.h" #include "ap_config.h" #include "ap_drv_ops.h" +#include "sta_info.h" #include "hs20.h" @@ -25,17 +27,20 @@ u8 * hostapd_eid_hs20_indication(struct hostapd_data *hapd, u8 *eid) if (!hapd->conf->hs20) return eid; *eid++ = WLAN_EID_VENDOR_SPECIFIC; - *eid++ = 7; + *eid++ = hapd->conf->hs20_release < 2 ? 5 : 7; WPA_PUT_BE24(eid, OUI_WFA); eid += 3; *eid++ = HS20_INDICATION_OUI_TYPE; - conf = HS20_VERSION; /* Release Number */ - conf |= HS20_ANQP_DOMAIN_ID_PRESENT; + conf = (hapd->conf->hs20_release - 1) << 4; /* Release Number */ + if (hapd->conf->hs20_release >= 2) + conf |= HS20_ANQP_DOMAIN_ID_PRESENT; if (hapd->conf->disable_dgaf) conf |= HS20_DGAF_DISABLED; *eid++ = conf; - WPA_PUT_LE16(eid, hapd->conf->anqp_domain_id); - eid += 2; + if (hapd->conf->hs20_release >= 2) { + WPA_PUT_LE16(eid, hapd->conf->anqp_domain_id); + eid += 2; + } return eid; } @@ -84,6 +89,10 @@ u8 * hostapd_eid_osen(struct hostapd_data *hapd, u8 *eid) capab |= WPA_CAPABILITY_MFPR; } #endif /* CONFIG_IEEE80211W */ +#ifdef CONFIG_OCV + if (hapd->conf->ocv) + capab |= WPA_CAPABILITY_OCVC; +#endif /* CONFIG_OCV */ WPA_PUT_LE16(eid, capab); eid += 2; @@ -177,3 +186,72 @@ int hs20_send_wnm_notification_deauth_req(struct hostapd_data *hapd, return ret; } + + +int hs20_send_wnm_notification_t_c(struct hostapd_data *hapd, + const u8 *addr, const char *url) +{ + struct wpabuf *buf; + int ret; + size_t url_len; + + if (!url) { + wpa_printf(MSG_INFO, "HS 2.0: No T&C Server URL available"); + return -1; + } + + url_len = os_strlen(url); + if (5 + url_len > 255) { + wpa_printf(MSG_INFO, + "HS 2.0: Too long T&C Server URL for WNM-Notification: '%s'", + url); + return -1; + } + + buf = wpabuf_alloc(4 + 7 + url_len); + if (!buf) + return -1; + + wpabuf_put_u8(buf, WLAN_ACTION_WNM); + wpabuf_put_u8(buf, WNM_NOTIFICATION_REQ); + wpabuf_put_u8(buf, 1); /* Dialog token */ + wpabuf_put_u8(buf, 1); /* Type - 1 reserved for WFA */ + + /* Terms and Conditions Acceptance subelement */ + wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC); + wpabuf_put_u8(buf, 4 + 1 + url_len); + wpabuf_put_be24(buf, OUI_WFA); + wpabuf_put_u8(buf, HS20_WNM_T_C_ACCEPTANCE); + wpabuf_put_u8(buf, url_len); + wpabuf_put_str(buf, url); + + ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr, + wpabuf_head(buf), wpabuf_len(buf)); + + wpabuf_free(buf); + + return ret; +} + + +void hs20_t_c_filtering(struct hostapd_data *hapd, struct sta_info *sta, + int enabled) +{ + if (enabled) { + wpa_printf(MSG_DEBUG, + "HS 2.0: Terms and Conditions filtering required for " + MACSTR, MAC2STR(sta->addr)); + sta->hs20_t_c_filtering = 1; + /* TODO: Enable firewall filtering for the STA */ + wpa_msg(hapd->msg_ctx, MSG_INFO, HS20_T_C_FILTERING_ADD MACSTR, + MAC2STR(sta->addr)); + } else { + wpa_printf(MSG_DEBUG, + "HS 2.0: Terms and Conditions filtering not required for " + MACSTR, MAC2STR(sta->addr)); + sta->hs20_t_c_filtering = 0; + /* TODO: Disable firewall filtering for the STA */ + wpa_msg(hapd->msg_ctx, MSG_INFO, + HS20_T_C_FILTERING_REMOVE MACSTR, MAC2STR(sta->addr)); + } +} diff --git a/freebsd/contrib/wpa/src/ap/hs20.h b/freebsd/contrib/wpa/src/ap/hs20.h index 152439f4..e99e26e9 100644 --- a/freebsd/contrib/wpa/src/ap/hs20.h +++ b/freebsd/contrib/wpa/src/ap/hs20.h @@ -18,5 +18,9 @@ int hs20_send_wnm_notification(struct hostapd_data *hapd, const u8 *addr, int hs20_send_wnm_notification_deauth_req(struct hostapd_data *hapd, const u8 *addr, const struct wpabuf *payload); +int hs20_send_wnm_notification_t_c(struct hostapd_data *hapd, + const u8 *addr, const char *url); +void hs20_t_c_filtering(struct hostapd_data *hapd, struct sta_info *sta, + int enabled); #endif /* HS20_H */ diff --git a/freebsd/contrib/wpa/src/ap/ieee802_11.h b/freebsd/contrib/wpa/src/ap/ieee802_11.h index 0327dec2..db7badcf 100644 --- a/freebsd/contrib/wpa/src/ap/ieee802_11.h +++ b/freebsd/contrib/wpa/src/ap/ieee802_11.h @@ -16,6 +16,8 @@ struct hostapd_frame_info; struct ieee80211_ht_capabilities; struct ieee80211_vht_capabilities; struct ieee80211_mgmt; +struct vlan_description; +struct hostapd_sta_wpa_psk_short; int ieee802_11_mgmt(struct hostapd_data *hapd, const u8 *buf, size_t len, struct hostapd_frame_info *fi); @@ -55,6 +57,9 @@ u8 * hostapd_eid_vht_operation(struct hostapd_data *hapd, u8 *eid); u8 * hostapd_eid_vendor_vht(struct hostapd_data *hapd, u8 *eid); u8 * hostapd_eid_wb_chsw_wrapper(struct hostapd_data *hapd, u8 *eid); u8 * hostapd_eid_txpower_envelope(struct hostapd_data *hapd, u8 *eid); +u8 * hostapd_eid_he_capab(struct hostapd_data *hapd, u8 *eid); +u8 * hostapd_eid_he_operation(struct hostapd_data *hapd, u8 *eid); +u8 * hostapd_eid_he_mu_edca_parameter_set(struct hostapd_data *hapd, u8 *eid); int hostapd_ht_operation_update(struct hostapd_iface *iface); void ieee802_11_send_sa_query_req(struct hostapd_data *hapd, @@ -76,6 +81,8 @@ void ht40_intolerant_add(struct hostapd_iface *iface, struct sta_info *sta); void ht40_intolerant_remove(struct hostapd_iface *iface, struct sta_info *sta); u16 copy_sta_vht_capab(struct hostapd_data *hapd, struct sta_info *sta, const u8 *vht_capab); +u16 copy_sta_vht_oper(struct hostapd_data *hapd, struct sta_info *sta, + const u8 *vht_oper); u16 set_sta_vht_opmode(struct hostapd_data *hapd, struct sta_info *sta, const u8 *vht_opmode); void hostapd_tx_status(struct hostapd_data *hapd, const u8 *addr, @@ -87,8 +94,8 @@ void ieee802_11_rx_from_unknown(struct hostapd_data *hapd, const u8 *src, u8 * hostapd_eid_assoc_comeback_time(struct hostapd_data *hapd, struct sta_info *sta, u8 *eid); void ieee802_11_sa_query_action(struct hostapd_data *hapd, - const u8 *sa, const u8 action_type, - const u8 *trans_id); + const struct ieee80211_mgmt *mgmt, + size_t len); u8 * hostapd_eid_interworking(struct hostapd_data *hapd, u8 *eid); u8 * hostapd_eid_adv_proto(struct hostapd_data *hapd, u8 *eid); u8 * hostapd_eid_roaming_consortium(struct hostapd_data *hapd, u8 *eid); @@ -116,6 +123,9 @@ u8 * hostapd_eid_mbo(struct hostapd_data *hapd, u8 *eid, size_t len); u8 hostapd_mbo_ie_len(struct hostapd_data *hapd); +u8 * hostapd_eid_mbo_rssi_assoc_rej(struct hostapd_data *hapd, u8 *eid, + size_t len, int delta); + #else /* CONFIG_MBO */ static inline u8 * hostapd_eid_mbo(struct hostapd_data *hapd, u8 *eid, @@ -135,4 +145,36 @@ void ap_copy_sta_supp_op_classes(struct sta_info *sta, const u8 *supp_op_classes, size_t supp_op_classes_len); +u8 * hostapd_eid_fils_indic(struct hostapd_data *hapd, u8 *eid, int hessid); +void ieee802_11_finish_fils_auth(struct hostapd_data *hapd, + struct sta_info *sta, int success, + struct wpabuf *erp_resp, + const u8 *msk, size_t msk_len); +u8 * owe_assoc_req_process(struct hostapd_data *hapd, struct sta_info *sta, + const u8 *owe_dh, u8 owe_dh_len, + u8 *owe_buf, size_t owe_buf_len, u16 *reason); +void fils_hlp_timeout(void *eloop_ctx, void *eloop_data); +void fils_hlp_finish_assoc(struct hostapd_data *hapd, struct sta_info *sta); +void handle_auth_fils(struct hostapd_data *hapd, struct sta_info *sta, + const u8 *pos, size_t len, u16 auth_alg, + u16 auth_transaction, u16 status_code, + void (*cb)(struct hostapd_data *hapd, + struct sta_info *sta, + u16 resp, struct wpabuf *data, int pub)); + +size_t hostapd_eid_owe_trans_len(struct hostapd_data *hapd); +u8 * hostapd_eid_owe_trans(struct hostapd_data *hapd, u8 *eid, size_t len); +int ieee802_11_allowed_address(struct hostapd_data *hapd, const u8 *addr, + const u8 *msg, size_t len, u32 *session_timeout, + u32 *acct_interim_interval, + struct vlan_description *vlan_id, + struct hostapd_sta_wpa_psk_short **psk, + char **identity, char **radius_cui, + int is_probe_req); + +int get_tx_parameters(struct sta_info *sta, int ap_max_chanwidth, + int ap_seg1_idx, int *bandwidth, int *seg1_idx); + +void auth_sae_process_commit(void *eloop_ctx, void *user_ctx); + #endif /* IEEE802_11_H */ diff --git a/freebsd/contrib/wpa/src/ap/ieee802_11_auth.h b/freebsd/contrib/wpa/src/ap/ieee802_11_auth.h index 71f53b96..5aece518 100644 --- a/freebsd/contrib/wpa/src/ap/ieee802_11_auth.h +++ b/freebsd/contrib/wpa/src/ap/ieee802_11_auth.h @@ -23,7 +23,8 @@ int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr, u32 *acct_interim_interval, struct vlan_description *vlan_id, struct hostapd_sta_wpa_psk_short **psk, - char **identity, char **radius_cui); + char **identity, char **radius_cui, + int is_probe_req); int hostapd_acl_init(struct hostapd_data *hapd); void hostapd_acl_deinit(struct hostapd_data *hapd); void hostapd_free_psk_list(struct hostapd_sta_wpa_psk_short *psk); diff --git a/freebsd/contrib/wpa/src/ap/ieee802_11_shared.c b/freebsd/contrib/wpa/src/ap/ieee802_11_shared.c index 8a08e93d..2302d486 100644 --- a/freebsd/contrib/wpa/src/ap/ieee802_11_shared.c +++ b/freebsd/contrib/wpa/src/ap/ieee802_11_shared.c @@ -12,10 +12,12 @@ #include "utils/common.h" #include "common/ieee802_11_defs.h" +#include "common/ocv.h" #include "hostapd.h" #include "sta_info.h" #include "ap_config.h" #include "ap_drv_ops.h" +#include "wpa_auth.h" #include "ieee802_11.h" @@ -51,7 +53,12 @@ u8 * hostapd_eid_assoc_comeback_time(struct hostapd_data *hapd, void ieee802_11_send_sa_query_req(struct hostapd_data *hapd, const u8 *addr, const u8 *trans_id) { - struct ieee80211_mgmt mgmt; +#ifdef CONFIG_OCV + struct sta_info *sta; +#endif /* CONFIG_OCV */ + struct ieee80211_mgmt *mgmt; + u8 *oci_ie = NULL; + u8 oci_ie_len = 0; u8 *end; wpa_printf(MSG_DEBUG, "IEEE 802.11: Sending SA Query Request to " @@ -59,19 +66,61 @@ void ieee802_11_send_sa_query_req(struct hostapd_data *hapd, wpa_hexdump(MSG_DEBUG, "IEEE 802.11: SA Query Transaction ID", trans_id, WLAN_SA_QUERY_TR_ID_LEN); - os_memset(&mgmt, 0, sizeof(mgmt)); - mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, - WLAN_FC_STYPE_ACTION); - os_memcpy(mgmt.da, addr, ETH_ALEN); - os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN); - os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN); - mgmt.u.action.category = WLAN_ACTION_SA_QUERY; - mgmt.u.action.u.sa_query_req.action = WLAN_SA_QUERY_REQUEST; - os_memcpy(mgmt.u.action.u.sa_query_req.trans_id, trans_id, +#ifdef CONFIG_OCV + sta = ap_get_sta(hapd, addr); + if (sta && wpa_auth_uses_ocv(sta->wpa_sm)) { + struct wpa_channel_info ci; + + if (hostapd_drv_channel_info(hapd, &ci) != 0) { + wpa_printf(MSG_WARNING, + "Failed to get channel info for OCI element in SA Query Request"); + return; + } + + oci_ie_len = OCV_OCI_EXTENDED_LEN; + oci_ie = os_zalloc(oci_ie_len); + if (!oci_ie) { + wpa_printf(MSG_WARNING, + "Failed to allocate buffer for OCI element in SA Query Request"); + return; + } + + if (ocv_insert_extended_oci(&ci, oci_ie) < 0) { + os_free(oci_ie); + return; + } + } +#endif /* CONFIG_OCV */ + + mgmt = os_zalloc(sizeof(*mgmt) + oci_ie_len); + if (!mgmt) { + wpa_printf(MSG_DEBUG, + "Failed to allocate buffer for SA Query Response frame"); + os_free(oci_ie); + return; + } + + mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, + WLAN_FC_STYPE_ACTION); + os_memcpy(mgmt->da, addr, ETH_ALEN); + os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN); + os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN); + mgmt->u.action.category = WLAN_ACTION_SA_QUERY; + mgmt->u.action.u.sa_query_req.action = WLAN_SA_QUERY_REQUEST; + os_memcpy(mgmt->u.action.u.sa_query_req.trans_id, trans_id, WLAN_SA_QUERY_TR_ID_LEN); - end = mgmt.u.action.u.sa_query_req.trans_id + WLAN_SA_QUERY_TR_ID_LEN; - if (hostapd_drv_send_mlme(hapd, &mgmt, end - (u8 *) &mgmt, 0) < 0) + end = mgmt->u.action.u.sa_query_req.variable; +#ifdef CONFIG_OCV + if (oci_ie_len > 0) { + os_memcpy(end, oci_ie, oci_ie_len); + end += oci_ie_len; + } +#endif /* CONFIG_OCV */ + if (hostapd_drv_send_mlme(hapd, mgmt, end - (u8 *) mgmt, 0) < 0) wpa_printf(MSG_INFO, "ieee802_11_send_sa_query_req: send failed"); + + os_free(mgmt); + os_free(oci_ie); } @@ -79,7 +128,9 @@ static void ieee802_11_send_sa_query_resp(struct hostapd_data *hapd, const u8 *sa, const u8 *trans_id) { struct sta_info *sta; - struct ieee80211_mgmt resp; + struct ieee80211_mgmt *resp; + u8 *oci_ie = NULL; + u8 oci_ie_len = 0; u8 *end; wpa_printf(MSG_DEBUG, "IEEE 802.11: Received SA Query Request from " @@ -94,30 +145,123 @@ static void ieee802_11_send_sa_query_resp(struct hostapd_data *hapd, return; } +#ifdef CONFIG_OCV + if (wpa_auth_uses_ocv(sta->wpa_sm)) { + struct wpa_channel_info ci; + + if (hostapd_drv_channel_info(hapd, &ci) != 0) { + wpa_printf(MSG_WARNING, + "Failed to get channel info for OCI element in SA Query Response"); + return; + } + + oci_ie_len = OCV_OCI_EXTENDED_LEN; + oci_ie = os_zalloc(oci_ie_len); + if (!oci_ie) { + wpa_printf(MSG_WARNING, + "Failed to allocate buffer for for OCI element in SA Query Response"); + return; + } + + if (ocv_insert_extended_oci(&ci, oci_ie) < 0) { + os_free(oci_ie); + return; + } + } +#endif /* CONFIG_OCV */ + + resp = os_zalloc(sizeof(*resp) + oci_ie_len); + if (!resp) { + wpa_printf(MSG_DEBUG, + "Failed to allocate buffer for SA Query Response frame"); + os_free(oci_ie); + return; + } + wpa_printf(MSG_DEBUG, "IEEE 802.11: Sending SA Query Response to " MACSTR, MAC2STR(sa)); - os_memset(&resp, 0, sizeof(resp)); - resp.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, - WLAN_FC_STYPE_ACTION); - os_memcpy(resp.da, sa, ETH_ALEN); - os_memcpy(resp.sa, hapd->own_addr, ETH_ALEN); - os_memcpy(resp.bssid, hapd->own_addr, ETH_ALEN); - resp.u.action.category = WLAN_ACTION_SA_QUERY; - resp.u.action.u.sa_query_req.action = WLAN_SA_QUERY_RESPONSE; - os_memcpy(resp.u.action.u.sa_query_req.trans_id, trans_id, + resp->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, + WLAN_FC_STYPE_ACTION); + os_memcpy(resp->da, sa, ETH_ALEN); + os_memcpy(resp->sa, hapd->own_addr, ETH_ALEN); + os_memcpy(resp->bssid, hapd->own_addr, ETH_ALEN); + resp->u.action.category = WLAN_ACTION_SA_QUERY; + resp->u.action.u.sa_query_req.action = WLAN_SA_QUERY_RESPONSE; + os_memcpy(resp->u.action.u.sa_query_req.trans_id, trans_id, WLAN_SA_QUERY_TR_ID_LEN); - end = resp.u.action.u.sa_query_req.trans_id + WLAN_SA_QUERY_TR_ID_LEN; - if (hostapd_drv_send_mlme(hapd, &resp, end - (u8 *) &resp, 0) < 0) + end = resp->u.action.u.sa_query_req.variable; +#ifdef CONFIG_OCV + if (oci_ie_len > 0) { + os_memcpy(end, oci_ie, oci_ie_len); + end += oci_ie_len; + } +#endif /* CONFIG_OCV */ + if (hostapd_drv_send_mlme(hapd, resp, end - (u8 *) resp, 0) < 0) wpa_printf(MSG_INFO, "ieee80211_mgmt_sa_query_request: send failed"); + + os_free(resp); + os_free(oci_ie); } -void ieee802_11_sa_query_action(struct hostapd_data *hapd, const u8 *sa, - const u8 action_type, const u8 *trans_id) +void ieee802_11_sa_query_action(struct hostapd_data *hapd, + const struct ieee80211_mgmt *mgmt, + size_t len) { struct sta_info *sta; int i; + const u8 *sa = mgmt->sa; + const u8 action_type = mgmt->u.action.u.sa_query_resp.action; + const u8 *trans_id = mgmt->u.action.u.sa_query_resp.trans_id; + + if (((const u8 *) mgmt) + len < + mgmt->u.action.u.sa_query_resp.variable) { + wpa_printf(MSG_DEBUG, + "IEEE 802.11: Too short SA Query Action frame (len=%lu)", + (unsigned long) len); + return; + } + + sta = ap_get_sta(hapd, sa); + +#ifdef CONFIG_OCV + if (sta && wpa_auth_uses_ocv(sta->wpa_sm)) { + struct ieee802_11_elems elems; + struct wpa_channel_info ci; + int tx_chanwidth; + int tx_seg1_idx; + size_t ies_len; + const u8 *ies; + + ies = mgmt->u.action.u.sa_query_resp.variable; + ies_len = len - (ies - (u8 *) mgmt); + if (ieee802_11_parse_elems(ies, ies_len, &elems, 1) == + ParseFailed) { + wpa_printf(MSG_DEBUG, + "SA Query: Failed to parse elements"); + return; + } + + if (hostapd_drv_channel_info(hapd, &ci) != 0) { + wpa_printf(MSG_WARNING, + "Failed to get channel info to validate received OCI in SA Query Action frame"); + return; + } + + if (get_sta_tx_parameters(sta->wpa_sm, + channel_width_to_int(ci.chanwidth), + ci.seg1_idx, &tx_chanwidth, + &tx_seg1_idx) < 0) + return; + + if (ocv_verify_tx_params(elems.oci, elems.oci_len, &ci, + tx_chanwidth, tx_seg1_idx) != 0) { + wpa_printf(MSG_WARNING, "%s", ocv_errorstr); + return; + } + } +#endif /* CONFIG_OCV */ if (action_type == WLAN_SA_QUERY_REQUEST) { ieee802_11_send_sa_query_resp(hapd, sa, trans_id); @@ -137,7 +281,6 @@ void ieee802_11_sa_query_action(struct hostapd_data *hapd, const u8 *sa, /* MLME-SAQuery.confirm */ - sta = ap_get_sta(hapd, sa); if (sta == NULL || sta->sa_query_trans_id == NULL) { wpa_printf(MSG_DEBUG, "IEEE 802.11: No matching STA with " "pending SA Query request found"); @@ -180,6 +323,10 @@ static void hostapd_ext_capab_byte(struct hostapd_data *hapd, u8 *pos, int idx) case 1: /* Bits 8-15 */ if (hapd->conf->proxy_arp) *pos |= 0x10; /* Bit 12 - Proxy ARP */ + if (hapd->conf->coloc_intf_reporting) { + /* Bit 13 - Collocated Interference Reporting */ + *pos |= 0x20; + } break; case 2: /* Bits 16-23 */ if (hapd->conf->wnm_sleep_mode) @@ -188,9 +335,9 @@ static void hostapd_ext_capab_byte(struct hostapd_data *hapd, u8 *pos, int idx) *pos |= 0x08; /* Bit 19 - BSS Transition */ break; case 3: /* Bits 24-31 */ -#ifdef CONFIG_WNM +#ifdef CONFIG_WNM_AP *pos |= 0x02; /* Bit 25 - SSID List */ -#endif /* CONFIG_WNM */ +#endif /* CONFIG_WNM_AP */ if (hapd->conf->time_advertisement == 2) *pos |= 0x08; /* Bit 27 - UTC TSF Offset */ if (hapd->conf->interworking) @@ -220,12 +367,36 @@ static void hostapd_ext_capab_byte(struct hostapd_data *hapd, u8 *pos, int idx) if (hapd->conf->ssid.utf8_ssid) *pos |= 0x01; /* Bit 48 - UTF-8 SSID */ break; + case 7: /* Bits 56-63 */ + break; case 8: /* Bits 64-71 */ if (hapd->conf->ftm_responder) *pos |= 0x40; /* Bit 70 - FTM responder */ if (hapd->conf->ftm_initiator) *pos |= 0x80; /* Bit 71 - FTM initiator */ break; + case 9: /* Bits 72-79 */ +#ifdef CONFIG_FILS + if ((hapd->conf->wpa & WPA_PROTO_RSN) && + wpa_key_mgmt_fils(hapd->conf->wpa_key_mgmt)) + *pos |= 0x01; +#endif /* CONFIG_FILS */ + break; + case 10: /* Bits 80-87 */ +#ifdef CONFIG_SAE + if (hapd->conf->wpa && + wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt)) { + int in_use = hostapd_sae_pw_id_in_use(hapd->conf); + + if (in_use) + *pos |= 0x02; /* Bit 81 - SAE Password + * Identifiers In Use */ + if (in_use == 2) + *pos |= 0x04; /* Bit 82 - SAE Password + * Identifiers Used Exclusively */ + } +#endif /* CONFIG_SAE */ + break; } } @@ -248,10 +419,10 @@ u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid) if (len < 9 && (hapd->conf->ftm_initiator || hapd->conf->ftm_responder)) len = 9; -#ifdef CONFIG_WNM +#ifdef CONFIG_WNM_AP if (len < 4) len = 4; -#endif /* CONFIG_WNM */ +#endif /* CONFIG_WNM_AP */ #ifdef CONFIG_HS20 if (hapd->conf->hs20 && len < 6) len = 6; @@ -260,6 +431,17 @@ u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid) if (hapd->conf->mbo_enabled && len < 6) len = 6; #endif /* CONFIG_MBO */ +#ifdef CONFIG_FILS + if ((!(hapd->conf->wpa & WPA_PROTO_RSN) || + !wpa_key_mgmt_fils(hapd->conf->wpa_key_mgmt)) && len < 10) + len = 10; +#endif /* CONFIG_FILS */ +#ifdef CONFIG_SAE + if (len < 11 && hapd->conf->wpa && + wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) && + hostapd_sae_pw_id_in_use(hapd->conf)) + len = 11; +#endif /* CONFIG_SAE */ if (len < hapd->iface->extended_capa_len) len = hapd->iface->extended_capa_len; if (len == 0) @@ -434,7 +616,7 @@ u8 * hostapd_eid_time_zone(struct hostapd_data *hapd, u8 *eid) { size_t len; - if (hapd->conf->time_advertisement != 2) + if (hapd->conf->time_advertisement != 2 || !hapd->conf->time_zone) return eid; len = os_strlen(hapd->conf->time_zone); @@ -505,7 +687,7 @@ u8 * hostapd_eid_bss_max_idle_period(struct hostapd_data *hapd, u8 *eid) { u8 *pos = eid; -#ifdef CONFIG_WNM +#ifdef CONFIG_WNM_AP if (hapd->conf->ap_max_inactivity > 0) { unsigned int val; *pos++ = WLAN_EID_BSS_MAX_IDLE_PERIOD; @@ -523,7 +705,7 @@ u8 * hostapd_eid_bss_max_idle_period(struct hostapd_data *hapd, u8 *eid) pos += 2; *pos++ = 0x00; /* TODO: Protected Keep-Alive Required */ } -#endif /* CONFIG_WNM */ +#endif /* CONFIG_WNM_AP */ return pos; } @@ -531,25 +713,56 @@ u8 * hostapd_eid_bss_max_idle_period(struct hostapd_data *hapd, u8 *eid) #ifdef CONFIG_MBO +u8 * hostapd_eid_mbo_rssi_assoc_rej(struct hostapd_data *hapd, u8 *eid, + size_t len, int delta) +{ + u8 mbo[4]; + + mbo[0] = OCE_ATTR_ID_RSSI_BASED_ASSOC_REJECT; + mbo[1] = 2; + /* Delta RSSI */ + mbo[2] = delta; + /* Retry delay */ + mbo[3] = hapd->iconf->rssi_reject_assoc_timeout; + + return eid + mbo_add_ie(eid, len, mbo, 4); +} + + u8 * hostapd_eid_mbo(struct hostapd_data *hapd, u8 *eid, size_t len) { - u8 mbo[6], *mbo_pos = mbo; + u8 mbo[9], *mbo_pos = mbo; u8 *pos = eid; - if (!hapd->conf->mbo_enabled) + if (!hapd->conf->mbo_enabled && + !OCE_STA_CFON_ENABLED(hapd) && !OCE_AP_ENABLED(hapd)) return eid; - *mbo_pos++ = MBO_ATTR_ID_AP_CAPA_IND; - *mbo_pos++ = 1; - /* Not Cellular aware */ - *mbo_pos++ = 0; + if (hapd->conf->mbo_enabled) { + *mbo_pos++ = MBO_ATTR_ID_AP_CAPA_IND; + *mbo_pos++ = 1; + /* Not Cellular aware */ + *mbo_pos++ = 0; + } - if (hapd->mbo_assoc_disallow) { + if (hapd->conf->mbo_enabled && hapd->mbo_assoc_disallow) { *mbo_pos++ = MBO_ATTR_ID_ASSOC_DISALLOW; *mbo_pos++ = 1; *mbo_pos++ = hapd->mbo_assoc_disallow; } + if (OCE_STA_CFON_ENABLED(hapd) || OCE_AP_ENABLED(hapd)) { + u8 ctrl; + + ctrl = OCE_RELEASE; + if (OCE_STA_CFON_ENABLED(hapd) && !OCE_AP_ENABLED(hapd)) + ctrl |= OCE_IS_STA_CFON; + + *mbo_pos++ = OCE_ATTR_ID_CAPA_IND; + *mbo_pos++ = 1; + *mbo_pos++ = ctrl; + } + pos += mbo_add_ie(pos, len, mbo, mbo_pos - mbo); return pos; @@ -558,19 +771,91 @@ u8 * hostapd_eid_mbo(struct hostapd_data *hapd, u8 *eid, size_t len) u8 hostapd_mbo_ie_len(struct hostapd_data *hapd) { - if (!hapd->conf->mbo_enabled) + u8 len; + + if (!hapd->conf->mbo_enabled && + !OCE_STA_CFON_ENABLED(hapd) && !OCE_AP_ENABLED(hapd)) return 0; /* * MBO IE header (6) + Capability Indication attribute (3) + * Association Disallowed attribute (3) = 12 */ - return 6 + 3 + (hapd->mbo_assoc_disallow ? 3 : 0); + len = 6; + if (hapd->conf->mbo_enabled) + len += 3 + (hapd->mbo_assoc_disallow ? 3 : 0); + + /* OCE capability indication attribute (3) */ + if (OCE_STA_CFON_ENABLED(hapd) || OCE_AP_ENABLED(hapd)) + len += 3; + + return len; } #endif /* CONFIG_MBO */ +#ifdef CONFIG_OWE +static int hostapd_eid_owe_trans_enabled(struct hostapd_data *hapd) +{ + return hapd->conf->owe_transition_ssid_len > 0 && + !is_zero_ether_addr(hapd->conf->owe_transition_bssid); +} +#endif /* CONFIG_OWE */ + + +size_t hostapd_eid_owe_trans_len(struct hostapd_data *hapd) +{ +#ifdef CONFIG_OWE + if (!hostapd_eid_owe_trans_enabled(hapd)) + return 0; + return 6 + ETH_ALEN + 1 + hapd->conf->owe_transition_ssid_len; +#else /* CONFIG_OWE */ + return 0; +#endif /* CONFIG_OWE */ +} + + +u8 * hostapd_eid_owe_trans(struct hostapd_data *hapd, u8 *eid, + size_t len) +{ +#ifdef CONFIG_OWE + u8 *pos = eid; + size_t elen; + + if (hapd->conf->owe_transition_ifname[0] && + !hostapd_eid_owe_trans_enabled(hapd)) + hostapd_owe_trans_get_info(hapd); + + if (!hostapd_eid_owe_trans_enabled(hapd)) + return pos; + + elen = hostapd_eid_owe_trans_len(hapd); + if (len < elen) { + wpa_printf(MSG_DEBUG, + "OWE: Not enough room in the buffer for OWE IE"); + return pos; + } + + *pos++ = WLAN_EID_VENDOR_SPECIFIC; + *pos++ = elen - 2; + WPA_PUT_BE24(pos, OUI_WFA); + pos += 3; + *pos++ = OWE_OUI_TYPE; + os_memcpy(pos, hapd->conf->owe_transition_bssid, ETH_ALEN); + pos += ETH_ALEN; + *pos++ = hapd->conf->owe_transition_ssid_len; + os_memcpy(pos, hapd->conf->owe_transition_ssid, + hapd->conf->owe_transition_ssid_len); + pos += hapd->conf->owe_transition_ssid_len; + + return pos; +#else /* CONFIG_OWE */ + return eid; +#endif /* CONFIG_OWE */ +} + + void ap_copy_sta_supp_op_classes(struct sta_info *sta, const u8 *supp_op_classes, size_t supp_op_classes_len) @@ -586,3 +871,134 @@ void ap_copy_sta_supp_op_classes(struct sta_info *sta, os_memcpy(sta->supp_op_classes + 1, supp_op_classes, supp_op_classes_len); } + + +u8 * hostapd_eid_fils_indic(struct hostapd_data *hapd, u8 *eid, int hessid) +{ + u8 *pos = eid; +#ifdef CONFIG_FILS + u8 *len; + u16 fils_info = 0; + size_t realms; + struct fils_realm *realm; + + if (!(hapd->conf->wpa & WPA_PROTO_RSN) || + !wpa_key_mgmt_fils(hapd->conf->wpa_key_mgmt)) + return pos; + + realms = dl_list_len(&hapd->conf->fils_realms); + if (realms > 7) + realms = 7; /* 3 bit count field limits this to max 7 */ + + *pos++ = WLAN_EID_FILS_INDICATION; + len = pos++; + /* TODO: B0..B2: Number of Public Key Identifiers */ + if (hapd->conf->erp_domain) { + /* B3..B5: Number of Realm Identifiers */ + fils_info |= realms << 3; + } + /* TODO: B6: FILS IP Address Configuration */ + if (hapd->conf->fils_cache_id_set) + fils_info |= BIT(7); + if (hessid && !is_zero_ether_addr(hapd->conf->hessid)) + fils_info |= BIT(8); /* HESSID Included */ + /* FILS Shared Key Authentication without PFS Supported */ + fils_info |= BIT(9); + if (hapd->conf->fils_dh_group) { + /* FILS Shared Key Authentication with PFS Supported */ + fils_info |= BIT(10); + } + /* TODO: B11: FILS Public Key Authentication Supported */ + /* B12..B15: Reserved */ + WPA_PUT_LE16(pos, fils_info); + pos += 2; + if (hapd->conf->fils_cache_id_set) { + os_memcpy(pos, hapd->conf->fils_cache_id, FILS_CACHE_ID_LEN); + pos += FILS_CACHE_ID_LEN; + } + if (hessid && !is_zero_ether_addr(hapd->conf->hessid)) { + os_memcpy(pos, hapd->conf->hessid, ETH_ALEN); + pos += ETH_ALEN; + } + + dl_list_for_each(realm, &hapd->conf->fils_realms, struct fils_realm, + list) { + if (realms == 0) + break; + realms--; + os_memcpy(pos, realm->hash, 2); + pos += 2; + } + *len = pos - len - 1; +#endif /* CONFIG_FILS */ + + return pos; +} + + +#ifdef CONFIG_OCV +int get_tx_parameters(struct sta_info *sta, int ap_max_chanwidth, + int ap_seg1_idx, int *bandwidth, int *seg1_idx) +{ + int ht_40mhz = 0; + int vht_80p80 = 0; + int requested_bw; + + if (sta->ht_capabilities) + ht_40mhz = !!(sta->ht_capabilities->ht_capabilities_info & + HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET); + + if (sta->vht_operation) { + struct ieee80211_vht_operation *oper = sta->vht_operation; + + /* + * If a VHT Operation element was present, use it to determine + * the supported channel bandwidth. + */ + if (oper->vht_op_info_chwidth == 0) { + requested_bw = ht_40mhz ? 40 : 20; + } else if (oper->vht_op_info_chan_center_freq_seg1_idx == 0) { + requested_bw = 80; + } else { + int diff; + + requested_bw = 160; + diff = abs((int) + oper->vht_op_info_chan_center_freq_seg0_idx - + (int) + oper->vht_op_info_chan_center_freq_seg1_idx); + vht_80p80 = oper->vht_op_info_chan_center_freq_seg1_idx + != 0 && diff > 16; + } + } else if (sta->vht_capabilities) { + struct ieee80211_vht_capabilities *capab; + int vht_chanwidth; + + capab = sta->vht_capabilities; + + /* + * If only the VHT Capabilities element is present (e.g., for + * normal clients), use it to determine the supported channel + * bandwidth. + */ + vht_chanwidth = capab->vht_capabilities_info & + VHT_CAP_SUPP_CHAN_WIDTH_MASK; + vht_80p80 = capab->vht_capabilities_info & + VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ; + + /* TODO: Also take into account Extended NSS BW Support field */ + requested_bw = vht_chanwidth ? 160 : 80; + } else { + requested_bw = ht_40mhz ? 40 : 20; + } + + *bandwidth = requested_bw < ap_max_chanwidth ? + requested_bw : ap_max_chanwidth; + + *seg1_idx = 0; + if (ap_seg1_idx && vht_80p80) + *seg1_idx = ap_seg1_idx; + + return 0; +} +#endif /* CONFIG_OCV */ diff --git a/freebsd/contrib/wpa/src/ap/pmksa_cache_auth.h b/freebsd/contrib/wpa/src/ap/pmksa_cache_auth.h index d8d9c5a2..2ef21743 100644 --- a/freebsd/contrib/wpa/src/ap/pmksa_cache_auth.h +++ b/freebsd/contrib/wpa/src/ap/pmksa_cache_auth.h @@ -35,6 +35,7 @@ struct rsn_pmksa_cache_entry { }; struct rsn_pmksa_cache; +struct radius_das_attrs; struct rsn_pmksa_cache * pmksa_cache_auth_init(void (*free_cb)(struct rsn_pmksa_cache_entry *entry, @@ -53,6 +54,13 @@ pmksa_cache_auth_add(struct rsn_pmksa_cache *pmksa, const u8 *aa, const u8 *spa, int session_timeout, struct eapol_state_machine *eapol, int akmp); struct rsn_pmksa_cache_entry * +pmksa_cache_auth_create_entry(const u8 *pmk, size_t pmk_len, const u8 *pmkid, + const u8 *kck, size_t kck_len, const u8 *aa, + const u8 *spa, int session_timeout, + struct eapol_state_machine *eapol, int akmp); +int pmksa_cache_auth_add_entry(struct rsn_pmksa_cache *pmksa, + struct rsn_pmksa_cache_entry *entry); +struct rsn_pmksa_cache_entry * pmksa_cache_add_okc(struct rsn_pmksa_cache *pmksa, const struct rsn_pmksa_cache_entry *old_entry, const u8 *aa, const u8 *pmkid); @@ -65,5 +73,7 @@ int pmksa_cache_auth_radius_das_disconnect(struct rsn_pmksa_cache *pmksa, struct radius_das_attrs *attr); int pmksa_cache_auth_list(struct rsn_pmksa_cache *pmksa, char *buf, size_t len); void pmksa_cache_auth_flush(struct rsn_pmksa_cache *pmksa); +int pmksa_cache_auth_list_mesh(struct rsn_pmksa_cache *pmksa, const u8 *addr, + char *buf, size_t len); #endif /* PMKSA_CACHE_H */ diff --git a/freebsd/contrib/wpa/src/ap/sta_info.h b/freebsd/contrib/wpa/src/ap/sta_info.h index 099de62d..ece0c60a 100644 --- a/freebsd/contrib/wpa/src/ap/sta_info.h +++ b/freebsd/contrib/wpa/src/ap/sta_info.h @@ -1,6 +1,6 @@ /* * hostapd / Station table - * Copyright (c) 2002-2011, Jouni Malinen <j@w1.fi> + * Copyright (c) 2002-2017, Jouni Malinen <j@w1.fi> * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -9,14 +9,11 @@ #ifndef STA_INFO_H #define STA_INFO_H -#ifdef CONFIG_MESH -/* needed for mesh_plink_state enum */ #include "common/defs.h" -#include "common/wpa_common.h" -#endif /* CONFIG_MESH */ - #include "list.h" #include "vlan.h" +#include "common/wpa_common.h" +#include "common/ieee802_11_defs.h" /* STA flags */ #define WLAN_STA_AUTH BIT(0) @@ -38,6 +35,8 @@ #define WLAN_STA_WNM_SLEEP_MODE BIT(19) #define WLAN_STA_VHT_OPMODE_ENABLED BIT(20) #define WLAN_STA_VENDOR_VHT BIT(21) +#define WLAN_STA_PENDING_FILS_ERP BIT(22) +#define WLAN_STA_MULTI_AP BIT(23) #define WLAN_STA_PENDING_DISASSOC_CB BIT(29) #define WLAN_STA_PENDING_DEAUTH_CB BIT(30) #define WLAN_STA_NONERP BIT(31) @@ -46,6 +45,7 @@ * Supported Rates IEs). */ #define WLAN_SUPP_RATES_MAX 32 +struct hostapd_data; struct mbo_non_pref_chan_info { struct mbo_non_pref_chan_info *next; @@ -68,6 +68,7 @@ struct sta_info { be32 ipaddr; struct dl_list ip6addr; /* list head for struct ip6addr */ u16 aid; /* STA's unique AID (1 .. 2007) or 0 if not yet assigned */ + u16 disconnect_reason_code; /* RADIUS server override */ u32 flags; /* Bitfield of WLAN_STA_* */ u16 capability; u16 listen_interval; /* or beacon_int for APs */ @@ -113,6 +114,11 @@ struct sta_info { unsigned int radius_das_match:1; unsigned int ecsa_supported:1; unsigned int added_unassoc:1; + unsigned int pending_wds_enable:1; + unsigned int power_capab:1; + unsigned int agreed_to_steer:1; + unsigned int hs20_t_c_filtering:1; + unsigned int ft_over_ds:1; u16 auth_alg; @@ -158,6 +164,7 @@ struct sta_info { struct ieee80211_ht_capabilities *ht_capabilities; struct ieee80211_vht_capabilities *vht_capabilities; + struct ieee80211_vht_operation *vht_operation; u8 vht_opmode; #ifdef CONFIG_IEEE80211W @@ -170,17 +177,20 @@ struct sta_info { struct os_reltime sa_query_start; #endif /* CONFIG_IEEE80211W */ -#ifdef CONFIG_INTERWORKING +#if defined(CONFIG_INTERWORKING) || defined(CONFIG_DPP) #define GAS_DIALOG_MAX 8 /* Max concurrent dialog number */ struct gas_dialog_info *gas_dialog; u8 gas_dialog_next; -#endif /* CONFIG_INTERWORKING */ +#endif /* CONFIG_INTERWORKING || CONFIG_DPP */ struct wpabuf *wps_ie; /* WPS IE from (Re)Association Request */ struct wpabuf *p2p_ie; /* P2P IE from (Re)Association Request */ struct wpabuf *hs20_ie; /* HS 2.0 IE from (Re)Association Request */ + /* Hotspot 2.0 Roaming Consortium from (Re)Association Request */ + struct wpabuf *roaming_consortium; u8 remediation_method; char *remediation_url; /* HS 2.0 Subscription Remediation Server URL */ + char *t_c_url; /* HS 2.0 Terms and Conditions Server URL */ struct wpabuf *hs20_deauth_req; char *hs20_session_info_url; int hs20_disassoc_timer; @@ -195,7 +205,8 @@ struct sta_info { unsigned int mesh_sae_pmksa_caching:1; #endif /* CONFIG_SAE */ - u32 session_timeout; /* valid only if session_timeout_set == 1 */ + /* valid only if session_timeout_set == 1 */ + struct os_reltime session_timeout; /* Last Authentication/(Re)Association Request/Action frame sequence * control */ @@ -207,6 +218,7 @@ struct sta_info { u8 cell_capa; /* 0 = unknown (not an MBO STA); otherwise, * enum mbo_cellular_capa values */ struct mbo_non_pref_chan_info *non_pref_chan; + int auth_rssi; /* Last Authentication frame RSSI */ #endif /* CONFIG_MBO */ u8 *supp_op_classes; /* Supported Operating Classes element, if @@ -214,10 +226,55 @@ struct sta_info { u8 rrm_enabled_capa[5]; + s8 min_tx_power; + s8 max_tx_power; + #ifdef CONFIG_TAXONOMY struct wpabuf *probe_ie_taxonomy; struct wpabuf *assoc_ie_taxonomy; #endif /* CONFIG_TAXONOMY */ + +#ifdef CONFIG_FILS + u8 fils_snonce[FILS_NONCE_LEN]; + u8 fils_session[FILS_SESSION_LEN]; + u8 fils_erp_pmkid[PMKID_LEN]; + u8 *fils_pending_assoc_req; + size_t fils_pending_assoc_req_len; + unsigned int fils_pending_assoc_is_reassoc:1; + unsigned int fils_dhcp_rapid_commit_proxy:1; + unsigned int fils_erp_pmkid_set:1; + unsigned int fils_drv_assoc_finish:1; + struct wpabuf *fils_hlp_resp; + struct wpabuf *hlp_dhcp_discover; + void (*fils_pending_cb)(struct hostapd_data *hapd, struct sta_info *sta, + u16 resp, struct wpabuf *data, int pub); +#ifdef CONFIG_FILS_SK_PFS + struct crypto_ecdh *fils_ecdh; +#endif /* CONFIG_FILS_SK_PFS */ + struct wpabuf *fils_dh_ss; + struct wpabuf *fils_g_sta; +#endif /* CONFIG_FILS */ + +#ifdef CONFIG_OWE + u8 *owe_pmk; + size_t owe_pmk_len; + struct crypto_ecdh *owe_ecdh; + u16 owe_group; +#endif /* CONFIG_OWE */ + + u8 *ext_capability; + char *ifname_wds; /* WDS ifname, if in use */ + +#ifdef CONFIG_DPP2 + struct dpp_pfs *dpp_pfs; +#endif /* CONFIG_DPP2 */ + +#ifdef CONFIG_TESTING_OPTIONS + enum wpa_alg last_tk_alg; + int last_tk_key_idx; + u8 last_tk[WPA_TK_MAX_LEN]; + size_t last_tk_len; +#endif /* CONFIG_TESTING_OPTIONS */ }; @@ -237,8 +294,6 @@ struct sta_info { #define AP_MAX_INACTIVITY_AFTER_DEAUTH (1 * 5) -struct hostapd_data; - int ap_for_each_sta(struct hostapd_data *hapd, int (*cb)(struct hostapd_data *hapd, struct sta_info *sta, void *ctx), @@ -273,6 +328,8 @@ int ap_sta_set_vlan(struct hostapd_data *hapd, struct sta_info *sta, void ap_sta_start_sa_query(struct hostapd_data *hapd, struct sta_info *sta); void ap_sta_stop_sa_query(struct hostapd_data *hapd, struct sta_info *sta); int ap_check_sa_query_timeout(struct hostapd_data *hapd, struct sta_info *sta); +const char * ap_sta_wpa_get_keyid(struct hostapd_data *hapd, + struct sta_info *sta); void ap_sta_disconnect(struct hostapd_data *hapd, struct sta_info *sta, const u8 *addr, u16 reason); @@ -289,5 +346,9 @@ void ap_sta_clear_disconnect_timeouts(struct hostapd_data *hapd, struct sta_info *sta); int ap_sta_flags_txt(u32 flags, char *buf, size_t buflen); +void ap_sta_delayed_1x_auth_fail_disconnect(struct hostapd_data *hapd, + struct sta_info *sta); +int ap_sta_pending_delayed_1x_auth_fail_disconnect(struct hostapd_data *hapd, + struct sta_info *sta); #endif /* STA_INFO_H */ diff --git a/freebsd/contrib/wpa/src/ap/wpa_auth.c b/freebsd/contrib/wpa/src/ap/wpa_auth.c index 5e0b0bf8..5a1b250c 100644 --- a/freebsd/contrib/wpa/src/ap/wpa_auth.c +++ b/freebsd/contrib/wpa/src/ap/wpa_auth.c @@ -2,7 +2,7 @@ /* * IEEE 802.11 RSN / WPA Authenticator - * Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi> + * Copyright (c) 2004-2019, Jouni Malinen <j@w1.fi> * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -15,12 +15,17 @@ #include "utils/state_machine.h" #include "utils/bitfield.h" #include "common/ieee802_11_defs.h" +#include "common/ocv.h" +#include "crypto/aes.h" #include "crypto/aes_wrap.h" +#include "crypto/aes_siv.h" #include "crypto/crypto.h" #include "crypto/sha1.h" #include "crypto/sha256.h" +#include "crypto/sha384.h" #include "crypto/random.h" #include "eapol_auth/eapol_auth_sm.h" +#include "drivers/driver.h" #include "ap_config.h" #include "ieee802_11.h" #include "wpa_auth.h" @@ -35,8 +40,14 @@ static void wpa_send_eapol_timeout(void *eloop_ctx, void *timeout_ctx); static int wpa_sm_step(struct wpa_state_machine *sm); -static int wpa_verify_key_mic(int akmp, struct wpa_ptk *PTK, u8 *data, - size_t data_len); +static int wpa_verify_key_mic(int akmp, size_t pmk_len, struct wpa_ptk *PTK, + u8 *data, size_t data_len); +#ifdef CONFIG_FILS +static int wpa_aead_decrypt(struct wpa_state_machine *sm, struct wpa_ptk *ptk, + u8 *buf, size_t buf_len, u16 *_key_data_len); +static struct wpabuf * fils_prepare_plainbuf(struct wpa_state_machine *sm, + const struct wpabuf *hlp); +#endif /* CONFIG_FILS */ static void wpa_sm_call_step(void *eloop_ctx, void *timeout_ctx); static void wpa_group_sm_step(struct wpa_authenticator *wpa_auth, struct wpa_group *group); @@ -54,12 +65,12 @@ static void wpa_group_get(struct wpa_authenticator *wpa_auth, struct wpa_group *group); static void wpa_group_put(struct wpa_authenticator *wpa_auth, struct wpa_group *group); +static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos); -static const u32 dot11RSNAConfigGroupUpdateCount = 4; -static const u32 dot11RSNAConfigPairwiseUpdateCount = 4; static const u32 eapol_key_timeout_first = 100; /* ms */ static const u32 eapol_key_timeout_subseq = 1000; /* ms */ static const u32 eapol_key_timeout_first_group = 500; /* ms */ +static const u32 eapol_key_timeout_no_retrans = 4000; /* ms */ /* TODO: make these configurable */ static const int dot11RSNAConfigPMKLifetime = 43200; @@ -70,8 +81,8 @@ static const int dot11RSNAConfigSATimeout = 60; static inline int wpa_auth_mic_failure_report( struct wpa_authenticator *wpa_auth, const u8 *addr) { - if (wpa_auth->cb.mic_failure_report) - return wpa_auth->cb.mic_failure_report(wpa_auth->cb.ctx, addr); + if (wpa_auth->cb->mic_failure_report) + return wpa_auth->cb->mic_failure_report(wpa_auth->cb_ctx, addr); return 0; } @@ -79,8 +90,8 @@ static inline int wpa_auth_mic_failure_report( static inline void wpa_auth_psk_failure_report( struct wpa_authenticator *wpa_auth, const u8 *addr) { - if (wpa_auth->cb.psk_failure_report) - wpa_auth->cb.psk_failure_report(wpa_auth->cb.ctx, addr); + if (wpa_auth->cb->psk_failure_report) + wpa_auth->cb->psk_failure_report(wpa_auth->cb_ctx, addr); } @@ -88,38 +99,39 @@ static inline void wpa_auth_set_eapol(struct wpa_authenticator *wpa_auth, const u8 *addr, wpa_eapol_variable var, int value) { - if (wpa_auth->cb.set_eapol) - wpa_auth->cb.set_eapol(wpa_auth->cb.ctx, addr, var, value); + if (wpa_auth->cb->set_eapol) + wpa_auth->cb->set_eapol(wpa_auth->cb_ctx, addr, var, value); } static inline int wpa_auth_get_eapol(struct wpa_authenticator *wpa_auth, const u8 *addr, wpa_eapol_variable var) { - if (wpa_auth->cb.get_eapol == NULL) + if (wpa_auth->cb->get_eapol == NULL) return -1; - return wpa_auth->cb.get_eapol(wpa_auth->cb.ctx, addr, var); + return wpa_auth->cb->get_eapol(wpa_auth->cb_ctx, addr, var); } static inline const u8 * wpa_auth_get_psk(struct wpa_authenticator *wpa_auth, const u8 *addr, const u8 *p2p_dev_addr, - const u8 *prev_psk) + const u8 *prev_psk, size_t *psk_len, + int *vlan_id) { - if (wpa_auth->cb.get_psk == NULL) + if (wpa_auth->cb->get_psk == NULL) return NULL; - return wpa_auth->cb.get_psk(wpa_auth->cb.ctx, addr, p2p_dev_addr, - prev_psk); + return wpa_auth->cb->get_psk(wpa_auth->cb_ctx, addr, p2p_dev_addr, + prev_psk, psk_len, vlan_id); } static inline int wpa_auth_get_msk(struct wpa_authenticator *wpa_auth, const u8 *addr, u8 *msk, size_t *len) { - if (wpa_auth->cb.get_msk == NULL) + if (wpa_auth->cb->get_msk == NULL) return -1; - return wpa_auth->cb.get_msk(wpa_auth->cb.ctx, addr, msk, len); + return wpa_auth->cb->get_msk(wpa_auth->cb_ctx, addr, msk, len); } @@ -128,19 +140,19 @@ static inline int wpa_auth_set_key(struct wpa_authenticator *wpa_auth, enum wpa_alg alg, const u8 *addr, int idx, u8 *key, size_t key_len) { - if (wpa_auth->cb.set_key == NULL) + 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); + return wpa_auth->cb->set_key(wpa_auth->cb_ctx, vlan_id, alg, addr, idx, + key, key_len); } static inline int wpa_auth_get_seqnum(struct wpa_authenticator *wpa_auth, const u8 *addr, int idx, u8 *seq) { - if (wpa_auth->cb.get_seqnum == NULL) + if (wpa_auth->cb->get_seqnum == NULL) return -1; - return wpa_auth->cb.get_seqnum(wpa_auth->cb.ctx, addr, idx, seq); + return wpa_auth->cb->get_seqnum(wpa_auth->cb_ctx, addr, idx, seq); } @@ -148,10 +160,10 @@ static inline int wpa_auth_send_eapol(struct wpa_authenticator *wpa_auth, const u8 *addr, const u8 *data, size_t data_len, int encrypt) { - if (wpa_auth->cb.send_eapol == NULL) + if (wpa_auth->cb->send_eapol == NULL) return -1; - return wpa_auth->cb.send_eapol(wpa_auth->cb.ctx, addr, data, data_len, - encrypt); + return wpa_auth->cb->send_eapol(wpa_auth->cb_ctx, addr, data, data_len, + encrypt); } @@ -159,9 +171,9 @@ wpa_auth_send_eapol(struct wpa_authenticator *wpa_auth, const u8 *addr, static inline int wpa_auth_start_ampe(struct wpa_authenticator *wpa_auth, const u8 *addr) { - if (wpa_auth->cb.start_ampe == NULL) + if (wpa_auth->cb->start_ampe == NULL) return -1; - return wpa_auth->cb.start_ampe(wpa_auth->cb.ctx, addr); + return wpa_auth->cb->start_ampe(wpa_auth->cb_ctx, addr); } #endif /* CONFIG_MESH */ @@ -170,9 +182,9 @@ int wpa_auth_for_each_sta(struct wpa_authenticator *wpa_auth, int (*cb)(struct wpa_state_machine *sm, void *ctx), void *cb_ctx) { - if (wpa_auth->cb.for_each_sta == NULL) + if (wpa_auth->cb->for_each_sta == NULL) return 0; - return wpa_auth->cb.for_each_sta(wpa_auth->cb.ctx, cb, cb_ctx); + return wpa_auth->cb->for_each_sta(wpa_auth->cb_ctx, cb, cb_ctx); } @@ -180,18 +192,18 @@ int wpa_auth_for_each_auth(struct wpa_authenticator *wpa_auth, int (*cb)(struct wpa_authenticator *a, void *ctx), void *cb_ctx) { - if (wpa_auth->cb.for_each_auth == NULL) + if (wpa_auth->cb->for_each_auth == NULL) return 0; - return wpa_auth->cb.for_each_auth(wpa_auth->cb.ctx, cb, cb_ctx); + return wpa_auth->cb->for_each_auth(wpa_auth->cb_ctx, cb, cb_ctx); } void wpa_auth_logger(struct wpa_authenticator *wpa_auth, const u8 *addr, logger_level level, const char *txt) { - if (wpa_auth->cb.logger == NULL) + if (wpa_auth->cb->logger == NULL) return; - wpa_auth->cb.logger(wpa_auth->cb.ctx, addr, level, txt); + wpa_auth->cb->logger(wpa_auth->cb_ctx, addr, level, txt); } @@ -202,7 +214,7 @@ void wpa_auth_vlogger(struct wpa_authenticator *wpa_auth, const u8 *addr, int maxlen; va_list ap; - if (wpa_auth->cb.logger == NULL) + if (wpa_auth->cb->logger == NULL) return; maxlen = os_strlen(fmt) + 100; @@ -221,30 +233,33 @@ void wpa_auth_vlogger(struct wpa_authenticator *wpa_auth, const u8 *addr, static void wpa_sta_disconnect(struct wpa_authenticator *wpa_auth, - const u8 *addr) + const u8 *addr, u16 reason) { - if (wpa_auth->cb.disconnect == NULL) + if (wpa_auth->cb->disconnect == NULL) return; - wpa_printf(MSG_DEBUG, "wpa_sta_disconnect STA " MACSTR, MAC2STR(addr)); - wpa_auth->cb.disconnect(wpa_auth->cb.ctx, addr, - WLAN_REASON_PREV_AUTH_NOT_VALID); + wpa_printf(MSG_DEBUG, "wpa_sta_disconnect STA " MACSTR " (reason %u)", + MAC2STR(addr), reason); + wpa_auth->cb->disconnect(wpa_auth->cb_ctx, addr, reason); } -static int wpa_use_aes_cmac(struct wpa_state_machine *sm) +#ifdef CONFIG_OCV +static int wpa_channel_info(struct wpa_authenticator *wpa_auth, + struct wpa_channel_info *ci) { - int ret = 0; -#ifdef CONFIG_IEEE80211R - if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) - ret = 1; -#endif /* CONFIG_IEEE80211R */ -#ifdef CONFIG_IEEE80211W - if (wpa_key_mgmt_sha256(sm->wpa_key_mgmt)) - ret = 1; -#endif /* CONFIG_IEEE80211W */ - if (sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) - ret = 1; - return ret; + if (!wpa_auth->cb->channel_info) + return -1; + return wpa_auth->cb->channel_info(wpa_auth->cb_ctx, ci); +} +#endif /* CONFIG_OCV */ + + +static int wpa_auth_update_vlan(struct wpa_authenticator *wpa_auth, + const u8 *addr, int vlan_id) +{ + if (!wpa_auth->cb->update_vlan) + return -1; + return wpa_auth->cb->update_vlan(wpa_auth->cb_ctx, addr, vlan_id); } @@ -307,6 +322,19 @@ static void wpa_rekey_ptk(void *eloop_ctx, void *timeout_ctx) } +void wpa_auth_set_ptk_rekey_timer(struct wpa_state_machine *sm) +{ + if (sm && sm->wpa_auth->conf.wpa_ptk_rekey) { + wpa_printf(MSG_DEBUG, "WPA: Start PTK rekeying timer for " + MACSTR " (%d seconds)", MAC2STR(sm->addr), + sm->wpa_auth->conf.wpa_ptk_rekey); + eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm); + eloop_register_timeout(sm->wpa_auth->conf.wpa_ptk_rekey, 0, + wpa_rekey_ptk, sm->wpa_auth, sm); + } +} + + static int wpa_auth_pmksa_clear_cb(struct wpa_state_machine *sm, void *ctx) { if (sm->pmksa == ctx) @@ -342,6 +370,10 @@ static int wpa_group_init_gmk_and_counter(struct wpa_authenticator *wpa_auth, wpa_get_ntp_timestamp(buf + ETH_ALEN); ptr = (unsigned long) group; os_memcpy(buf + ETH_ALEN + 8, &ptr, sizeof(ptr)); +#ifdef TEST_FUZZ + os_memset(buf + ETH_ALEN, 0xab, 8); + os_memset(buf + ETH_ALEN + 8, 0xcd, sizeof(ptr)); +#endif /* TEST_FUZZ */ if (random_get_bytes(rkey, sizeof(rkey)) < 0) return -1; @@ -411,7 +443,8 @@ static struct wpa_group * wpa_group_init(struct wpa_authenticator *wpa_auth, */ struct wpa_authenticator * wpa_init(const u8 *addr, struct wpa_auth_config *conf, - struct wpa_auth_callbacks *cb) + const struct wpa_auth_callbacks *cb, + void *cb_ctx) { struct wpa_authenticator *wpa_auth; @@ -420,7 +453,8 @@ struct wpa_authenticator * wpa_init(const u8 *addr, return NULL; os_memcpy(wpa_auth->addr, addr, ETH_ALEN); os_memcpy(&wpa_auth->conf, conf, sizeof(*conf)); - os_memcpy(&wpa_auth->cb, cb, sizeof(*cb)); + wpa_auth->cb = cb; + wpa_auth->cb_ctx = cb_ctx; if (wpa_auth_gen_wpa_ie(wpa_auth)) { wpa_printf(MSG_ERROR, "Could not generate WPA IE."); @@ -445,7 +479,7 @@ struct wpa_authenticator * wpa_init(const u8 *addr, return NULL; } -#ifdef CONFIG_IEEE80211R +#ifdef CONFIG_IEEE80211R_AP wpa_auth->ft_pmk_cache = wpa_ft_pmk_cache_init(); if (wpa_auth->ft_pmk_cache == NULL) { wpa_printf(MSG_ERROR, "FT PMK cache initialization failed."); @@ -455,7 +489,7 @@ struct wpa_authenticator * wpa_init(const u8 *addr, os_free(wpa_auth); return NULL; } -#endif /* CONFIG_IEEE80211R */ +#endif /* CONFIG_IEEE80211R_AP */ if (wpa_auth->conf.wpa_gmk_rekey) { eloop_register_timeout(wpa_auth->conf.wpa_gmk_rekey, 0, @@ -508,17 +542,13 @@ void wpa_deinit(struct wpa_authenticator *wpa_auth) eloop_cancel_timeout(wpa_rekey_gmk, wpa_auth, NULL); eloop_cancel_timeout(wpa_rekey_gtk, wpa_auth, NULL); -#ifdef CONFIG_PEERKEY - while (wpa_auth->stsl_negotiations) - wpa_stsl_remove(wpa_auth, wpa_auth->stsl_negotiations); -#endif /* CONFIG_PEERKEY */ - pmksa_cache_auth_deinit(wpa_auth->pmksa); -#ifdef CONFIG_IEEE80211R +#ifdef CONFIG_IEEE80211R_AP wpa_ft_pmk_cache_deinit(wpa_auth->ft_pmk_cache); wpa_auth->ft_pmk_cache = NULL; -#endif /* CONFIG_IEEE80211R */ + wpa_ft_deinit(wpa_auth); +#endif /* CONFIG_IEEE80211R_AP */ #ifdef CONFIG_P2P bitfield_free(wpa_auth->ip_pool); @@ -601,16 +631,28 @@ int wpa_auth_sta_associated(struct wpa_authenticator *wpa_auth, if (wpa_auth == NULL || !wpa_auth->conf.wpa || sm == NULL) return -1; -#ifdef CONFIG_IEEE80211R +#ifdef CONFIG_IEEE80211R_AP if (sm->ft_completed) { wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, "FT authentication already completed - do not " "start 4-way handshake"); /* Go to PTKINITDONE state to allow GTK rekeying */ sm->wpa_ptk_state = WPA_PTK_PTKINITDONE; + sm->Pair = TRUE; + return 0; + } +#endif /* CONFIG_IEEE80211R_AP */ + +#ifdef CONFIG_FILS + if (sm->fils_completed) { + wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, + "FILS authentication already completed - do not start 4-way handshake"); + /* Go to PTKINITDONE state to allow GTK rekeying */ + sm->wpa_ptk_state = WPA_PTK_PTKINITDONE; + sm->Pair = TRUE; return 0; } -#endif /* CONFIG_IEEE80211R */ +#endif /* CONFIG_FILS */ if (sm->started) { os_memset(&sm->key_replay, 0, sizeof(sm->key_replay)); @@ -662,14 +704,17 @@ static void wpa_free_sta_sm(struct wpa_state_machine *sm) sm->group->GKeyDoneStations--; sm->GUpdateStationKeys = FALSE; } -#ifdef CONFIG_IEEE80211R +#ifdef CONFIG_IEEE80211R_AP os_free(sm->assoc_resp_ftie); wpabuf_free(sm->ft_pending_req_ies); -#endif /* CONFIG_IEEE80211R */ +#endif /* CONFIG_IEEE80211R_AP */ os_free(sm->last_rx_eapol_key); os_free(sm->wpa_ie); wpa_group_put(sm->wpa_auth, sm->group); - os_free(sm); +#ifdef CONFIG_DPP2 + wpabuf_clear_free(sm->dpp_z); +#endif /* CONFIG_DPP2 */ + bin_clear_free(sm, sizeof(*sm)); } @@ -682,15 +727,19 @@ void wpa_auth_sta_deinit(struct wpa_state_machine *sm) wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, "strict rekeying - force GTK rekey since STA " "is leaving"); - eloop_cancel_timeout(wpa_rekey_gtk, sm->wpa_auth, NULL); - eloop_register_timeout(0, 500000, wpa_rekey_gtk, sm->wpa_auth, - NULL); + if (eloop_deplete_timeout(0, 500000, wpa_rekey_gtk, + sm->wpa_auth, NULL) == -1) + eloop_register_timeout(0, 500000, wpa_rekey_gtk, sm->wpa_auth, + NULL); } eloop_cancel_timeout(wpa_send_eapol_timeout, sm->wpa_auth, sm); sm->pending_1_of_4_timeout = 0; eloop_cancel_timeout(wpa_sm_call_step, sm, NULL); eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm); +#ifdef CONFIG_IEEE80211R_AP + wpa_ft_sta_deinit(sm); +#endif /* CONFIG_IEEE80211R_AP */ if (sm->in_step_loop) { /* Must not free state machine while wpa_sm_step() is running. * Freeing will be completed in the end of wpa_sm_step(). */ @@ -741,7 +790,7 @@ static void wpa_replay_counter_mark_invalid(struct wpa_key_replay_counter *ctr, } -#ifdef CONFIG_IEEE80211R +#ifdef CONFIG_IEEE80211R_AP static int ft_check_msg_2_of_4(struct wpa_authenticator *wpa_auth, struct wpa_state_machine *sm, struct wpa_eapol_ie_parse *kde) @@ -788,7 +837,7 @@ static int ft_check_msg_2_of_4(struct wpa_authenticator *wpa_auth, return 0; } -#endif /* CONFIG_IEEE80211R */ +#endif /* CONFIG_IEEE80211R_AP */ static int wpa_receive_error_report(struct wpa_authenticator *wpa_auth, @@ -830,29 +879,44 @@ static int wpa_try_alt_snonce(struct wpa_state_machine *sm, u8 *data, struct wpa_ptk PTK; int ok = 0; const u8 *pmk = NULL; - unsigned int pmk_len; + size_t pmk_len; + int vlan_id = 0; + os_memset(&PTK, 0, sizeof(PTK)); for (;;) { - if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) { + if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) && + !wpa_key_mgmt_sae(sm->wpa_key_mgmt)) { pmk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, - sm->p2p_dev_addr, pmk); + sm->p2p_dev_addr, pmk, &pmk_len, + &vlan_id); if (pmk == NULL) break; - pmk_len = PMK_LEN; +#ifdef CONFIG_IEEE80211R_AP + if (wpa_key_mgmt_ft_psk(sm->wpa_key_mgmt)) { + os_memcpy(sm->xxkey, pmk, pmk_len); + sm->xxkey_len = pmk_len; + } +#endif /* CONFIG_IEEE80211R_AP */ } else { pmk = sm->PMK; pmk_len = sm->pmk_len; } - wpa_derive_ptk(sm, sm->alt_SNonce, pmk, pmk_len, &PTK); + if (wpa_derive_ptk(sm, sm->alt_SNonce, pmk, pmk_len, &PTK) < 0) + break; - if (wpa_verify_key_mic(sm->wpa_key_mgmt, &PTK, data, data_len) - == 0) { + if (wpa_verify_key_mic(sm->wpa_key_mgmt, pmk_len, &PTK, + data, data_len) == 0) { + if (sm->PMK != pmk) { + os_memcpy(sm->PMK, pmk, pmk_len); + sm->pmk_len = pmk_len; + } ok = 1; break; } - if (!wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) + if (!wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) || + wpa_key_mgmt_sae(sm->wpa_key_mgmt)) break; } @@ -865,6 +929,11 @@ static int wpa_try_alt_snonce(struct wpa_state_machine *sm, u8 *data, wpa_printf(MSG_DEBUG, "WPA: Earlier SNonce resulted in matching MIC"); sm->alt_snonce_valid = 0; + + if (vlan_id && wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) && + wpa_auth_update_vlan(sm->wpa_auth, sm->addr, vlan_id) < 0) + return -1; + os_memcpy(sm->SNonce, sm->alt_SNonce, WPA_NONCE_LEN); os_memcpy(&sm->PTK, &PTK, sizeof(PTK)); sm->PTK_valid = TRUE; @@ -879,39 +948,41 @@ void wpa_receive(struct wpa_authenticator *wpa_auth, { struct ieee802_1x_hdr *hdr; struct wpa_eapol_key *key; - struct wpa_eapol_key_192 *key192; u16 key_info, key_data_length; - enum { PAIRWISE_2, PAIRWISE_4, GROUP_2, REQUEST, - SMK_M1, SMK_M3, SMK_ERROR } msg; + enum { PAIRWISE_2, PAIRWISE_4, GROUP_2, REQUEST } msg; char *msgtxt; struct wpa_eapol_ie_parse kde; - int ft; - const u8 *eapol_key_ie, *key_data; - size_t eapol_key_ie_len, keyhdrlen, mic_len; + const u8 *key_data; + size_t keyhdrlen, mic_len; + u8 *mic; if (wpa_auth == NULL || !wpa_auth->conf.wpa || sm == NULL) return; + wpa_hexdump(MSG_MSGDUMP, "WPA: RX EAPOL data", data, data_len); - mic_len = wpa_mic_len(sm->wpa_key_mgmt); - keyhdrlen = mic_len == 24 ? sizeof(*key192) : sizeof(*key); + mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len); + keyhdrlen = sizeof(*key) + mic_len + 2; - if (data_len < sizeof(*hdr) + keyhdrlen) + if (data_len < sizeof(*hdr) + keyhdrlen) { + wpa_printf(MSG_DEBUG, "WPA: Ignore too short EAPOL-Key frame"); return; + } hdr = (struct ieee802_1x_hdr *) data; key = (struct wpa_eapol_key *) (hdr + 1); - key192 = (struct wpa_eapol_key_192 *) (hdr + 1); + mic = (u8 *) (key + 1); key_info = WPA_GET_BE16(key->key_info); - if (mic_len == 24) { - key_data = (const u8 *) (key192 + 1); - key_data_length = WPA_GET_BE16(key192->key_data_length); - } else { - key_data = (const u8 *) (key + 1); - key_data_length = WPA_GET_BE16(key->key_data_length); - } + key_data = mic + mic_len + 2; + key_data_length = WPA_GET_BE16(mic + mic_len); wpa_printf(MSG_DEBUG, "WPA: Received EAPOL-Key from " MACSTR - " key_info=0x%x type=%u key_data_length=%u", - MAC2STR(sm->addr), key_info, key->type, key_data_length); + " key_info=0x%x type=%u mic_len=%u key_data_length=%u", + MAC2STR(sm->addr), key_info, key->type, + (unsigned int) mic_len, key_data_length); + wpa_hexdump(MSG_MSGDUMP, + "WPA: EAPOL-Key header (ending before Key MIC)", + key, sizeof(*key)); + wpa_hexdump(MSG_MSGDUMP, "WPA: EAPOL-Key Key MIC", + mic, mic_len); if (key_data_length > data_len - sizeof(*hdr) - keyhdrlen) { wpa_printf(MSG_INFO, "WPA: Invalid EAPOL-Key frame - " "key_data overflow (%d > %lu)", @@ -952,25 +1023,20 @@ void wpa_receive(struct wpa_authenticator *wpa_auth, /* FIX: verify that the EAPOL-Key frame was encrypted if pairwise keys * are set */ - if ((key_info & (WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_REQUEST)) == - (WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_REQUEST)) { - if (key_info & WPA_KEY_INFO_ERROR) { - msg = SMK_ERROR; - msgtxt = "SMK Error"; - } else { - msg = SMK_M1; - msgtxt = "SMK M1"; - } - } else if (key_info & WPA_KEY_INFO_SMK_MESSAGE) { - msg = SMK_M3; - msgtxt = "SMK M3"; - } else if (key_info & WPA_KEY_INFO_REQUEST) { + if (key_info & WPA_KEY_INFO_SMK_MESSAGE) { + wpa_printf(MSG_DEBUG, "WPA: Ignore SMK message"); + return; + } + + if (key_info & WPA_KEY_INFO_REQUEST) { msg = REQUEST; msgtxt = "Request"; } else if (!(key_info & WPA_KEY_INFO_KEY_TYPE)) { msg = GROUP_2; msgtxt = "2/2 Group"; - } else if (key_data_length == 0) { + } else if (key_data_length == 0 || + (mic_len == 0 && (key_info & WPA_KEY_INFO_ENCR_KEY_DATA) && + key_data_length == AES_BLOCK_SIZE)) { msg = PAIRWISE_4; msgtxt = "4/4 Pairwise"; } else { @@ -978,15 +1044,13 @@ void wpa_receive(struct wpa_authenticator *wpa_auth, msgtxt = "2/4 Pairwise"; } - /* TODO: key_info type validation for PeerKey */ if (msg == REQUEST || msg == PAIRWISE_2 || msg == PAIRWISE_4 || msg == GROUP_2) { u16 ver = key_info & WPA_KEY_INFO_TYPE_MASK; if (sm->pairwise == WPA_CIPHER_CCMP || sm->pairwise == WPA_CIPHER_GCMP) { - if (wpa_use_aes_cmac(sm) && - sm->wpa_key_mgmt != WPA_KEY_MGMT_OSEN && - !wpa_key_mgmt_suite_b(sm->wpa_key_mgmt) && + if (wpa_use_cmac(sm->wpa_key_mgmt) && + !wpa_use_akm_defined(sm->wpa_key_mgmt) && ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) { wpa_auth_logger(wpa_auth, sm->addr, LOGGER_WARNING, @@ -996,7 +1060,8 @@ void wpa_receive(struct wpa_authenticator *wpa_auth, return; } - if (!wpa_use_aes_cmac(sm) && + if (!wpa_use_cmac(sm->wpa_key_mgmt) && + !wpa_use_akm_defined(sm->wpa_key_mgmt) && ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { wpa_auth_logger(wpa_auth, sm->addr, LOGGER_WARNING, @@ -1006,7 +1071,7 @@ void wpa_receive(struct wpa_authenticator *wpa_auth, } } - if (wpa_key_mgmt_suite_b(sm->wpa_key_mgmt) && + if (wpa_use_akm_defined(sm->wpa_key_mgmt) && ver != WPA_KEY_INFO_TYPE_AKM_DEFINED) { wpa_auth_logger(wpa_auth, sm->addr, LOGGER_WARNING, "did not use EAPOL-Key descriptor version 0 as required for AKM-defined cases"); @@ -1094,6 +1159,15 @@ void wpa_receive(struct wpa_authenticator *wpa_auth, } continue_processing: +#ifdef CONFIG_FILS + if (sm->wpa == WPA_VERSION_WPA2 && mic_len == 0 && + !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) { + wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG, + "WPA: Encr Key Data bit not set even though AEAD cipher is supposed to be used - drop frame"); + return; + } +#endif /* CONFIG_FILS */ + switch (msg) { case PAIRWISE_2: if (sm->wpa_ptk_state != WPA_PTK_PTKSTART && @@ -1121,70 +1195,10 @@ continue_processing: "collect more entropy for random number " "generation"); random_mark_pool_ready(); - wpa_sta_disconnect(wpa_auth, sm->addr); + wpa_sta_disconnect(wpa_auth, sm->addr, + WLAN_REASON_PREV_AUTH_NOT_VALID); return; } - if (wpa_parse_kde_ies(key_data, key_data_length, &kde) < 0) { - wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, - "received EAPOL-Key msg 2/4 with " - "invalid Key Data contents"); - return; - } - if (kde.rsn_ie) { - eapol_key_ie = kde.rsn_ie; - eapol_key_ie_len = kde.rsn_ie_len; - } else if (kde.osen) { - eapol_key_ie = kde.osen; - eapol_key_ie_len = kde.osen_len; - } else { - eapol_key_ie = kde.wpa_ie; - eapol_key_ie_len = kde.wpa_ie_len; - } - ft = sm->wpa == WPA_VERSION_WPA2 && - wpa_key_mgmt_ft(sm->wpa_key_mgmt); - if (sm->wpa_ie == NULL || - wpa_compare_rsn_ie(ft, - sm->wpa_ie, sm->wpa_ie_len, - eapol_key_ie, eapol_key_ie_len)) { - wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, - "WPA IE from (Re)AssocReq did not " - "match with msg 2/4"); - if (sm->wpa_ie) { - wpa_hexdump(MSG_DEBUG, "WPA IE in AssocReq", - sm->wpa_ie, sm->wpa_ie_len); - } - wpa_hexdump(MSG_DEBUG, "WPA IE in msg 2/4", - eapol_key_ie, eapol_key_ie_len); - /* MLME-DEAUTHENTICATE.request */ - wpa_sta_disconnect(wpa_auth, sm->addr); - return; - } -#ifdef CONFIG_IEEE80211R - if (ft && ft_check_msg_2_of_4(wpa_auth, sm, &kde) < 0) { - wpa_sta_disconnect(wpa_auth, sm->addr); - return; - } -#endif /* CONFIG_IEEE80211R */ -#ifdef CONFIG_P2P - if (kde.ip_addr_req && kde.ip_addr_req[0] && - wpa_auth->ip_pool && WPA_GET_BE32(sm->ip_addr) == 0) { - int idx; - wpa_printf(MSG_DEBUG, "P2P: IP address requested in " - "EAPOL-Key exchange"); - idx = bitfield_get_first_zero(wpa_auth->ip_pool); - if (idx >= 0) { - u32 start = WPA_GET_BE32(wpa_auth->conf. - ip_addr_start); - bitfield_set(wpa_auth->ip_pool, idx); - WPA_PUT_BE32(sm->ip_addr, start + idx); - wpa_printf(MSG_DEBUG, "P2P: Assigned IP " - "address %u.%u.%u.%u to " MACSTR, - sm->ip_addr[0], sm->ip_addr[1], - sm->ip_addr[2], sm->ip_addr[3], - MAC2STR(sm->addr)); - } - } -#endif /* CONFIG_P2P */ break; case PAIRWISE_4: if (sm->wpa_ptk_state != WPA_PTK_PTKINITNEGOTIATING || @@ -1206,28 +1220,6 @@ continue_processing: return; } break; -#ifdef CONFIG_PEERKEY - case SMK_M1: - case SMK_M3: - case SMK_ERROR: - if (!wpa_auth->conf.peerkey) { - wpa_printf(MSG_DEBUG, "RSN: SMK M1/M3/Error, but " - "PeerKey use disabled - ignoring message"); - return; - } - if (!sm->PTK_valid) { - wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, - "received EAPOL-Key msg SMK in " - "invalid state - dropped"); - return; - } - break; -#else /* CONFIG_PEERKEY */ - case SMK_M1: - case SMK_M3: - case SMK_ERROR: - return; /* STSL disabled - ignore SMK messages */ -#endif /* CONFIG_PEERKEY */ case REQUEST: break; } @@ -1241,22 +1233,55 @@ continue_processing: return; } - if (!(key_info & WPA_KEY_INFO_MIC)) { + if (!wpa_key_mgmt_fils(sm->wpa_key_mgmt) && + !(key_info & WPA_KEY_INFO_MIC)) { wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, "received invalid EAPOL-Key: Key MIC not set"); return; } +#ifdef CONFIG_FILS + if (wpa_key_mgmt_fils(sm->wpa_key_mgmt) && + (key_info & WPA_KEY_INFO_MIC)) { + wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, + "received invalid EAPOL-Key: Key MIC set"); + return; + } +#endif /* CONFIG_FILS */ + sm->MICVerified = FALSE; if (sm->PTK_valid && !sm->update_snonce) { - if (wpa_verify_key_mic(sm->wpa_key_mgmt, &sm->PTK, data, - data_len) && + if (mic_len && + wpa_verify_key_mic(sm->wpa_key_mgmt, sm->pmk_len, &sm->PTK, + data, data_len) && (msg != PAIRWISE_4 || !sm->alt_snonce_valid || wpa_try_alt_snonce(sm, data, data_len))) { wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, "received EAPOL-Key with invalid MIC"); +#ifdef TEST_FUZZ + wpa_printf(MSG_INFO, + "TEST: Ignore Key MIC failure for fuzz testing"); + goto continue_fuzz; +#endif /* TEST_FUZZ */ + return; + } +#ifdef CONFIG_FILS + if (!mic_len && + wpa_aead_decrypt(sm, &sm->PTK, data, data_len, + &key_data_length) < 0) { + wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, + "received EAPOL-Key with invalid MIC"); +#ifdef TEST_FUZZ + wpa_printf(MSG_INFO, + "TEST: Ignore Key MIC failure for fuzz testing"); + goto continue_fuzz; +#endif /* TEST_FUZZ */ return; } +#endif /* CONFIG_FILS */ +#ifdef TEST_FUZZ + continue_fuzz: +#endif /* TEST_FUZZ */ sm->MICVerified = TRUE; eloop_cancel_timeout(wpa_send_eapol_timeout, wpa_auth, sm); sm->pending_1_of_4_timeout = 0; @@ -1279,12 +1304,7 @@ continue_processing: * even though MAC address KDE is not normally encrypted, * supplicant is allowed to encrypt it. */ - if (msg == SMK_ERROR) { -#ifdef CONFIG_PEERKEY - wpa_smk_error(wpa_auth, sm, key_data, key_data_length); -#endif /* CONFIG_PEERKEY */ - return; - } else if (key_info & WPA_KEY_INFO_ERROR) { + if (key_info & WPA_KEY_INFO_ERROR) { if (wpa_receive_error_report( wpa_auth, sm, !(key_info & WPA_KEY_INFO_KEY_TYPE)) > 0) @@ -1294,11 +1314,6 @@ continue_processing: "received EAPOL-Key Request for new " "4-Way Handshake"); wpa_request_new_ptk(sm); -#ifdef CONFIG_PEERKEY - } else if (msg == SMK_M1) { - wpa_smk_m1(wpa_auth, sm, key, key_data, - key_data_length); -#endif /* CONFIG_PEERKEY */ } else if (key_data_length > 0 && wpa_parse_kde_ies(key_data, key_data_length, &kde) == 0 && @@ -1337,18 +1352,10 @@ continue_processing: wpa_replay_counter_mark_invalid(sm->key_replay, NULL); } -#ifdef CONFIG_PEERKEY - if (msg == SMK_M3) { - wpa_smk_m3(wpa_auth, sm, key, key_data, key_data_length); - return; - } -#endif /* CONFIG_PEERKEY */ - os_free(sm->last_rx_eapol_key); - sm->last_rx_eapol_key = os_malloc(data_len); + sm->last_rx_eapol_key = os_memdup(data, data_len); if (sm->last_rx_eapol_key == NULL) return; - os_memcpy(sm->last_rx_eapol_key, data, data_len); sm->last_rx_eapol_key_len = data_len; sm->rx_eapol_key_secure = !!(key_info & WPA_KEY_INFO_SECURE); @@ -1363,7 +1370,7 @@ continue_processing: static int wpa_gmk_to_gtk(const u8 *gmk, const char *label, const u8 *addr, const u8 *gnonce, u8 *gtk, size_t gtk_len) { - u8 data[ETH_ALEN + WPA_NONCE_LEN + 8 + 16]; + u8 data[ETH_ALEN + WPA_NONCE_LEN + 8 + WPA_GTK_MAX_LEN]; u8 *pos; int ret = 0; @@ -1374,21 +1381,33 @@ static int wpa_gmk_to_gtk(const u8 *gmk, const char *label, const u8 *addr, * is done only at the Authenticator and as such, does not need to be * exactly same. */ + os_memset(data, 0, sizeof(data)); os_memcpy(data, addr, ETH_ALEN); os_memcpy(data + ETH_ALEN, gnonce, WPA_NONCE_LEN); pos = data + ETH_ALEN + WPA_NONCE_LEN; wpa_get_ntp_timestamp(pos); +#ifdef TEST_FUZZ + os_memset(pos, 0xef, 8); +#endif /* TEST_FUZZ */ pos += 8; - if (random_get_bytes(pos, 16) < 0) + if (random_get_bytes(pos, gtk_len) < 0) ret = -1; -#ifdef CONFIG_IEEE80211W - sha256_prf(gmk, WPA_GMK_LEN, label, data, sizeof(data), gtk, gtk_len); -#else /* CONFIG_IEEE80211W */ - if (sha1_prf(gmk, WPA_GMK_LEN, label, data, sizeof(data), gtk, gtk_len) - < 0) +#ifdef CONFIG_SHA384 + if (sha384_prf(gmk, WPA_GMK_LEN, label, data, sizeof(data), + gtk, gtk_len) < 0) ret = -1; -#endif /* CONFIG_IEEE80211W */ +#else /* CONFIG_SHA384 */ +#ifdef CONFIG_SHA256 + if (sha256_prf(gmk, WPA_GMK_LEN, label, data, sizeof(data), + gtk, gtk_len) < 0) + ret = -1; +#else /* CONFIG_SHA256 */ + if (sha1_prf(gmk, WPA_GMK_LEN, label, data, sizeof(data), + gtk, gtk_len) < 0) + ret = -1; +#endif /* CONFIG_SHA256 */ +#endif /* CONFIG_SHA384 */ return ret; } @@ -1414,26 +1433,24 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, { struct ieee802_1x_hdr *hdr; struct wpa_eapol_key *key; - struct wpa_eapol_key_192 *key192; size_t len, mic_len, keyhdrlen; int alg; int key_data_len, pad_len = 0; u8 *buf, *pos; int version, pairwise; int i; - u8 *key_data; + u8 *key_mic, *key_data; - mic_len = wpa_mic_len(sm->wpa_key_mgmt); - keyhdrlen = mic_len == 24 ? sizeof(*key192) : sizeof(*key); + mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len); + keyhdrlen = sizeof(*key) + mic_len + 2; len = sizeof(struct ieee802_1x_hdr) + keyhdrlen; if (force_version) version = force_version; - else if (sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN || - wpa_key_mgmt_suite_b(sm->wpa_key_mgmt)) + else if (wpa_use_akm_defined(sm->wpa_key_mgmt)) version = WPA_KEY_INFO_TYPE_AKM_DEFINED; - else if (wpa_use_aes_cmac(sm)) + else if (wpa_use_cmac(sm->wpa_key_mgmt)) version = WPA_KEY_INFO_TYPE_AES_128_CMAC; else if (sm->pairwise != WPA_CIPHER_TKIP) version = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES; @@ -1455,8 +1472,7 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, key_data_len = kde_len; if ((version == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES || - sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN || - wpa_key_mgmt_suite_b(sm->wpa_key_mgmt) || + wpa_use_aes_key_wrap(sm->wpa_key_mgmt) || version == WPA_KEY_INFO_TYPE_AES_128_CMAC) && encr) { pad_len = key_data_len % 8; if (pad_len) @@ -1465,6 +1481,8 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, } len += key_data_len; + if (!mic_len && encr) + len += AES_BLOCK_SIZE; hdr = os_zalloc(len); if (hdr == NULL) @@ -1473,7 +1491,7 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, hdr->type = IEEE802_1X_TYPE_EAPOL_KEY; hdr->length = host_to_be16(len - sizeof(*hdr)); key = (struct wpa_eapol_key *) (hdr + 1); - key192 = (struct wpa_eapol_key_192 *) (hdr + 1); + key_mic = (u8 *) (key + 1); key_data = ((u8 *) (hdr + 1)) + keyhdrlen; key->type = sm->wpa == WPA_VERSION_WPA2 ? @@ -1486,11 +1504,11 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, WPA_PUT_BE16(key->key_info, key_info); alg = pairwise ? sm->pairwise : wpa_auth->conf.wpa_group; - WPA_PUT_BE16(key->key_length, wpa_cipher_key_len(alg)); - if (key_info & WPA_KEY_INFO_SMK_MESSAGE) + if (sm->wpa == WPA_VERSION_WPA2 && !pairwise) WPA_PUT_BE16(key->key_length, 0); + else + WPA_PUT_BE16(key->key_length, wpa_cipher_key_len(alg)); - /* FIX: STSL: what to use as key_replay_counter? */ for (i = RSNA_MAX_EAPOL_RETRIES - 1; i > 0; i--) { sm->key_replay[i].valid = sm->key_replay[i - 1].valid; os_memcpy(sm->key_replay[i].counter, @@ -1512,10 +1530,31 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, if (kde && !encr) { os_memcpy(key_data, kde, kde_len); - if (mic_len == 24) - WPA_PUT_BE16(key192->key_data_length, kde_len); - else - WPA_PUT_BE16(key->key_data_length, kde_len); + WPA_PUT_BE16(key_mic + mic_len, kde_len); +#ifdef CONFIG_FILS + } else if (!mic_len && kde) { + const u8 *aad[1]; + size_t aad_len[1]; + + WPA_PUT_BE16(key_mic, AES_BLOCK_SIZE + kde_len); + wpa_hexdump_key(MSG_DEBUG, "Plaintext EAPOL-Key Key Data", + kde, kde_len); + + wpa_hexdump_key(MSG_DEBUG, "WPA: KEK", + sm->PTK.kek, sm->PTK.kek_len); + /* AES-SIV AAD from EAPOL protocol version field (inclusive) to + * to Key Data (exclusive). */ + aad[0] = (u8 *) hdr; + aad_len[0] = key_mic + 2 - (u8 *) hdr; + if (aes_siv_encrypt(sm->PTK.kek, sm->PTK.kek_len, kde, kde_len, + 1, aad, aad_len, key_mic + 2) < 0) { + wpa_printf(MSG_DEBUG, "WPA: AES-SIV encryption failed"); + return; + } + + wpa_hexdump(MSG_DEBUG, "WPA: Encrypted Key Data from SIV", + key_mic + 2, AES_BLOCK_SIZE + kde_len); +#endif /* CONFIG_FILS */ } else if (encr && kde) { buf = os_zalloc(key_data_len); if (buf == NULL) { @@ -1532,24 +1571,24 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, wpa_hexdump_key(MSG_DEBUG, "Plaintext EAPOL-Key Key Data", buf, key_data_len); if (version == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES || - sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN || - wpa_key_mgmt_suite_b(sm->wpa_key_mgmt) || + wpa_use_aes_key_wrap(sm->wpa_key_mgmt) || version == WPA_KEY_INFO_TYPE_AES_128_CMAC) { + wpa_printf(MSG_DEBUG, + "WPA: Encrypt Key Data using AES-WRAP (KEK length %u)", + (unsigned int) sm->PTK.kek_len); if (aes_wrap(sm->PTK.kek, sm->PTK.kek_len, (key_data_len - 8) / 8, buf, key_data)) { os_free(hdr); os_free(buf); return; } - if (mic_len == 24) - WPA_PUT_BE16(key192->key_data_length, - key_data_len); - else - WPA_PUT_BE16(key->key_data_length, - key_data_len); + WPA_PUT_BE16(key_mic + mic_len, key_data_len); #ifndef CONFIG_NO_RC4 } else if (sm->PTK.kek_len == 16) { u8 ek[32]; + + wpa_printf(MSG_DEBUG, + "WPA: Encrypt Key Data using RC4"); os_memcpy(key->key_iv, sm->group->Counter + WPA_NONCE_LEN - 16, 16); inc_byte_array(sm->group->Counter, WPA_NONCE_LEN); @@ -1557,12 +1596,7 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, os_memcpy(ek + 16, sm->PTK.kek, sm->PTK.kek_len); os_memcpy(key_data, buf, key_data_len); rc4_skip(ek, 32, 256, key_data, key_data_len); - if (mic_len == 24) - WPA_PUT_BE16(key192->key_data_length, - key_data_len); - else - WPA_PUT_BE16(key->key_data_length, - key_data_len); + WPA_PUT_BE16(key_mic + mic_len, key_data_len); #endif /* CONFIG_NO_RC4 */ } else { os_free(hdr); @@ -1573,9 +1607,7 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, } if (key_info & WPA_KEY_INFO_MIC) { - u8 *key_mic; - - if (!sm->PTK_valid) { + if (!sm->PTK_valid || !mic_len) { wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, "PTK not valid when sending EAPOL-Key " "frame"); @@ -1583,10 +1615,12 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, return; } - key_mic = key192->key_mic; /* same offset for key and key192 */ - wpa_eapol_key_mic(sm->PTK.kck, sm->PTK.kck_len, - sm->wpa_key_mgmt, version, - (u8 *) hdr, len, key_mic); + if (wpa_eapol_key_mic(sm->PTK.kck, sm->PTK.kck_len, + sm->wpa_key_mgmt, version, + (u8 *) hdr, len, key_mic) < 0) { + os_free(hdr); + return; + } #ifdef CONFIG_TESTING_OPTIONS if (!pairwise && wpa_auth->conf.corrupt_gtk_rekey_mic_probability > 0.0 && @@ -1615,7 +1649,7 @@ static void wpa_send_eapol(struct wpa_authenticator *wpa_auth, { int timeout_ms; int pairwise = key_info & WPA_KEY_INFO_KEY_TYPE; - int ctr; + u32 ctr; if (sm == NULL) return; @@ -1629,41 +1663,46 @@ static void wpa_send_eapol(struct wpa_authenticator *wpa_auth, eapol_key_timeout_first_group; else timeout_ms = eapol_key_timeout_subseq; + if (wpa_auth->conf.wpa_disable_eapol_key_retries && + (!pairwise || (key_info & WPA_KEY_INFO_MIC))) + timeout_ms = eapol_key_timeout_no_retrans; if (pairwise && ctr == 1 && !(key_info & WPA_KEY_INFO_MIC)) sm->pending_1_of_4_timeout = 1; +#ifdef TEST_FUZZ + timeout_ms = 1; +#endif /* TEST_FUZZ */ wpa_printf(MSG_DEBUG, "WPA: Use EAPOL-Key timeout of %u ms (retry " - "counter %d)", timeout_ms, ctr); + "counter %u)", timeout_ms, ctr); eloop_register_timeout(timeout_ms / 1000, (timeout_ms % 1000) * 1000, wpa_send_eapol_timeout, wpa_auth, sm); } -static int wpa_verify_key_mic(int akmp, struct wpa_ptk *PTK, u8 *data, - size_t data_len) +static int wpa_verify_key_mic(int akmp, size_t pmk_len, struct wpa_ptk *PTK, + u8 *data, size_t data_len) { struct ieee802_1x_hdr *hdr; struct wpa_eapol_key *key; - struct wpa_eapol_key_192 *key192; u16 key_info; int ret = 0; - u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN]; - size_t mic_len = wpa_mic_len(akmp); + u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN], *mic_pos; + size_t mic_len = wpa_mic_len(akmp, pmk_len); if (data_len < sizeof(*hdr) + sizeof(*key)) return -1; hdr = (struct ieee802_1x_hdr *) data; key = (struct wpa_eapol_key *) (hdr + 1); - key192 = (struct wpa_eapol_key_192 *) (hdr + 1); + mic_pos = (u8 *) (key + 1); key_info = WPA_GET_BE16(key->key_info); - os_memcpy(mic, key192->key_mic, mic_len); - os_memset(key192->key_mic, 0, mic_len); + os_memcpy(mic, mic_pos, mic_len); + os_memset(mic_pos, 0, mic_len); if (wpa_eapol_key_mic(PTK->kck, PTK->kck_len, akmp, key_info & WPA_KEY_INFO_TYPE_MASK, - data, data_len, key192->key_mic) || - os_memcmp_const(mic, key192->key_mic, mic_len) != 0) + data, data_len, mic_pos) || + os_memcmp_const(mic, mic_pos, mic_len) != 0) ret = -1; - os_memcpy(key192->key_mic, mic, mic_len); + os_memcpy(mic_pos, mic, mic_len); return ret; } @@ -1672,7 +1711,10 @@ void wpa_remove_ptk(struct wpa_state_machine *sm) { sm->PTK_valid = FALSE; os_memset(&sm->PTK, 0, sizeof(sm->PTK)); - wpa_auth_set_key(sm->wpa_auth, 0, WPA_ALG_NONE, sm->addr, 0, NULL, 0); + if (wpa_auth_set_key(sm->wpa_auth, 0, WPA_ALG_NONE, sm->addr, 0, NULL, + 0)) + wpa_printf(MSG_DEBUG, + "RSN: PTK removal from the driver failed"); sm->pairwise_set = FALSE; eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm); } @@ -1703,6 +1745,14 @@ int wpa_auth_sm_event(struct wpa_state_machine *sm, enum wpa_event event) case WPA_DEAUTH: case WPA_DISASSOC: sm->DeauthenticationRequest = TRUE; +#ifdef CONFIG_IEEE80211R_AP + os_memset(sm->PMK, 0, sizeof(sm->PMK)); + sm->pmk_len = 0; + os_memset(sm->xxkey, 0, sizeof(sm->xxkey)); + sm->xxkey_len = 0; + os_memset(sm->pmk_r1, 0, sizeof(sm->pmk_r1)); + sm->pmk_r1_len = 0; +#endif /* CONFIG_IEEE80211R_AP */ break; case WPA_REAUTH: case WPA_REAUTH_EAPOL: @@ -1736,30 +1786,46 @@ int wpa_auth_sm_event(struct wpa_state_machine *sm, enum wpa_event event) sm->ReAuthenticationRequest = TRUE; break; case WPA_ASSOC_FT: -#ifdef CONFIG_IEEE80211R +#ifdef CONFIG_IEEE80211R_AP wpa_printf(MSG_DEBUG, "FT: Retry PTK configuration " "after association"); wpa_ft_install_ptk(sm); /* Using FT protocol, not WPA auth state machine */ sm->ft_completed = 1; + wpa_auth_set_ptk_rekey_timer(sm); return 0; -#else /* CONFIG_IEEE80211R */ +#else /* CONFIG_IEEE80211R_AP */ break; -#endif /* CONFIG_IEEE80211R */ +#endif /* CONFIG_IEEE80211R_AP */ + case WPA_ASSOC_FILS: +#ifdef CONFIG_FILS + wpa_printf(MSG_DEBUG, + "FILS: TK configuration after association"); + fils_set_tk(sm); + sm->fils_completed = 1; + return 0; +#else /* CONFIG_FILS */ + break; +#endif /* CONFIG_FILS */ case WPA_DRV_STA_REMOVED: sm->tk_already_set = FALSE; return 0; } -#ifdef CONFIG_IEEE80211R +#ifdef CONFIG_IEEE80211R_AP sm->ft_completed = 0; -#endif /* CONFIG_IEEE80211R */ +#endif /* CONFIG_IEEE80211R_AP */ #ifdef CONFIG_IEEE80211W if (sm->mgmt_frame_prot && event == WPA_AUTH) remove_ptk = 0; #endif /* CONFIG_IEEE80211W */ +#ifdef CONFIG_FILS + if (wpa_key_mgmt_fils(sm->wpa_key_mgmt) && + (event == WPA_AUTH || event == WPA_ASSOC)) + remove_ptk = 0; +#endif /* CONFIG_FILS */ if (remove_ptk) { sm->PTK_valid = FALSE; @@ -1804,7 +1870,9 @@ SM_STATE(WPA_PTK, INITIALIZE) wpa_remove_ptk(sm); wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portValid, 0); sm->TimeoutCtr = 0; - if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) { + if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) || + sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP || + sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE) { wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_authorized, 0); } @@ -1813,9 +1881,14 @@ SM_STATE(WPA_PTK, INITIALIZE) SM_STATE(WPA_PTK, DISCONNECT) { + u16 reason = sm->disconnect_reason; + SM_ENTRY_MA(WPA_PTK, DISCONNECT, wpa_ptk); sm->Disconnect = FALSE; - wpa_sta_disconnect(sm->wpa_auth, sm->addr); + sm->disconnect_reason = 0; + if (!reason) + reason = WLAN_REASON_PREV_AUTH_NOT_VALID; + wpa_sta_disconnect(sm->wpa_auth, sm->addr, reason); } @@ -1924,17 +1997,25 @@ SM_STATE(WPA_PTK, INITPMK) size_t len = 2 * PMK_LEN; SM_ENTRY_MA(WPA_PTK, INITPMK, wpa_ptk); -#ifdef CONFIG_IEEE80211R +#ifdef CONFIG_IEEE80211R_AP sm->xxkey_len = 0; -#endif /* CONFIG_IEEE80211R */ +#endif /* CONFIG_IEEE80211R_AP */ if (sm->pmksa) { wpa_printf(MSG_DEBUG, "WPA: PMK from PMKSA cache"); os_memcpy(sm->PMK, sm->pmksa->pmk, sm->pmksa->pmk_len); sm->pmk_len = sm->pmksa->pmk_len; +#ifdef CONFIG_DPP + } else if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP) { + wpa_printf(MSG_DEBUG, + "DPP: No PMKSA cache entry for STA - reject connection"); + sm->Disconnect = TRUE; + sm->disconnect_reason = WLAN_REASON_INVALID_PMKID; + return; +#endif /* CONFIG_DPP */ } else if (wpa_auth_get_msk(sm->wpa_auth, sm->addr, msk, &len) == 0) { unsigned int pmk_len; - if (sm->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) + if (wpa_key_mgmt_sha384(sm->wpa_key_mgmt)) pmk_len = PMK_LEN_SUITE_B_192; else pmk_len = PMK_LEN; @@ -1950,15 +2031,20 @@ SM_STATE(WPA_PTK, INITPMK) } os_memcpy(sm->PMK, msk, pmk_len); sm->pmk_len = pmk_len; -#ifdef CONFIG_IEEE80211R +#ifdef CONFIG_IEEE80211R_AP if (len >= 2 * PMK_LEN) { - os_memcpy(sm->xxkey, msk + PMK_LEN, PMK_LEN); - sm->xxkey_len = PMK_LEN; + if (wpa_key_mgmt_sha384(sm->wpa_key_mgmt)) { + os_memcpy(sm->xxkey, msk, SHA384_MAC_LEN); + sm->xxkey_len = SHA384_MAC_LEN; + } else { + os_memcpy(sm->xxkey, msk + PMK_LEN, PMK_LEN); + sm->xxkey_len = PMK_LEN; + } } -#endif /* CONFIG_IEEE80211R */ +#endif /* CONFIG_IEEE80211R_AP */ } else { wpa_printf(MSG_DEBUG, "WPA: Could not get PMK, get_msk: %p", - sm->wpa_auth->cb.get_msk); + sm->wpa_auth->cb->get_msk); sm->Disconnect = TRUE; return; } @@ -1980,16 +2066,30 @@ SM_STATE(WPA_PTK, INITPMK) SM_STATE(WPA_PTK, INITPSK) { const u8 *psk; + size_t psk_len; + SM_ENTRY_MA(WPA_PTK, INITPSK, wpa_ptk); - psk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, sm->p2p_dev_addr, NULL); + psk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, sm->p2p_dev_addr, NULL, + &psk_len, NULL); if (psk) { - os_memcpy(sm->PMK, psk, PMK_LEN); - sm->pmk_len = PMK_LEN; -#ifdef CONFIG_IEEE80211R + os_memcpy(sm->PMK, psk, psk_len); + sm->pmk_len = psk_len; +#ifdef CONFIG_IEEE80211R_AP os_memcpy(sm->xxkey, psk, PMK_LEN); sm->xxkey_len = PMK_LEN; -#endif /* CONFIG_IEEE80211R */ +#endif /* CONFIG_IEEE80211R_AP */ } +#ifdef CONFIG_SAE + if (wpa_auth_uses_sae(sm) && sm->pmksa) { + wpa_printf(MSG_DEBUG, "SAE: PMK from PMKSA cache"); + os_memcpy(sm->PMK, sm->pmksa->pmk, sm->pmksa->pmk_len); + sm->pmk_len = sm->pmksa->pmk_len; +#ifdef CONFIG_IEEE80211R_AP + os_memcpy(sm->xxkey, sm->pmksa->pmk, sm->pmksa->pmk_len); + sm->xxkey_len = sm->pmksa->pmk_len; +#endif /* CONFIG_IEEE80211R_AP */ + } +#endif /* CONFIG_SAE */ sm->req_replay_counter_used = 0; } @@ -2005,7 +2105,7 @@ SM_STATE(WPA_PTK, PTKSTART) sm->alt_snonce_valid = FALSE; sm->TimeoutCtr++; - if (sm->TimeoutCtr > (int) dot11RSNAConfigPairwiseUpdateCount) { + if (sm->TimeoutCtr > sm->wpa_auth->conf.wpa_pairwise_update_count) { /* No point in sending the EAPOL-Key - we will disconnect * immediately following this. */ return; @@ -2014,11 +2114,23 @@ SM_STATE(WPA_PTK, PTKSTART) wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, "sending 1/4 msg of 4-Way Handshake"); /* - * TODO: Could add PMKID even with WPA2-PSK, but only if there is only - * one possible PSK for this STA. + * For infrastructure BSS cases, it is better for the AP not to include + * the PMKID KDE in EAPOL-Key msg 1/4 since it could be used to initiate + * offline search for the passphrase/PSK without having to be able to + * capture a 4-way handshake from a STA that has access to the network. + * + * For IBSS cases, addition of PMKID KDE could be considered even with + * WPA2-PSK cases that use multiple PSKs, but only if there is a single + * possible PSK for this STA. However, this should not be done unless + * there is support for using that information on the supplicant side. + * The concern about exposing PMKID unnecessarily in infrastructure BSS + * cases would also apply here, but at least in the IBSS case, this + * would cover a potential real use case. */ if (sm->wpa == WPA_VERSION_WPA2 && - wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt) && + (wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt) || + (sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE && sm->pmksa) || + wpa_key_mgmt_sae(sm->wpa_key_mgmt)) && sm->wpa_key_mgmt != WPA_KEY_MGMT_OSEN) { pmkid = buf; pmkid_len = 2 + RSN_SELECTOR_LEN + PMKID_LEN; @@ -2026,11 +2138,54 @@ SM_STATE(WPA_PTK, PTKSTART) pmkid[1] = RSN_SELECTOR_LEN + PMKID_LEN; RSN_SELECTOR_PUT(&pmkid[2], RSN_KEY_DATA_PMKID); if (sm->pmksa) { + wpa_hexdump(MSG_DEBUG, + "RSN: Message 1/4 PMKID from PMKSA entry", + sm->pmksa->pmkid, PMKID_LEN); os_memcpy(&pmkid[2 + RSN_SELECTOR_LEN], sm->pmksa->pmkid, PMKID_LEN); } else if (wpa_key_mgmt_suite_b(sm->wpa_key_mgmt)) { /* No KCK available to derive PMKID */ + wpa_printf(MSG_DEBUG, + "RSN: No KCK available to derive PMKID for message 1/4"); + pmkid = NULL; +#ifdef CONFIG_FILS + } else if (wpa_key_mgmt_fils(sm->wpa_key_mgmt)) { + if (sm->pmkid_set) { + wpa_hexdump(MSG_DEBUG, + "RSN: Message 1/4 PMKID from FILS/ERP", + sm->pmkid, PMKID_LEN); + os_memcpy(&pmkid[2 + RSN_SELECTOR_LEN], + sm->pmkid, PMKID_LEN); + } else { + /* No PMKID available */ + wpa_printf(MSG_DEBUG, + "RSN: No FILS/ERP PMKID available for message 1/4"); + pmkid = NULL; + } +#endif /* CONFIG_FILS */ +#ifdef CONFIG_IEEE80211R_AP + } else if (wpa_key_mgmt_ft(sm->wpa_key_mgmt) && + sm->ft_completed) { + wpa_printf(MSG_DEBUG, + "FT: No PMKID in message 1/4 when using FT protocol"); pmkid = NULL; + pmkid_len = 0; +#endif /* CONFIG_IEEE80211R_AP */ +#ifdef CONFIG_SAE + } else if (wpa_key_mgmt_sae(sm->wpa_key_mgmt)) { + if (sm->pmkid_set) { + wpa_hexdump(MSG_DEBUG, + "RSN: Message 1/4 PMKID from SAE", + sm->pmkid, PMKID_LEN); + os_memcpy(&pmkid[2 + RSN_SELECTOR_LEN], + sm->pmkid, PMKID_LEN); + } else { + /* No PMKID available */ + wpa_printf(MSG_DEBUG, + "RSN: No SAE PMKID available for message 1/4"); + pmkid = NULL; + } +#endif /* CONFIG_SAE */ } else { /* * Calculate PMKID since no PMKSA cache entry was @@ -2038,7 +2193,10 @@ SM_STATE(WPA_PTK, PTKSTART) */ rsn_pmkid(sm->PMK, sm->pmk_len, sm->wpa_auth->addr, sm->addr, &pmkid[2 + RSN_SELECTOR_LEN], - wpa_key_mgmt_sha256(sm->wpa_key_mgmt)); + sm->wpa_key_mgmt); + wpa_hexdump(MSG_DEBUG, + "RSN: Message 1/4 PMKID derived from PMK", + &pmkid[2 + RSN_SELECTOR_LEN], PMKID_LEN); } } wpa_send_eapol(sm->wpa_auth, sm, @@ -2051,54 +2209,678 @@ static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce, const u8 *pmk, unsigned int pmk_len, struct wpa_ptk *ptk) { -#ifdef CONFIG_IEEE80211R - if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) - return wpa_auth_derive_ptk_ft(sm, pmk, ptk); -#endif /* CONFIG_IEEE80211R */ + const u8 *z = NULL; + size_t z_len = 0; + +#ifdef CONFIG_IEEE80211R_AP + if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { + if (sm->ft_completed) { + u8 ptk_name[WPA_PMK_NAME_LEN]; + + return wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->pmk_r1_len, + sm->SNonce, sm->ANonce, + sm->addr, sm->wpa_auth->addr, + sm->pmk_r1_name, + ptk, ptk_name, + sm->wpa_key_mgmt, + sm->pairwise); + } + return wpa_auth_derive_ptk_ft(sm, ptk); + } +#endif /* CONFIG_IEEE80211R_AP */ + +#ifdef CONFIG_DPP2 + if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP && sm->dpp_z) { + z = wpabuf_head(sm->dpp_z); + z_len = wpabuf_len(sm->dpp_z); + } +#endif /* CONFIG_DPP2 */ return wpa_pmk_to_ptk(pmk, pmk_len, "Pairwise key expansion", sm->wpa_auth->addr, sm->addr, sm->ANonce, snonce, - ptk, sm->wpa_key_mgmt, sm->pairwise); + ptk, sm->wpa_key_mgmt, sm->pairwise, z, z_len); +} + + +#ifdef CONFIG_FILS + +int fils_auth_pmk_to_ptk(struct wpa_state_machine *sm, const u8 *pmk, + size_t pmk_len, const u8 *snonce, const u8 *anonce, + const u8 *dhss, size_t dhss_len, + struct wpabuf *g_sta, struct wpabuf *g_ap) +{ + u8 ick[FILS_ICK_MAX_LEN]; + size_t ick_len; + int res; + u8 fils_ft[FILS_FT_MAX_LEN]; + size_t fils_ft_len = 0; + + res = fils_pmk_to_ptk(pmk, pmk_len, sm->addr, sm->wpa_auth->addr, + snonce, anonce, dhss, dhss_len, + &sm->PTK, ick, &ick_len, + sm->wpa_key_mgmt, sm->pairwise, + fils_ft, &fils_ft_len); + if (res < 0) + return res; + sm->PTK_valid = TRUE; + sm->tk_already_set = FALSE; + +#ifdef CONFIG_IEEE80211R_AP + if (fils_ft_len) { + struct wpa_authenticator *wpa_auth = sm->wpa_auth; + struct wpa_auth_config *conf = &wpa_auth->conf; + u8 pmk_r0[PMK_LEN_MAX], pmk_r0_name[WPA_PMK_NAME_LEN]; + int use_sha384 = wpa_key_mgmt_sha384(sm->wpa_key_mgmt); + size_t pmk_r0_len = use_sha384 ? SHA384_MAC_LEN : PMK_LEN; + + if (wpa_derive_pmk_r0(fils_ft, fils_ft_len, + conf->ssid, conf->ssid_len, + conf->mobility_domain, + conf->r0_key_holder, + conf->r0_key_holder_len, + sm->addr, pmk_r0, pmk_r0_name, + use_sha384) < 0) + return -1; + + wpa_hexdump_key(MSG_DEBUG, "FILS+FT: PMK-R0", + pmk_r0, pmk_r0_len); + wpa_hexdump(MSG_DEBUG, "FILS+FT: PMKR0Name", + pmk_r0_name, WPA_PMK_NAME_LEN); + wpa_ft_store_pmk_fils(sm, pmk_r0, pmk_r0_name); + os_memset(fils_ft, 0, sizeof(fils_ft)); + + res = wpa_derive_pmk_r1_name(pmk_r0_name, conf->r1_key_holder, + sm->addr, sm->pmk_r1_name, + use_sha384); + os_memset(pmk_r0, 0, PMK_LEN_MAX); + if (res < 0) + return -1; + wpa_hexdump(MSG_DEBUG, "FILS+FT: PMKR1Name", sm->pmk_r1_name, + WPA_PMK_NAME_LEN); + sm->pmk_r1_name_valid = 1; + } +#endif /* CONFIG_IEEE80211R_AP */ + + res = fils_key_auth_sk(ick, ick_len, snonce, anonce, + sm->addr, sm->wpa_auth->addr, + g_sta ? wpabuf_head(g_sta) : NULL, + g_sta ? wpabuf_len(g_sta) : 0, + g_ap ? wpabuf_head(g_ap) : NULL, + g_ap ? wpabuf_len(g_ap) : 0, + sm->wpa_key_mgmt, sm->fils_key_auth_sta, + sm->fils_key_auth_ap, + &sm->fils_key_auth_len); + os_memset(ick, 0, sizeof(ick)); + + /* Store nonces for (Re)Association Request/Response frame processing */ + os_memcpy(sm->SNonce, snonce, FILS_NONCE_LEN); + os_memcpy(sm->ANonce, anonce, FILS_NONCE_LEN); + + return res; +} + + +static int wpa_aead_decrypt(struct wpa_state_machine *sm, struct wpa_ptk *ptk, + u8 *buf, size_t buf_len, u16 *_key_data_len) +{ + struct ieee802_1x_hdr *hdr; + struct wpa_eapol_key *key; + u8 *pos; + u16 key_data_len; + u8 *tmp; + const u8 *aad[1]; + size_t aad_len[1]; + + hdr = (struct ieee802_1x_hdr *) buf; + key = (struct wpa_eapol_key *) (hdr + 1); + pos = (u8 *) (key + 1); + key_data_len = WPA_GET_BE16(pos); + if (key_data_len < AES_BLOCK_SIZE || + key_data_len > buf_len - sizeof(*hdr) - sizeof(*key) - 2) { + wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_INFO, + "No room for AES-SIV data in the frame"); + return -1; + } + pos += 2; /* Pointing at the Encrypted Key Data field */ + + tmp = os_malloc(key_data_len); + if (!tmp) + return -1; + + /* AES-SIV AAD from EAPOL protocol version field (inclusive) to + * to Key Data (exclusive). */ + aad[0] = buf; + aad_len[0] = pos - buf; + if (aes_siv_decrypt(ptk->kek, ptk->kek_len, pos, key_data_len, + 1, aad, aad_len, tmp) < 0) { + wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_INFO, + "Invalid AES-SIV data in the frame"); + bin_clear_free(tmp, key_data_len); + return -1; + } + + /* AEAD decryption and validation completed successfully */ + key_data_len -= AES_BLOCK_SIZE; + wpa_hexdump_key(MSG_DEBUG, "WPA: Decrypted Key Data", + tmp, key_data_len); + + /* Replace Key Data field with the decrypted version */ + os_memcpy(pos, tmp, key_data_len); + pos -= 2; /* Key Data Length field */ + WPA_PUT_BE16(pos, key_data_len); + bin_clear_free(tmp, key_data_len); + if (_key_data_len) + *_key_data_len = key_data_len; + return 0; +} + + +const u8 * wpa_fils_validate_fils_session(struct wpa_state_machine *sm, + const u8 *ies, size_t ies_len, + const u8 *fils_session) +{ + const u8 *ie, *end; + const u8 *session = NULL; + + if (!wpa_key_mgmt_fils(sm->wpa_key_mgmt)) { + wpa_printf(MSG_DEBUG, + "FILS: Not a FILS AKM - reject association"); + return NULL; + } + + /* Verify Session element */ + ie = ies; + end = ((const u8 *) ie) + ies_len; + while (ie + 1 < end) { + if (ie + 2 + ie[1] > end) + break; + if (ie[0] == WLAN_EID_EXTENSION && + ie[1] >= 1 + FILS_SESSION_LEN && + ie[2] == WLAN_EID_EXT_FILS_SESSION) { + session = ie; + break; + } + ie += 2 + ie[1]; + } + + if (!session) { + wpa_printf(MSG_DEBUG, + "FILS: %s: Could not find FILS Session element in Assoc Req - reject", + __func__); + return NULL; + } + + if (!fils_session) { + wpa_printf(MSG_DEBUG, + "FILS: %s: Could not find FILS Session element in STA entry - reject", + __func__); + return NULL; + } + + if (os_memcmp(fils_session, session + 3, FILS_SESSION_LEN) != 0) { + wpa_printf(MSG_DEBUG, "FILS: Session mismatch"); + wpa_hexdump(MSG_DEBUG, "FILS: Expected FILS Session", + fils_session, FILS_SESSION_LEN); + wpa_hexdump(MSG_DEBUG, "FILS: Received FILS Session", + session + 3, FILS_SESSION_LEN); + return NULL; + } + return session; +} + + +int wpa_fils_validate_key_confirm(struct wpa_state_machine *sm, const u8 *ies, + size_t ies_len) +{ + struct ieee802_11_elems elems; + + if (ieee802_11_parse_elems(ies, ies_len, &elems, 1) == ParseFailed) { + wpa_printf(MSG_DEBUG, + "FILS: Failed to parse decrypted elements"); + return -1; + } + + if (!elems.fils_session) { + wpa_printf(MSG_DEBUG, "FILS: No FILS Session element"); + return -1; + } + + if (!elems.fils_key_confirm) { + wpa_printf(MSG_DEBUG, "FILS: No FILS Key Confirm element"); + return -1; + } + + if (elems.fils_key_confirm_len != sm->fils_key_auth_len) { + wpa_printf(MSG_DEBUG, + "FILS: Unexpected Key-Auth length %d (expected %d)", + elems.fils_key_confirm_len, + (int) sm->fils_key_auth_len); + return -1; + } + + if (os_memcmp(elems.fils_key_confirm, sm->fils_key_auth_sta, + sm->fils_key_auth_len) != 0) { + wpa_printf(MSG_DEBUG, "FILS: Key-Auth mismatch"); + wpa_hexdump(MSG_DEBUG, "FILS: Received Key-Auth", + elems.fils_key_confirm, elems.fils_key_confirm_len); + wpa_hexdump(MSG_DEBUG, "FILS: Expected Key-Auth", + sm->fils_key_auth_sta, sm->fils_key_auth_len); + return -1; + } + + return 0; +} + + +int fils_decrypt_assoc(struct wpa_state_machine *sm, const u8 *fils_session, + const struct ieee80211_mgmt *mgmt, size_t frame_len, + u8 *pos, size_t left) +{ + u16 fc, stype; + const u8 *end, *ie_start, *ie, *session, *crypt; + const u8 *aad[5]; + size_t aad_len[5]; + + if (!sm || !sm->PTK_valid) { + wpa_printf(MSG_DEBUG, + "FILS: No KEK to decrypt Assocication Request frame"); + return -1; + } + + if (!wpa_key_mgmt_fils(sm->wpa_key_mgmt)) { + wpa_printf(MSG_DEBUG, + "FILS: Not a FILS AKM - reject association"); + return -1; + } + + end = ((const u8 *) mgmt) + frame_len; + fc = le_to_host16(mgmt->frame_control); + stype = WLAN_FC_GET_STYPE(fc); + if (stype == WLAN_FC_STYPE_REASSOC_REQ) + ie_start = mgmt->u.reassoc_req.variable; + else + ie_start = mgmt->u.assoc_req.variable; + ie = ie_start; + + /* + * Find FILS Session element which is the last unencrypted element in + * the frame. + */ + session = wpa_fils_validate_fils_session(sm, ie, end - ie, + fils_session); + if (!session) { + wpa_printf(MSG_DEBUG, "FILS: Session validation failed"); + return -1; + } + + crypt = session + 2 + session[1]; + + if (end - crypt < AES_BLOCK_SIZE) { + wpa_printf(MSG_DEBUG, + "FILS: Too short frame to include AES-SIV data"); + return -1; + } + + /* AES-SIV AAD vectors */ + + /* The STA's MAC address */ + aad[0] = mgmt->sa; + aad_len[0] = ETH_ALEN; + /* The AP's BSSID */ + aad[1] = mgmt->da; + aad_len[1] = ETH_ALEN; + /* The STA's nonce */ + aad[2] = sm->SNonce; + aad_len[2] = FILS_NONCE_LEN; + /* The AP's nonce */ + aad[3] = sm->ANonce; + aad_len[3] = FILS_NONCE_LEN; + /* + * The (Re)Association Request frame from the Capability Information + * field to the FILS Session element (both inclusive). + */ + aad[4] = (const u8 *) &mgmt->u.assoc_req.capab_info; + aad_len[4] = crypt - aad[4]; + + if (aes_siv_decrypt(sm->PTK.kek, sm->PTK.kek_len, crypt, end - crypt, + 5, aad, aad_len, pos + (crypt - ie_start)) < 0) { + wpa_printf(MSG_DEBUG, + "FILS: Invalid AES-SIV data in the frame"); + return -1; + } + wpa_hexdump(MSG_DEBUG, "FILS: Decrypted Association Request elements", + pos, left - AES_BLOCK_SIZE); + + if (wpa_fils_validate_key_confirm(sm, pos, left - AES_BLOCK_SIZE) < 0) { + wpa_printf(MSG_DEBUG, "FILS: Key Confirm validation failed"); + return -1; + } + + return left - AES_BLOCK_SIZE; +} + + +int fils_encrypt_assoc(struct wpa_state_machine *sm, u8 *buf, + size_t current_len, size_t max_len, + const struct wpabuf *hlp) +{ + u8 *end = buf + max_len; + u8 *pos = buf + current_len; + struct ieee80211_mgmt *mgmt; + struct wpabuf *plain; + const u8 *aad[5]; + size_t aad_len[5]; + + if (!sm || !sm->PTK_valid) + return -1; + + wpa_hexdump(MSG_DEBUG, + "FILS: Association Response frame before FILS processing", + buf, current_len); + + mgmt = (struct ieee80211_mgmt *) buf; + + /* AES-SIV AAD vectors */ + + /* The AP's BSSID */ + aad[0] = mgmt->sa; + aad_len[0] = ETH_ALEN; + /* The STA's MAC address */ + aad[1] = mgmt->da; + aad_len[1] = ETH_ALEN; + /* The AP's nonce */ + aad[2] = sm->ANonce; + aad_len[2] = FILS_NONCE_LEN; + /* The STA's nonce */ + aad[3] = sm->SNonce; + aad_len[3] = FILS_NONCE_LEN; + /* + * The (Re)Association Response frame from the Capability Information + * field (the same offset in both Association and Reassociation + * Response frames) to the FILS Session element (both inclusive). + */ + aad[4] = (const u8 *) &mgmt->u.assoc_resp.capab_info; + aad_len[4] = pos - aad[4]; + + /* The following elements will be encrypted with AES-SIV */ + plain = fils_prepare_plainbuf(sm, hlp); + if (!plain) { + wpa_printf(MSG_DEBUG, "FILS: Plain buffer prep failed"); + return -1; + } + + if (pos + wpabuf_len(plain) + AES_BLOCK_SIZE > end) { + wpa_printf(MSG_DEBUG, + "FILS: Not enough room for FILS elements"); + wpabuf_free(plain); + return -1; + } + + wpa_hexdump_buf_key(MSG_DEBUG, "FILS: Association Response plaintext", + plain); + + if (aes_siv_encrypt(sm->PTK.kek, sm->PTK.kek_len, + wpabuf_head(plain), wpabuf_len(plain), + 5, aad, aad_len, pos) < 0) { + wpabuf_free(plain); + return -1; + } + + wpa_hexdump(MSG_DEBUG, + "FILS: Encrypted Association Response elements", + pos, AES_BLOCK_SIZE + wpabuf_len(plain)); + current_len += wpabuf_len(plain) + AES_BLOCK_SIZE; + wpabuf_free(plain); + + sm->fils_completed = 1; + + return current_len; +} + + +static struct wpabuf * fils_prepare_plainbuf(struct wpa_state_machine *sm, + const struct wpabuf *hlp) +{ + struct wpabuf *plain; + u8 *len, *tmp, *tmp2; + u8 hdr[2]; + u8 *gtk, dummy_gtk[32]; + size_t gtk_len; + struct wpa_group *gsm; + + plain = wpabuf_alloc(1000); + if (!plain) + return NULL; + + /* TODO: FILS Public Key */ + + /* FILS Key Confirmation */ + wpabuf_put_u8(plain, WLAN_EID_EXTENSION); /* Element ID */ + wpabuf_put_u8(plain, 1 + sm->fils_key_auth_len); /* Length */ + /* Element ID Extension */ + wpabuf_put_u8(plain, WLAN_EID_EXT_FILS_KEY_CONFIRM); + wpabuf_put_data(plain, sm->fils_key_auth_ap, sm->fils_key_auth_len); + + /* FILS HLP Container */ + if (hlp) + wpabuf_put_buf(plain, hlp); + + /* TODO: FILS IP Address Assignment */ + + /* Key Delivery */ + gsm = sm->group; + wpabuf_put_u8(plain, WLAN_EID_EXTENSION); /* Element ID */ + len = wpabuf_put(plain, 1); + wpabuf_put_u8(plain, WLAN_EID_EXT_KEY_DELIVERY); + wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, + wpabuf_put(plain, WPA_KEY_RSC_LEN)); + /* GTK KDE */ + gtk = gsm->GTK[gsm->GN - 1]; + gtk_len = gsm->GTK_len; + if (sm->wpa_auth->conf.disable_gtk || + sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) { + /* + * Provide unique random GTK to each STA to prevent use + * of GTK in the BSS. + */ + if (random_get_bytes(dummy_gtk, gtk_len) < 0) { + wpabuf_free(plain); + return NULL; + } + gtk = dummy_gtk; + } + hdr[0] = gsm->GN & 0x03; + hdr[1] = 0; + tmp = wpabuf_put(plain, 0); + tmp2 = wpa_add_kde(tmp, RSN_KEY_DATA_GROUPKEY, hdr, 2, + gtk, gtk_len); + wpabuf_put(plain, tmp2 - tmp); + + /* IGTK KDE */ + tmp = wpabuf_put(plain, 0); + tmp2 = ieee80211w_kde_add(sm, tmp); + wpabuf_put(plain, tmp2 - tmp); + + *len = (u8 *) wpabuf_put(plain, 0) - len - 1; + +#ifdef CONFIG_OCV + if (wpa_auth_uses_ocv(sm)) { + struct wpa_channel_info ci; + u8 *pos; + + if (wpa_channel_info(sm->wpa_auth, &ci) != 0) { + wpa_printf(MSG_WARNING, + "FILS: Failed to get channel info for OCI element"); + wpabuf_free(plain); + return NULL; + } + + pos = wpabuf_put(plain, OCV_OCI_EXTENDED_LEN); + if (ocv_insert_extended_oci(&ci, pos) < 0) { + wpabuf_free(plain); + return NULL; + } + } +#endif /* CONFIG_OCV */ + + return plain; } +int fils_set_tk(struct wpa_state_machine *sm) +{ + enum wpa_alg alg; + int klen; + + if (!sm || !sm->PTK_valid) { + wpa_printf(MSG_DEBUG, "FILS: No valid PTK available to set TK"); + return -1; + } + if (sm->tk_already_set) { + wpa_printf(MSG_DEBUG, "FILS: TK already set to the driver"); + return -1; + } + + alg = wpa_cipher_to_alg(sm->pairwise); + klen = wpa_cipher_key_len(sm->pairwise); + + 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)) { + wpa_printf(MSG_DEBUG, "FILS: Failed to set TK to the driver"); + return -1; + } + sm->tk_already_set = TRUE; + + return 0; +} + + +u8 * hostapd_eid_assoc_fils_session(struct wpa_state_machine *sm, u8 *buf, + const u8 *fils_session, struct wpabuf *hlp) +{ + struct wpabuf *plain; + u8 *pos = buf; + + /* FILS Session */ + *pos++ = WLAN_EID_EXTENSION; /* Element ID */ + *pos++ = 1 + FILS_SESSION_LEN; /* Length */ + *pos++ = WLAN_EID_EXT_FILS_SESSION; /* Element ID Extension */ + os_memcpy(pos, fils_session, FILS_SESSION_LEN); + pos += FILS_SESSION_LEN; + + plain = fils_prepare_plainbuf(sm, hlp); + if (!plain) { + wpa_printf(MSG_DEBUG, "FILS: Plain buffer prep failed"); + return NULL; + } + + os_memcpy(pos, wpabuf_head(plain), wpabuf_len(plain)); + pos += wpabuf_len(plain); + + wpa_printf(MSG_DEBUG, "%s: plain buf_len: %u", __func__, + (unsigned int) wpabuf_len(plain)); + wpabuf_free(plain); + sm->fils_completed = 1; + return pos; +} + +#endif /* CONFIG_FILS */ + + +#ifdef CONFIG_OCV +int get_sta_tx_parameters(struct wpa_state_machine *sm, int ap_max_chanwidth, + int ap_seg1_idx, int *bandwidth, int *seg1_idx) +{ + struct wpa_authenticator *wpa_auth = sm->wpa_auth; + + if (!wpa_auth->cb->get_sta_tx_params) + return -1; + return wpa_auth->cb->get_sta_tx_params(wpa_auth->cb_ctx, sm->addr, + ap_max_chanwidth, ap_seg1_idx, + bandwidth, seg1_idx); +} +#endif /* CONFIG_OCV */ + + SM_STATE(WPA_PTK, PTKCALCNEGOTIATING) { + struct wpa_authenticator *wpa_auth = sm->wpa_auth; struct wpa_ptk PTK; int ok = 0, psk_found = 0; const u8 *pmk = NULL; - unsigned int pmk_len; + size_t pmk_len; + int ft; + const u8 *eapol_key_ie, *key_data, *mic; + u16 key_data_length; + size_t mic_len, eapol_key_ie_len; + struct ieee802_1x_hdr *hdr; + struct wpa_eapol_key *key; + struct wpa_eapol_ie_parse kde; + int vlan_id = 0; SM_ENTRY_MA(WPA_PTK, PTKCALCNEGOTIATING, wpa_ptk); sm->EAPOLKeyReceived = FALSE; sm->update_snonce = FALSE; + os_memset(&PTK, 0, sizeof(PTK)); + + mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len); /* WPA with IEEE 802.1X: use the derived PMK from EAP * WPA-PSK: iterate through possible PSKs and select the one matching * the packet */ for (;;) { - if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) { + if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) && + !wpa_key_mgmt_sae(sm->wpa_key_mgmt)) { pmk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, - sm->p2p_dev_addr, pmk); + sm->p2p_dev_addr, pmk, &pmk_len, + &vlan_id); if (pmk == NULL) break; psk_found = 1; - pmk_len = PMK_LEN; +#ifdef CONFIG_IEEE80211R_AP + if (wpa_key_mgmt_ft_psk(sm->wpa_key_mgmt)) { + os_memcpy(sm->xxkey, pmk, pmk_len); + sm->xxkey_len = pmk_len; + } +#endif /* CONFIG_IEEE80211R_AP */ } else { pmk = sm->PMK; pmk_len = sm->pmk_len; } - wpa_derive_ptk(sm, sm->SNonce, pmk, pmk_len, &PTK); + if ((!pmk || !pmk_len) && sm->pmksa) { + wpa_printf(MSG_DEBUG, "WPA: Use PMK from PMKSA cache"); + pmk = sm->pmksa->pmk; + pmk_len = sm->pmksa->pmk_len; + } - if (wpa_verify_key_mic(sm->wpa_key_mgmt, &PTK, + if (wpa_derive_ptk(sm, sm->SNonce, pmk, pmk_len, &PTK) < 0) + break; + + if (mic_len && + wpa_verify_key_mic(sm->wpa_key_mgmt, pmk_len, &PTK, sm->last_rx_eapol_key, sm->last_rx_eapol_key_len) == 0) { + if (sm->PMK != pmk) { + os_memcpy(sm->PMK, pmk, pmk_len); + sm->pmk_len = pmk_len; + } + ok = 1; + break; + } + +#ifdef CONFIG_FILS + if (!mic_len && + wpa_aead_decrypt(sm, &PTK, sm->last_rx_eapol_key, + sm->last_rx_eapol_key_len, NULL) == 0) { ok = 1; break; } +#endif /* CONFIG_FILS */ - if (!wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) + if (!wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) || + wpa_key_mgmt_sae(sm->wpa_key_mgmt)) break; } @@ -2110,7 +2892,105 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING) return; } -#ifdef CONFIG_IEEE80211R + /* + * Note: last_rx_eapol_key length fields have already been validated in + * wpa_receive(). + */ + hdr = (struct ieee802_1x_hdr *) sm->last_rx_eapol_key; + key = (struct wpa_eapol_key *) (hdr + 1); + mic = (u8 *) (key + 1); + key_data = mic + mic_len + 2; + key_data_length = WPA_GET_BE16(mic + mic_len); + if (key_data_length > sm->last_rx_eapol_key_len - sizeof(*hdr) - + sizeof(*key) - mic_len - 2) + return; + + if (wpa_parse_kde_ies(key_data, key_data_length, &kde) < 0) { + wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, + "received EAPOL-Key msg 2/4 with invalid Key Data contents"); + return; + } + if (kde.rsn_ie) { + eapol_key_ie = kde.rsn_ie; + eapol_key_ie_len = kde.rsn_ie_len; + } else if (kde.osen) { + eapol_key_ie = kde.osen; + eapol_key_ie_len = kde.osen_len; + } else { + eapol_key_ie = kde.wpa_ie; + eapol_key_ie_len = kde.wpa_ie_len; + } + ft = sm->wpa == WPA_VERSION_WPA2 && wpa_key_mgmt_ft(sm->wpa_key_mgmt); + if (sm->wpa_ie == NULL || + wpa_compare_rsn_ie(ft, sm->wpa_ie, sm->wpa_ie_len, + eapol_key_ie, eapol_key_ie_len)) { + wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, + "WPA IE from (Re)AssocReq did not match with msg 2/4"); + if (sm->wpa_ie) { + wpa_hexdump(MSG_DEBUG, "WPA IE in AssocReq", + sm->wpa_ie, sm->wpa_ie_len); + } + wpa_hexdump(MSG_DEBUG, "WPA IE in msg 2/4", + eapol_key_ie, eapol_key_ie_len); + /* MLME-DEAUTHENTICATE.request */ + wpa_sta_disconnect(wpa_auth, sm->addr, + WLAN_REASON_PREV_AUTH_NOT_VALID); + return; + } +#ifdef CONFIG_OCV + if (wpa_auth_uses_ocv(sm)) { + struct wpa_channel_info ci; + int tx_chanwidth; + int tx_seg1_idx; + + if (wpa_channel_info(wpa_auth, &ci) != 0) { + wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, + "Failed to get channel info to validate received OCI in EAPOL-Key 2/4"); + return; + } + + if (get_sta_tx_parameters(sm, + channel_width_to_int(ci.chanwidth), + ci.seg1_idx, &tx_chanwidth, + &tx_seg1_idx) < 0) + return; + + if (ocv_verify_tx_params(kde.oci, kde.oci_len, &ci, + tx_chanwidth, tx_seg1_idx) != 0) { + wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, + ocv_errorstr); + return; + } + } +#endif /* CONFIG_OCV */ +#ifdef CONFIG_IEEE80211R_AP + if (ft && ft_check_msg_2_of_4(wpa_auth, sm, &kde) < 0) { + wpa_sta_disconnect(wpa_auth, sm->addr, + WLAN_REASON_PREV_AUTH_NOT_VALID); + return; + } +#endif /* CONFIG_IEEE80211R_AP */ +#ifdef CONFIG_P2P + if (kde.ip_addr_req && kde.ip_addr_req[0] && + wpa_auth->ip_pool && WPA_GET_BE32(sm->ip_addr) == 0) { + int idx; + wpa_printf(MSG_DEBUG, + "P2P: IP address requested in EAPOL-Key exchange"); + idx = bitfield_get_first_zero(wpa_auth->ip_pool); + if (idx >= 0) { + u32 start = WPA_GET_BE32(wpa_auth->conf.ip_addr_start); + bitfield_set(wpa_auth->ip_pool, idx); + WPA_PUT_BE32(sm->ip_addr, start + idx); + wpa_printf(MSG_DEBUG, + "P2P: Assigned IP address %u.%u.%u.%u to " + MACSTR, sm->ip_addr[0], sm->ip_addr[1], + sm->ip_addr[2], sm->ip_addr[3], + MAC2STR(sm->addr)); + } + } +#endif /* CONFIG_P2P */ + +#ifdef CONFIG_IEEE80211R_AP if (sm->wpa == WPA_VERSION_WPA2 && wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { /* * Verify that PMKR1Name from EAPOL-Key message 2/4 matches @@ -2129,7 +3009,14 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING) return; } } -#endif /* CONFIG_IEEE80211R */ +#endif /* CONFIG_IEEE80211R_AP */ + + if (vlan_id && wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) && + wpa_auth_update_vlan(wpa_auth, sm->addr, vlan_id) < 0) { + wpa_sta_disconnect(wpa_auth, sm->addr, + WLAN_REASON_PREV_AUTH_NOT_VALID); + return; + } sm->pending_1_of_4_timeout = 0; eloop_cancel_timeout(wpa_send_eapol_timeout, sm->wpa_auth, sm); @@ -2188,7 +3075,8 @@ static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos) else os_memcpy(igtk.pn, rsc, sizeof(igtk.pn)); os_memcpy(igtk.igtk, gsm->IGTK[gsm->GN_igtk - 4], len); - if (sm->wpa_auth->conf.disable_gtk) { + if (sm->wpa_auth->conf.disable_gtk || + sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) { /* * Provide unique random IGTK to each STA to prevent use of * IGTK in the BSS. @@ -2219,6 +3107,36 @@ static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos) #endif /* CONFIG_IEEE80211W */ +static int ocv_oci_len(struct wpa_state_machine *sm) +{ +#ifdef CONFIG_OCV + if (wpa_auth_uses_ocv(sm)) + return OCV_OCI_KDE_LEN; +#endif /* CONFIG_OCV */ + return 0; +} + +static int ocv_oci_add(struct wpa_state_machine *sm, u8 **argpos) +{ +#ifdef CONFIG_OCV + struct wpa_channel_info ci; + + if (!wpa_auth_uses_ocv(sm)) + return 0; + + if (wpa_channel_info(sm->wpa_auth, &ci) != 0) { + wpa_printf(MSG_WARNING, + "Failed to get channel info for OCI element"); + return -1; + } + + return ocv_insert_oci_kde(&ci, argpos); +#else /* CONFIG_OCV */ + return 0; +#endif /* CONFIG_OCV */ +} + + SM_STATE(WPA_PTK, PTKINITNEGOTIATING) { u8 rsc[WPA_KEY_RSC_LEN], *_rsc, *gtk, *kde, *pos, dummy_gtk[32]; @@ -2231,7 +3149,12 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) sm->TimeoutEvt = FALSE; sm->TimeoutCtr++; - if (sm->TimeoutCtr > (int) dot11RSNAConfigPairwiseUpdateCount) { + if (sm->wpa_auth->conf.wpa_disable_eapol_key_retries && + sm->TimeoutCtr > 1) { + /* Do not allow retransmission of EAPOL-Key msg 3/4 */ + return; + } + if (sm->TimeoutCtr > sm->wpa_auth->conf.wpa_pairwise_update_count) { /* No point in sending the EAPOL-Key - we will disconnect * immediately following this. */ return; @@ -2261,7 +3184,8 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) secure = 1; gtk = gsm->GTK[gsm->GN - 1]; gtk_len = gsm->GTK_len; - if (sm->wpa_auth->conf.disable_gtk) { + if (sm->wpa_auth->conf.disable_gtk || + sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) { /* * Provide unique random GTK to each STA to prevent use * of GTK in the BSS. @@ -2296,15 +3220,15 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) } } - kde_len = wpa_ie_len + ieee80211w_kde_len(sm); + kde_len = wpa_ie_len + ieee80211w_kde_len(sm) + ocv_oci_len(sm); if (gtk) kde_len += 2 + RSN_SELECTOR_LEN + 2 + gtk_len; -#ifdef CONFIG_IEEE80211R +#ifdef CONFIG_IEEE80211R_AP if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { kde_len += 2 + PMKID_LEN; /* PMKR1Name into RSN IE */ kde_len += 300; /* FTIE + 2 * TIE */ } -#endif /* CONFIG_IEEE80211R */ +#endif /* CONFIG_IEEE80211R_AP */ #ifdef CONFIG_P2P if (WPA_GET_BE32(sm->ip_addr) > 0) kde_len += 2 + RSN_SELECTOR_LEN + 3 * 4; @@ -2316,7 +3240,7 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) pos = kde; os_memcpy(pos, wpa_ie, wpa_ie_len); pos += wpa_ie_len; -#ifdef CONFIG_IEEE80211R +#ifdef CONFIG_IEEE80211R_AP if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { int res; size_t elen; @@ -2332,7 +3256,7 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) pos -= wpa_ie_len; pos += elen; } -#endif /* CONFIG_IEEE80211R */ +#endif /* CONFIG_IEEE80211R_AP */ if (gtk) { u8 hdr[2]; hdr[0] = keyidx & 0x03; @@ -2341,8 +3265,12 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) gtk, gtk_len); } pos = ieee80211w_kde_add(sm, pos); + if (ocv_oci_add(sm, &pos) < 0) { + os_free(kde); + return; + } -#ifdef CONFIG_IEEE80211R +#ifdef CONFIG_IEEE80211R_AP if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { int res; struct wpa_auth_config *conf; @@ -2354,7 +3282,10 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) 2 + sm->assoc_resp_ftie[1]); res = 2 + sm->assoc_resp_ftie[1]; } else { - res = wpa_write_ftie(conf, conf->r0_key_holder, + int use_sha384 = wpa_key_mgmt_sha384(sm->wpa_key_mgmt); + + res = wpa_write_ftie(conf, use_sha384, + conf->r0_key_holder, conf->r0_key_holder_len, NULL, NULL, pos, kde + kde_len - pos, @@ -2379,10 +3310,10 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) *pos++ = WLAN_EID_TIMEOUT_INTERVAL; *pos++ = 5; *pos++ = WLAN_TIMEOUT_KEY_LIFETIME; - WPA_PUT_LE32(pos, conf->r0_key_lifetime * 60); + WPA_PUT_LE32(pos, conf->r0_key_lifetime); pos += 4; } -#endif /* CONFIG_IEEE80211R */ +#endif /* CONFIG_IEEE80211R_AP */ #ifdef CONFIG_P2P if (WPA_GET_BE32(sm->ip_addr) > 0) { u8 addr[3 * 4]; @@ -2395,7 +3326,9 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) #endif /* CONFIG_P2P */ wpa_send_eapol(sm->wpa_auth, sm, - (secure ? WPA_KEY_INFO_SECURE : 0) | WPA_KEY_INFO_MIC | + (secure ? WPA_KEY_INFO_SECURE : 0) | + (wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len) ? + WPA_KEY_INFO_MIC : 0) | WPA_KEY_INFO_ACK | WPA_KEY_INFO_INSTALL | WPA_KEY_INFO_KEY_TYPE, _rsc, sm->ANonce, kde, pos - kde, keyidx, encr); @@ -2412,20 +3345,18 @@ SM_STATE(WPA_PTK, PTKINITDONE) 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)) { - wpa_sta_disconnect(sm->wpa_auth, sm->addr); + wpa_sta_disconnect(sm->wpa_auth, sm->addr, + WLAN_REASON_PREV_AUTH_NOT_VALID); return; } /* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */ sm->pairwise_set = TRUE; - if (sm->wpa_auth->conf.wpa_ptk_rekey) { - eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm); - eloop_register_timeout(sm->wpa_auth->conf. - wpa_ptk_rekey, 0, wpa_rekey_ptk, - sm->wpa_auth, sm); - } + wpa_auth_set_ptk_rekey_timer(sm); - if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) { + if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) || + sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP || + sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE) { wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_authorized, 1); } @@ -2451,9 +3382,9 @@ SM_STATE(WPA_PTK, PTKINITDONE) "pairwise key handshake completed (%s)", sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN"); -#ifdef CONFIG_IEEE80211R +#ifdef CONFIG_IEEE80211R_AP wpa_ft_push_pmk_r1(sm->wpa_auth, sm->addr); -#endif /* CONFIG_IEEE80211R */ +#endif /* CONFIG_IEEE80211R_AP */ } @@ -2497,15 +3428,22 @@ SM_STEP(WPA_PTK) wpa_auth_get_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyRun) > 0) SM_ENTER(WPA_PTK, INITPMK); - else if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) + else if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) || + sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE /* FIX: && 802.1X::keyRun */) SM_ENTER(WPA_PTK, INITPSK); + else if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP) + SM_ENTER(WPA_PTK, INITPMK); break; case WPA_PTK_INITPMK: if (wpa_auth_get_eapol(sm->wpa_auth, sm->addr, - WPA_EAPOL_keyAvailable) > 0) + WPA_EAPOL_keyAvailable) > 0) { + SM_ENTER(WPA_PTK, PTKSTART); +#ifdef CONFIG_DPP + } else if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP && sm->pmksa) { SM_ENTER(WPA_PTK, PTKSTART); - else { +#endif /* CONFIG_DPP */ + } else { wpa_auth->dot11RSNA4WayHandshakeFailures++; wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_INFO, "INITPMK - keyAvailable = false"); @@ -2514,9 +3452,13 @@ SM_STEP(WPA_PTK) break; case WPA_PTK_INITPSK: if (wpa_auth_get_psk(sm->wpa_auth, sm->addr, sm->p2p_dev_addr, - NULL)) + NULL, NULL, NULL)) { + SM_ENTER(WPA_PTK, PTKSTART); +#ifdef CONFIG_SAE + } else if (wpa_auth_uses_sae(sm) && sm->pmksa) { SM_ENTER(WPA_PTK, PTKSTART); - else { +#endif /* CONFIG_SAE */ + } else { wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_INFO, "no PSK configured for the STA"); wpa_auth->dot11RSNA4WayHandshakeFailures++; @@ -2528,11 +3470,12 @@ SM_STEP(WPA_PTK) sm->EAPOLKeyPairwise) SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING); else if (sm->TimeoutCtr > - (int) dot11RSNAConfigPairwiseUpdateCount) { + sm->wpa_auth->conf.wpa_pairwise_update_count) { wpa_auth->dot11RSNA4WayHandshakeFailures++; - wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, - "PTKSTART: Retry limit %d reached", - dot11RSNAConfigPairwiseUpdateCount); + wpa_auth_vlogger( + sm->wpa_auth, sm->addr, LOGGER_DEBUG, + "PTKSTART: Retry limit %u reached", + sm->wpa_auth->conf.wpa_pairwise_update_count); SM_ENTER(WPA_PTK, DISCONNECT); } else if (sm->TimeoutEvt) SM_ENTER(WPA_PTK, PTKSTART); @@ -2556,12 +3499,14 @@ SM_STEP(WPA_PTK) sm->EAPOLKeyPairwise && sm->MICVerified) SM_ENTER(WPA_PTK, PTKINITDONE); else if (sm->TimeoutCtr > - (int) dot11RSNAConfigPairwiseUpdateCount) { + sm->wpa_auth->conf.wpa_pairwise_update_count || + (sm->wpa_auth->conf.wpa_disable_eapol_key_retries && + sm->TimeoutCtr > 1)) { wpa_auth->dot11RSNA4WayHandshakeFailures++; - wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, - "PTKINITNEGOTIATING: Retry limit %d " - "reached", - dot11RSNAConfigPairwiseUpdateCount); + wpa_auth_vlogger( + sm->wpa_auth, sm->addr, LOGGER_DEBUG, + "PTKINITNEGOTIATING: Retry limit %u reached", + sm->wpa_auth->conf.wpa_pairwise_update_count); SM_ENTER(WPA_PTK, DISCONNECT); } else if (sm->TimeoutEvt) SM_ENTER(WPA_PTK, PTKINITNEGOTIATING); @@ -2596,7 +3541,12 @@ SM_STATE(WPA_PTK_GROUP, REKEYNEGOTIATING) SM_ENTRY_MA(WPA_PTK_GROUP, REKEYNEGOTIATING, wpa_ptk_group); sm->GTimeoutCtr++; - if (sm->GTimeoutCtr > (int) dot11RSNAConfigGroupUpdateCount) { + if (sm->wpa_auth->conf.wpa_disable_eapol_key_retries && + sm->GTimeoutCtr > 1) { + /* Do not allow retransmission of EAPOL-Key group msg 1/2 */ + return; + } + if (sm->GTimeoutCtr > sm->wpa_auth->conf.wpa_group_update_count) { /* No point in sending the EAPOL-Key - we will disconnect * immediately following this. */ return; @@ -2613,7 +3563,8 @@ SM_STATE(WPA_PTK_GROUP, REKEYNEGOTIATING) "sending 1/2 msg of Group Key Handshake"); gtk = gsm->GTK[gsm->GN - 1]; - if (sm->wpa_auth->conf.disable_gtk) { + if (sm->wpa_auth->conf.disable_gtk || + sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) { /* * Provide unique random GTK to each STA to prevent use * of GTK in the BSS. @@ -2624,7 +3575,7 @@ SM_STATE(WPA_PTK_GROUP, REKEYNEGOTIATING) } if (sm->wpa == WPA_VERSION_WPA2) { kde_len = 2 + RSN_SELECTOR_LEN + 2 + gsm->GTK_len + - ieee80211w_kde_len(sm); + ieee80211w_kde_len(sm) + ocv_oci_len(sm); kde_buf = os_malloc(kde_len); if (kde_buf == NULL) return; @@ -2635,6 +3586,10 @@ SM_STATE(WPA_PTK_GROUP, REKEYNEGOTIATING) pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2, gtk, gsm->GTK_len); pos = ieee80211w_kde_add(sm, pos); + if (ocv_oci_add(sm, &pos) < 0) { + os_free(kde_buf); + return; + } kde_len = pos - kde; } else { kde = gtk; @@ -2642,10 +3597,12 @@ SM_STATE(WPA_PTK_GROUP, REKEYNEGOTIATING) } wpa_send_eapol(sm->wpa_auth, sm, - WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC | + WPA_KEY_INFO_SECURE | + (wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len) ? + WPA_KEY_INFO_MIC : 0) | WPA_KEY_INFO_ACK | (!sm->Pair ? WPA_KEY_INFO_INSTALL : 0), - rsc, gsm->GNonce, kde, kde_len, gsm->GN, 1); + rsc, NULL, kde, kde_len, gsm->GN, 1); os_free(kde_buf); } @@ -2653,8 +3610,67 @@ SM_STATE(WPA_PTK_GROUP, REKEYNEGOTIATING) SM_STATE(WPA_PTK_GROUP, REKEYESTABLISHED) { +#ifdef CONFIG_OCV + struct wpa_authenticator *wpa_auth = sm->wpa_auth; + const u8 *key_data, *mic; + struct ieee802_1x_hdr *hdr; + struct wpa_eapol_key *key; + struct wpa_eapol_ie_parse kde; + size_t mic_len; + u16 key_data_length; +#endif /* CONFIG_OCV */ + SM_ENTRY_MA(WPA_PTK_GROUP, REKEYESTABLISHED, wpa_ptk_group); sm->EAPOLKeyReceived = FALSE; + +#ifdef CONFIG_OCV + mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len); + + /* + * Note: last_rx_eapol_key length fields have already been validated in + * wpa_receive(). + */ + hdr = (struct ieee802_1x_hdr *) sm->last_rx_eapol_key; + key = (struct wpa_eapol_key *) (hdr + 1); + mic = (u8 *) (key + 1); + key_data = mic + mic_len + 2; + key_data_length = WPA_GET_BE16(mic + mic_len); + if (key_data_length > sm->last_rx_eapol_key_len - sizeof(*hdr) - + sizeof(*key) - mic_len - 2) + return; + + if (wpa_parse_kde_ies(key_data, key_data_length, &kde) < 0) { + wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, + "received EAPOL-Key group msg 2/2 with invalid Key Data contents"); + return; + } + + if (wpa_auth_uses_ocv(sm)) { + struct wpa_channel_info ci; + int tx_chanwidth; + int tx_seg1_idx; + + if (wpa_channel_info(wpa_auth, &ci) != 0) { + wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, + "Failed to get channel info to validate received OCI in EAPOL-Key group 1/2"); + return; + } + + if (get_sta_tx_parameters(sm, + channel_width_to_int(ci.chanwidth), + ci.seg1_idx, &tx_chanwidth, + &tx_seg1_idx) < 0) + return; + + if (ocv_verify_tx_params(kde.oci, kde.oci_len, &ci, + tx_chanwidth, tx_seg1_idx) != 0) { + wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, + ocv_errorstr); + return; + } + } +#endif /* CONFIG_OCV */ + if (sm->GUpdateStationKeys) sm->group->GKeyDoneStations--; sm->GUpdateStationKeys = FALSE; @@ -2674,6 +3690,10 @@ SM_STATE(WPA_PTK_GROUP, KEYERROR) sm->group->GKeyDoneStations--; sm->GUpdateStationKeys = FALSE; sm->Disconnect = TRUE; + wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_INFO, + "group key handshake failed (%s) after %u tries", + sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN", + sm->wpa_auth->conf.wpa_group_update_count); } @@ -2693,7 +3713,9 @@ SM_STEP(WPA_PTK_GROUP) !sm->EAPOLKeyPairwise && sm->MICVerified) SM_ENTER(WPA_PTK_GROUP, REKEYESTABLISHED); else if (sm->GTimeoutCtr > - (int) dot11RSNAConfigGroupUpdateCount) + sm->wpa_auth->conf.wpa_group_update_count || + (sm->wpa_auth->conf.wpa_disable_eapol_key_retries && + sm->GTimeoutCtr > 1)) SM_ENTER(WPA_PTK_GROUP, KEYERROR); else if (sm->TimeoutEvt) SM_ENTER(WPA_PTK_GROUP, REKEYNEGOTIATING); @@ -2796,7 +3818,7 @@ static int wpa_group_update_sta(struct wpa_state_machine *sm, void *ctx) } -#ifdef CONFIG_WNM +#ifdef CONFIG_WNM_AP /* update GTK when exiting WNM-Sleep Mode */ void wpa_wnmsleep_rekey_gtk(struct wpa_state_machine *sm) { @@ -2875,7 +3897,7 @@ int wpa_wnmsleep_igtk_subelem(struct wpa_state_machine *sm, u8 *pos) return pos - start; } #endif /* CONFIG_IEEE80211W */ -#endif /* CONFIG_WNM */ +#endif /* CONFIG_WNM_AP */ static void wpa_group_setkeys(struct wpa_authenticator *wpa_auth, @@ -3153,8 +4175,8 @@ int wpa_get_mib(struct wpa_authenticator *wpa_auth, char *buf, size_t buflen) "dot11RSNAConfigNumberOfGTKSAReplayCounters=0\n", RSN_VERSION, !!wpa_auth->conf.wpa_strict_rekey, - dot11RSNAConfigGroupUpdateCount, - dot11RSNAConfigPairwiseUpdateCount, + wpa_auth->conf.wpa_group_update_count, + wpa_auth->conf.wpa_pairwise_update_count, wpa_cipher_key_len(wpa_auth->conf.wpa_group) * 8, dot11RSNAConfigPMKLifetime, dot11RSNAConfigPMKReauthThreshold, @@ -3257,6 +4279,15 @@ int wpa_auth_get_pairwise(struct wpa_state_machine *sm) } +const u8 * wpa_auth_get_pmk(struct wpa_state_machine *sm, int *len) +{ + if (!sm) + return NULL; + *len = sm->pmk_len; + return sm->PMK; +} + + int wpa_auth_sta_key_mgmt(struct wpa_state_machine *sm) { if (sm == NULL) @@ -3281,6 +4312,14 @@ int wpa_auth_sta_ft_tk_already_set(struct wpa_state_machine *sm) } +int wpa_auth_sta_fils_tk_already_set(struct wpa_state_machine *sm) +{ + if (!sm || !wpa_key_mgmt_fils(sm->wpa_key_mgmt)) + return 0; + return sm->tk_already_set; +} + + int wpa_auth_sta_clear_pmksa(struct wpa_state_machine *sm, struct rsn_pmksa_cache_entry *entry) { @@ -3322,7 +4361,7 @@ int wpa_auth_pmksa_add(struct wpa_state_machine *sm, const u8 *pmk, sm->wpa_auth->conf.disable_pmksa_caching) return -1; - if (sm->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) { + if (wpa_key_mgmt_sha384(sm->wpa_key_mgmt)) { if (pmk_len > PMK_LEN_SUITE_B_192) pmk_len = PMK_LEN_SUITE_B_192; } else if (pmk_len > PMK_LEN) { @@ -3374,6 +4413,29 @@ int wpa_auth_pmksa_add_sae(struct wpa_authenticator *wpa_auth, const u8 *addr, } +void wpa_auth_add_sae_pmkid(struct wpa_state_machine *sm, const u8 *pmkid) +{ + os_memcpy(sm->pmkid, pmkid, PMKID_LEN); + sm->pmkid_set = 1; +} + + +int wpa_auth_pmksa_add2(struct wpa_authenticator *wpa_auth, const u8 *addr, + const u8 *pmk, size_t pmk_len, const u8 *pmkid, + int session_timeout, int akmp) +{ + if (wpa_auth->conf.disable_pmksa_caching) + return -1; + + if (pmksa_cache_auth_add(wpa_auth->pmksa, pmk, pmk_len, pmkid, + NULL, 0, wpa_auth->addr, addr, session_timeout, + NULL, akmp)) + return 0; + + return -1; +} + + void wpa_auth_pmksa_remove(struct wpa_authenticator *wpa_auth, const u8 *sta_addr) { @@ -3406,12 +4468,65 @@ void wpa_auth_pmksa_flush(struct wpa_authenticator *wpa_auth) } +#ifdef CONFIG_PMKSA_CACHE_EXTERNAL +#ifdef CONFIG_MESH + +int wpa_auth_pmksa_list_mesh(struct wpa_authenticator *wpa_auth, const u8 *addr, + char *buf, size_t len) +{ + if (!wpa_auth || !wpa_auth->pmksa) + return 0; + + return pmksa_cache_auth_list_mesh(wpa_auth->pmksa, addr, buf, len); +} + + struct rsn_pmksa_cache_entry * -wpa_auth_pmksa_get(struct wpa_authenticator *wpa_auth, const u8 *sta_addr) +wpa_auth_pmksa_create_entry(const u8 *aa, const u8 *spa, const u8 *pmk, + const u8 *pmkid, int expiration) +{ + struct rsn_pmksa_cache_entry *entry; + struct os_reltime now; + + entry = pmksa_cache_auth_create_entry(pmk, PMK_LEN, pmkid, NULL, 0, aa, + spa, 0, NULL, WPA_KEY_MGMT_SAE); + if (!entry) + return NULL; + + os_get_reltime(&now); + entry->expiration = now.sec + expiration; + return entry; +} + + +int wpa_auth_pmksa_add_entry(struct wpa_authenticator *wpa_auth, + struct rsn_pmksa_cache_entry *entry) +{ + int ret; + + if (!wpa_auth || !wpa_auth->pmksa) + return -1; + + ret = pmksa_cache_auth_add_entry(wpa_auth->pmksa, entry); + if (ret < 0) + wpa_printf(MSG_DEBUG, + "RSN: Failed to store external PMKSA cache for " + MACSTR, MAC2STR(entry->spa)); + + return ret; +} + +#endif /* CONFIG_MESH */ +#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */ + + +struct rsn_pmksa_cache_entry * +wpa_auth_pmksa_get(struct wpa_authenticator *wpa_auth, const u8 *sta_addr, + const u8 *pmkid) { if (!wpa_auth || !wpa_auth->pmksa) return NULL; - return pmksa_cache_auth_get(wpa_auth->pmksa, sta_addr, NULL); + return pmksa_cache_auth_get(wpa_auth->pmksa, sta_addr, pmkid); } @@ -3664,6 +4779,14 @@ void wpa_auth_eapol_key_tx_status(struct wpa_authenticator *wpa_auth, (timeout_ms % 1000) * 1000, wpa_send_eapol_timeout, wpa_auth, sm); } + +#ifdef CONFIG_TESTING_OPTIONS + if (sm->eapol_status_cb) { + sm->eapol_status_cb(sm->eapol_status_cb_ctx1, + sm->eapol_status_cb_ctx2); + sm->eapol_status_cb = NULL; + } +#endif /* CONFIG_TESTING_OPTIONS */ } @@ -3710,3 +4833,379 @@ void wpa_auth_reconfig_group_keys(struct wpa_authenticator *wpa_auth) for (group = wpa_auth->group; group; group = group->next) wpa_group_config_group_keys(wpa_auth, group); } + + +#ifdef CONFIG_FILS + +struct wpa_auth_fils_iter_data { + struct wpa_authenticator *auth; + const u8 *cache_id; + struct rsn_pmksa_cache_entry *pmksa; + const u8 *spa; + const u8 *pmkid; +}; + + +static int wpa_auth_fils_iter(struct wpa_authenticator *a, void *ctx) +{ + struct wpa_auth_fils_iter_data *data = ctx; + + if (a == data->auth || !a->conf.fils_cache_id_set || + os_memcmp(a->conf.fils_cache_id, data->cache_id, + FILS_CACHE_ID_LEN) != 0) + return 0; + data->pmksa = pmksa_cache_auth_get(a->pmksa, data->spa, data->pmkid); + return data->pmksa != NULL; +} + + +struct rsn_pmksa_cache_entry * +wpa_auth_pmksa_get_fils_cache_id(struct wpa_authenticator *wpa_auth, + const u8 *sta_addr, const u8 *pmkid) +{ + struct wpa_auth_fils_iter_data idata; + + if (!wpa_auth->conf.fils_cache_id_set) + return NULL; + idata.auth = wpa_auth; + idata.cache_id = wpa_auth->conf.fils_cache_id; + idata.pmksa = NULL; + idata.spa = sta_addr; + idata.pmkid = pmkid; + wpa_auth_for_each_auth(wpa_auth, wpa_auth_fils_iter, &idata); + return idata.pmksa; +} + + +#ifdef CONFIG_IEEE80211R_AP +int wpa_auth_write_fte(struct wpa_authenticator *wpa_auth, int use_sha384, + u8 *buf, size_t len) +{ + struct wpa_auth_config *conf = &wpa_auth->conf; + + return wpa_write_ftie(conf, use_sha384, conf->r0_key_holder, + conf->r0_key_holder_len, + NULL, NULL, buf, len, NULL, 0); +} +#endif /* CONFIG_IEEE80211R_AP */ + + +void wpa_auth_get_fils_aead_params(struct wpa_state_machine *sm, + u8 *fils_anonce, u8 *fils_snonce, + u8 *fils_kek, size_t *fils_kek_len) +{ + os_memcpy(fils_anonce, sm->ANonce, WPA_NONCE_LEN); + os_memcpy(fils_snonce, sm->SNonce, WPA_NONCE_LEN); + os_memcpy(fils_kek, sm->PTK.kek, WPA_KEK_MAX_LEN); + *fils_kek_len = sm->PTK.kek_len; +} + + +void wpa_auth_add_fils_pmk_pmkid(struct wpa_state_machine *sm, const u8 *pmk, + size_t pmk_len, const u8 *pmkid) +{ + os_memcpy(sm->PMK, pmk, pmk_len); + sm->pmk_len = pmk_len; + os_memcpy(sm->pmkid, pmkid, PMKID_LEN); + sm->pmkid_set = 1; +} + +#endif /* CONFIG_FILS */ + + +void wpa_auth_set_auth_alg(struct wpa_state_machine *sm, u16 auth_alg) +{ + if (sm) + sm->auth_alg = auth_alg; +} + + +#ifdef CONFIG_DPP2 +void wpa_auth_set_dpp_z(struct wpa_state_machine *sm, const struct wpabuf *z) +{ + if (sm) { + wpabuf_clear_free(sm->dpp_z); + sm->dpp_z = z ? wpabuf_dup(z) : NULL; + } +} +#endif /* CONFIG_DPP2 */ + + +#ifdef CONFIG_TESTING_OPTIONS + +int wpa_auth_resend_m1(struct wpa_state_machine *sm, int change_anonce, + void (*cb)(void *ctx1, void *ctx2), + void *ctx1, void *ctx2) +{ + const u8 *anonce = sm->ANonce; + u8 anonce_buf[WPA_NONCE_LEN]; + + if (change_anonce) { + if (random_get_bytes(anonce_buf, WPA_NONCE_LEN)) + return -1; + anonce = anonce_buf; + } + + wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, + "sending 1/4 msg of 4-Way Handshake (TESTING)"); + wpa_send_eapol(sm->wpa_auth, sm, + WPA_KEY_INFO_ACK | WPA_KEY_INFO_KEY_TYPE, NULL, + anonce, NULL, 0, 0, 0); + return 0; +} + + +int wpa_auth_resend_m3(struct wpa_state_machine *sm, + void (*cb)(void *ctx1, void *ctx2), + void *ctx1, void *ctx2) +{ + u8 rsc[WPA_KEY_RSC_LEN], *_rsc, *gtk, *kde, *pos; +#ifdef CONFIG_IEEE80211W + u8 *opos; +#endif /* CONFIG_IEEE80211W */ + size_t gtk_len, kde_len; + struct wpa_group *gsm = sm->group; + u8 *wpa_ie; + int wpa_ie_len, secure, keyidx, encr = 0; + + /* Send EAPOL(1, 1, 1, Pair, P, RSC, ANonce, MIC(PTK), RSNIE, [MDIE], + GTK[GN], IGTK, [FTIE], [TIE * 2]) + */ + + /* Use 0 RSC */ + os_memset(rsc, 0, WPA_KEY_RSC_LEN); + /* If FT is used, wpa_auth->wpa_ie includes both RSNIE and MDIE */ + wpa_ie = sm->wpa_auth->wpa_ie; + wpa_ie_len = sm->wpa_auth->wpa_ie_len; + if (sm->wpa == WPA_VERSION_WPA && + (sm->wpa_auth->conf.wpa & WPA_PROTO_RSN) && + wpa_ie_len > wpa_ie[1] + 2 && wpa_ie[0] == WLAN_EID_RSN) { + /* WPA-only STA, remove RSN IE and possible MDIE */ + wpa_ie = wpa_ie + wpa_ie[1] + 2; + if (wpa_ie[0] == WLAN_EID_MOBILITY_DOMAIN) + wpa_ie = wpa_ie + wpa_ie[1] + 2; + wpa_ie_len = wpa_ie[1] + 2; + } + wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, + "sending 3/4 msg of 4-Way Handshake (TESTING)"); + if (sm->wpa == WPA_VERSION_WPA2) { + /* WPA2 send GTK in the 4-way handshake */ + secure = 1; + gtk = gsm->GTK[gsm->GN - 1]; + gtk_len = gsm->GTK_len; + keyidx = gsm->GN; + _rsc = rsc; + encr = 1; + } else { + /* WPA does not include GTK in msg 3/4 */ + secure = 0; + gtk = NULL; + gtk_len = 0; + keyidx = 0; + _rsc = NULL; + if (sm->rx_eapol_key_secure) { + /* + * It looks like Windows 7 supplicant tries to use + * Secure bit in msg 2/4 after having reported Michael + * MIC failure and it then rejects the 4-way handshake + * if msg 3/4 does not set Secure bit. Work around this + * by setting the Secure bit here even in the case of + * WPA if the supplicant used it first. + */ + wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, + "STA used Secure bit in WPA msg 2/4 - " + "set Secure for 3/4 as workaround"); + secure = 1; + } + } + + kde_len = wpa_ie_len + ieee80211w_kde_len(sm) + ocv_oci_len(sm); + if (gtk) + kde_len += 2 + RSN_SELECTOR_LEN + 2 + gtk_len; +#ifdef CONFIG_IEEE80211R_AP + if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { + kde_len += 2 + PMKID_LEN; /* PMKR1Name into RSN IE */ + kde_len += 300; /* FTIE + 2 * TIE */ + } +#endif /* CONFIG_IEEE80211R_AP */ + kde = os_malloc(kde_len); + if (kde == NULL) + return -1; + + pos = kde; + os_memcpy(pos, wpa_ie, wpa_ie_len); + pos += wpa_ie_len; +#ifdef CONFIG_IEEE80211R_AP + if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { + int res; + size_t elen; + + elen = pos - kde; + res = wpa_insert_pmkid(kde, &elen, sm->pmk_r1_name); + if (res < 0) { + wpa_printf(MSG_ERROR, "FT: Failed to insert " + "PMKR1Name into RSN IE in EAPOL-Key data"); + os_free(kde); + return -1; + } + pos -= wpa_ie_len; + pos += elen; + } +#endif /* CONFIG_IEEE80211R_AP */ + if (gtk) { + u8 hdr[2]; + hdr[0] = keyidx & 0x03; + hdr[1] = 0; + pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2, + gtk, gtk_len); + } +#ifdef CONFIG_IEEE80211W + opos = pos; + pos = ieee80211w_kde_add(sm, pos); + if (pos - opos >= 2 + RSN_SELECTOR_LEN + WPA_IGTK_KDE_PREFIX_LEN) { + /* skip KDE header and keyid */ + opos += 2 + RSN_SELECTOR_LEN + 2; + os_memset(opos, 0, 6); /* clear PN */ + } +#endif /* CONFIG_IEEE80211W */ + if (ocv_oci_add(sm, &pos) < 0) { + os_free(kde); + return -1; + } + +#ifdef CONFIG_IEEE80211R_AP + if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { + int res; + struct wpa_auth_config *conf; + + conf = &sm->wpa_auth->conf; + if (sm->assoc_resp_ftie && + kde + kde_len - pos >= 2 + sm->assoc_resp_ftie[1]) { + os_memcpy(pos, sm->assoc_resp_ftie, + 2 + sm->assoc_resp_ftie[1]); + res = 2 + sm->assoc_resp_ftie[1]; + } else { + int use_sha384 = wpa_key_mgmt_sha384(sm->wpa_key_mgmt); + + res = wpa_write_ftie(conf, use_sha384, + conf->r0_key_holder, + conf->r0_key_holder_len, + NULL, NULL, pos, + kde + kde_len - pos, + NULL, 0); + } + if (res < 0) { + wpa_printf(MSG_ERROR, "FT: Failed to insert FTIE " + "into EAPOL-Key Key Data"); + os_free(kde); + return -1; + } + pos += res; + + /* TIE[ReassociationDeadline] (TU) */ + *pos++ = WLAN_EID_TIMEOUT_INTERVAL; + *pos++ = 5; + *pos++ = WLAN_TIMEOUT_REASSOC_DEADLINE; + WPA_PUT_LE32(pos, conf->reassociation_deadline); + pos += 4; + + /* TIE[KeyLifetime] (seconds) */ + *pos++ = WLAN_EID_TIMEOUT_INTERVAL; + *pos++ = 5; + *pos++ = WLAN_TIMEOUT_KEY_LIFETIME; + WPA_PUT_LE32(pos, conf->r0_key_lifetime); + pos += 4; + } +#endif /* CONFIG_IEEE80211R_AP */ + + wpa_send_eapol(sm->wpa_auth, sm, + (secure ? WPA_KEY_INFO_SECURE : 0) | + (wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len) ? + WPA_KEY_INFO_MIC : 0) | + WPA_KEY_INFO_ACK | WPA_KEY_INFO_INSTALL | + WPA_KEY_INFO_KEY_TYPE, + _rsc, sm->ANonce, kde, pos - kde, keyidx, encr); + os_free(kde); + return 0; +} + + +int wpa_auth_resend_group_m1(struct wpa_state_machine *sm, + void (*cb)(void *ctx1, void *ctx2), + void *ctx1, void *ctx2) +{ + u8 rsc[WPA_KEY_RSC_LEN]; + struct wpa_group *gsm = sm->group; + const u8 *kde; + u8 *kde_buf = NULL, *pos, hdr[2]; +#ifdef CONFIG_IEEE80211W + u8 *opos; +#endif /* CONFIG_IEEE80211W */ + size_t kde_len; + u8 *gtk; + + /* Send EAPOL(1, 1, 1, !Pair, G, RSC, GNonce, MIC(PTK), GTK[GN]) */ + os_memset(rsc, 0, WPA_KEY_RSC_LEN); + /* Use 0 RSC */ + wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, + "sending 1/2 msg of Group Key Handshake (TESTING)"); + + gtk = gsm->GTK[gsm->GN - 1]; + if (sm->wpa == WPA_VERSION_WPA2) { + kde_len = 2 + RSN_SELECTOR_LEN + 2 + gsm->GTK_len + + ieee80211w_kde_len(sm) + ocv_oci_len(sm); + kde_buf = os_malloc(kde_len); + if (kde_buf == NULL) + return -1; + + kde = pos = kde_buf; + hdr[0] = gsm->GN & 0x03; + hdr[1] = 0; + pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2, + gtk, gsm->GTK_len); +#ifdef CONFIG_IEEE80211W + opos = pos; + pos = ieee80211w_kde_add(sm, pos); + if (pos - opos >= + 2 + RSN_SELECTOR_LEN + WPA_IGTK_KDE_PREFIX_LEN) { + /* skip KDE header and keyid */ + opos += 2 + RSN_SELECTOR_LEN + 2; + os_memset(opos, 0, 6); /* clear PN */ + } +#endif /* CONFIG_IEEE80211W */ + if (ocv_oci_add(sm, &pos) < 0) { + os_free(kde_buf); + return -1; + } + kde_len = pos - kde; + } else { + kde = gtk; + kde_len = gsm->GTK_len; + } + + sm->eapol_status_cb = cb; + sm->eapol_status_cb_ctx1 = ctx1; + sm->eapol_status_cb_ctx2 = ctx2; + + wpa_send_eapol(sm->wpa_auth, sm, + WPA_KEY_INFO_SECURE | + (wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len) ? + WPA_KEY_INFO_MIC : 0) | + WPA_KEY_INFO_ACK | + (!sm->Pair ? WPA_KEY_INFO_INSTALL : 0), + rsc, NULL, kde, kde_len, gsm->GN, 1); + + os_free(kde_buf); + return 0; +} + + +int wpa_auth_rekey_gtk(struct wpa_authenticator *wpa_auth) +{ + if (!wpa_auth) + return -1; + eloop_cancel_timeout(wpa_rekey_gtk, wpa_auth, NULL); + return eloop_register_timeout(0, 0, wpa_rekey_gtk, wpa_auth, NULL); +} + +#endif /* CONFIG_TESTING_OPTIONS */ diff --git a/freebsd/contrib/wpa/src/ap/wpa_auth.h b/freebsd/contrib/wpa/src/ap/wpa_auth.h index 97461b02..df1e17a0 100644 --- a/freebsd/contrib/wpa/src/ap/wpa_auth.h +++ b/freebsd/contrib/wpa/src/ap/wpa_auth.h @@ -1,6 +1,6 @@ /* * hostapd - IEEE 802.11i-2004 / WPA Authenticator - * Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi> + * Copyright (c) 2004-2017, Jouni Malinen <j@w1.fi> * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -14,6 +14,8 @@ #include "common/wpa_common.h" #include "common/ieee802_11_defs.h" +struct vlan_description; + #define MAX_OWN_IE_OVERRIDE 256 #ifdef _MSC_VER @@ -37,74 +39,100 @@ struct ft_rrb_frame { #define FT_PACKET_REQUEST 0 #define FT_PACKET_RESPONSE 1 -/* Vendor-specific types for R0KH-R1KH protocol; not defined in 802.11r */ -#define FT_PACKET_R0KH_R1KH_PULL 200 -#define FT_PACKET_R0KH_R1KH_RESP 201 -#define FT_PACKET_R0KH_R1KH_PUSH 202 - -#define FT_R0KH_R1KH_PULL_NONCE_LEN 16 -#define FT_R0KH_R1KH_PULL_DATA_LEN (FT_R0KH_R1KH_PULL_NONCE_LEN + \ - WPA_PMK_NAME_LEN + FT_R1KH_ID_LEN + \ - ETH_ALEN) -#define FT_R0KH_R1KH_PULL_PAD_LEN ((8 - FT_R0KH_R1KH_PULL_DATA_LEN % 8) % 8) - -struct ft_r0kh_r1kh_pull_frame { - u8 frame_type; /* RSN_REMOTE_FRAME_TYPE_FT_RRB */ - u8 packet_type; /* FT_PACKET_R0KH_R1KH_PULL */ - le16 data_length; /* little endian length of data (44) */ - u8 ap_address[ETH_ALEN]; - u8 nonce[FT_R0KH_R1KH_PULL_NONCE_LEN]; - u8 pmk_r0_name[WPA_PMK_NAME_LEN]; - u8 r1kh_id[FT_R1KH_ID_LEN]; - u8 s1kh_id[ETH_ALEN]; - u8 pad[FT_R0KH_R1KH_PULL_PAD_LEN]; /* 8-octet boundary for AES block */ - u8 key_wrap_extra[8]; -} STRUCT_PACKED; +/* Vendor-specific types for R0KH-R1KH protocol; not defined in 802.11r. These + * use OUI Extended EtherType as the encapsulating format. */ +#define FT_PACKET_R0KH_R1KH_PULL 0x01 +#define FT_PACKET_R0KH_R1KH_RESP 0x02 +#define FT_PACKET_R0KH_R1KH_PUSH 0x03 +#define FT_PACKET_R0KH_R1KH_SEQ_REQ 0x04 +#define FT_PACKET_R0KH_R1KH_SEQ_RESP 0x05 + +/* packet layout + * IEEE 802 extended OUI ethertype frame header + * u16 authlen (little endian) + * multiple of struct ft_rrb_tlv (authenticated only, length = authlen) + * multiple of struct ft_rrb_tlv (AES-SIV encrypted, AES-SIV needs an extra + * blocksize length) + * + * AES-SIV AAD; + * source MAC address (6) + * authenticated-only TLVs (authlen) + * subtype (1; FT_PACKET_*) + */ -#define FT_R0KH_R1KH_RESP_DATA_LEN (FT_R0KH_R1KH_PULL_NONCE_LEN + \ - FT_R1KH_ID_LEN + ETH_ALEN + PMK_LEN + \ - WPA_PMK_NAME_LEN + 2) -#define FT_R0KH_R1KH_RESP_PAD_LEN ((8 - FT_R0KH_R1KH_RESP_DATA_LEN % 8) % 8) -struct ft_r0kh_r1kh_resp_frame { - u8 frame_type; /* RSN_REMOTE_FRAME_TYPE_FT_RRB */ - u8 packet_type; /* FT_PACKET_R0KH_R1KH_RESP */ - le16 data_length; /* little endian length of data (78) */ - u8 ap_address[ETH_ALEN]; +#define FT_RRB_NONCE_LEN 16 - u8 nonce[FT_R0KH_R1KH_PULL_NONCE_LEN]; /* copied from pull */ - u8 r1kh_id[FT_R1KH_ID_LEN]; /* copied from pull */ - u8 s1kh_id[ETH_ALEN]; /* copied from pull */ - u8 pmk_r1[PMK_LEN]; - u8 pmk_r1_name[WPA_PMK_NAME_LEN]; - le16 pairwise; - u8 pad[FT_R0KH_R1KH_RESP_PAD_LEN]; /* 8-octet boundary for AES block */ - u8 key_wrap_extra[8]; -} STRUCT_PACKED; +#define FT_RRB_LAST_EMPTY 0 /* placeholder or padding */ -#define FT_R0KH_R1KH_PUSH_DATA_LEN (4 + FT_R1KH_ID_LEN + ETH_ALEN + \ - WPA_PMK_NAME_LEN + PMK_LEN + \ - WPA_PMK_NAME_LEN + 2) -#define FT_R0KH_R1KH_PUSH_PAD_LEN ((8 - FT_R0KH_R1KH_PUSH_DATA_LEN % 8) % 8) -struct ft_r0kh_r1kh_push_frame { - u8 frame_type; /* RSN_REMOTE_FRAME_TYPE_FT_RRB */ - u8 packet_type; /* FT_PACKET_R0KH_R1KH_PUSH */ - le16 data_length; /* little endian length of data (82) */ - u8 ap_address[ETH_ALEN]; +#define FT_RRB_SEQ 1 /* struct ft_rrb_seq */ +#define FT_RRB_NONCE 2 /* size FT_RRB_NONCE_LEN */ +#define FT_RRB_TIMESTAMP 3 /* le32 unix seconds */ + +#define FT_RRB_R0KH_ID 4 /* FT_R0KH_ID_MAX_LEN */ +#define FT_RRB_R1KH_ID 5 /* FT_R1KH_ID_LEN */ +#define FT_RRB_S1KH_ID 6 /* ETH_ALEN */ + +#define FT_RRB_PMK_R0_NAME 7 /* WPA_PMK_NAME_LEN */ +#define FT_RRB_PMK_R0 8 /* PMK_LEN */ +#define FT_RRB_PMK_R1_NAME 9 /* WPA_PMK_NAME_LEN */ +#define FT_RRB_PMK_R1 10 /* PMK_LEN */ + +#define FT_RRB_PAIRWISE 11 /* le16 */ +#define FT_RRB_EXPIRES_IN 12 /* le16 seconds */ + +#define FT_RRB_VLAN_UNTAGGED 13 /* le16 */ +#define FT_RRB_VLAN_TAGGED 14 /* n times le16 */ - /* Encrypted with AES key-wrap */ - u8 timestamp[4]; /* current time in seconds since unix epoch, little - * endian */ - u8 r1kh_id[FT_R1KH_ID_LEN]; - u8 s1kh_id[ETH_ALEN]; - u8 pmk_r0_name[WPA_PMK_NAME_LEN]; - u8 pmk_r1[PMK_LEN]; - u8 pmk_r1_name[WPA_PMK_NAME_LEN]; - le16 pairwise; - u8 pad[FT_R0KH_R1KH_PUSH_PAD_LEN]; /* 8-octet boundary for AES block */ - u8 key_wrap_extra[8]; +#define FT_RRB_IDENTITY 15 +#define FT_RRB_RADIUS_CUI 16 +#define FT_RRB_SESSION_TIMEOUT 17 /* le32 seconds */ + +struct ft_rrb_tlv { + le16 type; + le16 len; + /* followed by data of length len */ +} STRUCT_PACKED; + +struct ft_rrb_seq { + le32 dom; + le32 seq; + le32 ts; } STRUCT_PACKED; +/* session TLVs: + * required: PMK_R1, PMK_R1_NAME, PAIRWISE + * optional: VLAN_UNTAGGED, VLAN_TAGGED, EXPIRES_IN, IDENTITY, RADIUS_CUI, + * SESSION_TIMEOUT + * + * pull frame TLVs: + * auth: + * required: SEQ, NONCE, R0KH_ID, R1KH_ID + * encrypted: + * required: PMK_R0_NAME, S1KH_ID + * + * response frame TLVs: + * auth: + * required: SEQ, NONCE, R0KH_ID, R1KH_ID + * encrypted: + * required: S1KH_ID + * optional: session TLVs + * + * push frame TLVs: + * auth: + * required: SEQ, R0KH_ID, R1KH_ID + * encrypted: + * required: S1KH_ID, PMK_R0_NAME, session TLVs + * + * sequence number request frame TLVs: + * auth: + * required: R0KH_ID, R1KH_ID, NONCE + * + * sequence number response frame TLVs: + * auth: + * required: SEQ, NONCE, R0KH_ID, R1KH_ID + */ + #ifdef _MSC_VER #pragma pack(pop) #endif /* _MSC_VER */ @@ -116,6 +144,8 @@ struct wpa_authenticator; struct wpa_state_machine; struct rsn_pmksa_cache_entry; struct eapol_state_machine; +struct ft_remote_seq; +struct wpa_channel_info; struct ft_remote_r0kh { @@ -123,7 +153,8 @@ struct ft_remote_r0kh { u8 addr[ETH_ALEN]; u8 id[FT_R0KH_ID_MAX_LEN]; size_t id_len; - u8 key[16]; + u8 key[32]; + struct ft_remote_seq *seq; }; @@ -131,7 +162,8 @@ struct ft_remote_r1kh { struct ft_remote_r1kh *next; u8 addr[ETH_ALEN]; u8 id[FT_R1KH_ID_LEN]; - u8 key[16]; + u8 key[32]; + struct ft_remote_seq *seq; }; @@ -144,10 +176,12 @@ struct wpa_auth_config { int wpa_strict_rekey; int wpa_gmk_rekey; int wpa_ptk_rekey; + u32 wpa_group_update_count; + u32 wpa_pairwise_update_count; + int wpa_disable_eapol_key_retries; int rsn_pairwise; int rsn_preauth; int eapol_version; - int peerkey; int wmm_enabled; int wmm_uapsd; int disable_pmksa_caching; @@ -156,21 +190,31 @@ struct wpa_auth_config { #ifdef CONFIG_IEEE80211W enum mfp_options ieee80211w; int group_mgmt_cipher; + int sae_require_mfp; #endif /* CONFIG_IEEE80211W */ -#ifdef CONFIG_IEEE80211R +#ifdef CONFIG_OCV + int ocv; /* Operating Channel Validation */ +#endif /* CONFIG_OCV */ +#ifdef CONFIG_IEEE80211R_AP u8 ssid[SSID_MAX_LEN]; size_t ssid_len; u8 mobility_domain[MOBILITY_DOMAIN_ID_LEN]; u8 r0_key_holder[FT_R0KH_ID_MAX_LEN]; size_t r0_key_holder_len; u8 r1_key_holder[FT_R1KH_ID_LEN]; - u32 r0_key_lifetime; + u32 r0_key_lifetime; /* PMK-R0 lifetime seconds */ + int rkh_pos_timeout; + int rkh_neg_timeout; + int rkh_pull_timeout; /* ms */ + int rkh_pull_retries; + int r1_max_key_lifetime; u32 reassociation_deadline; - struct ft_remote_r0kh *r0kh_list; - struct ft_remote_r1kh *r1kh_list; + struct ft_remote_r0kh **r0kh_list; + struct ft_remote_r1kh **r1kh_list; int pmk_r1_push; int ft_over_ds; -#endif /* CONFIG_IEEE80211R */ + int ft_psk_generate_local; +#endif /* CONFIG_IEEE80211R_AP */ int disable_gtk; int ap_mlme; #ifdef CONFIG_TESTING_OPTIONS @@ -184,6 +228,10 @@ struct wpa_auth_config { u8 ip_addr_start[4]; u8 ip_addr_end[4]; #endif /* CONFIG_P2P */ +#ifdef CONFIG_FILS + unsigned int fils_cache_id_set:1; + u8 fils_cache_id[FILS_CACHE_ID_LEN]; +#endif /* CONFIG_FILS */ }; typedef enum { @@ -197,7 +245,6 @@ typedef enum { } wpa_eapol_variable; struct wpa_auth_callbacks { - void *ctx; void (*logger)(void *ctx, const u8 *addr, logger_level level, const char *txt); void (*disconnect)(void *ctx, const u8 *addr, u16 reason); @@ -207,7 +254,8 @@ struct wpa_auth_callbacks { int value); int (*get_eapol)(void *ctx, const u8 *addr, wpa_eapol_variable var); const u8 * (*get_psk)(void *ctx, const u8 *addr, const u8 *p2p_dev_addr, - const u8 *prev_psk); + 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); @@ -220,13 +268,34 @@ struct wpa_auth_callbacks { void *ctx), void *cb_ctx); int (*send_ether)(void *ctx, const u8 *dst, u16 proto, const u8 *data, size_t data_len); -#ifdef CONFIG_IEEE80211R + int (*send_oui)(void *ctx, const u8 *dst, u8 oui_suffix, const u8 *data, + size_t data_len); + int (*channel_info)(void *ctx, struct wpa_channel_info *ci); + int (*update_vlan)(void *ctx, const u8 *addr, int vlan_id); + int (*get_sta_tx_params)(void *ctx, const u8 *addr, + int ap_max_chanwidth, int ap_seg1_idx, + int *bandwidth, int *seg1_idx); +#ifdef CONFIG_IEEE80211R_AP struct wpa_state_machine * (*add_sta)(void *ctx, const u8 *sta_addr); + int (*set_vlan)(void *ctx, const u8 *sta_addr, + struct vlan_description *vlan); + int (*get_vlan)(void *ctx, const u8 *sta_addr, + struct vlan_description *vlan); + int (*set_identity)(void *ctx, const u8 *sta_addr, + const u8 *identity, size_t identity_len); + size_t (*get_identity)(void *ctx, const u8 *sta_addr, const u8 **buf); + int (*set_radius_cui)(void *ctx, const u8 *sta_addr, + const u8 *radius_cui, size_t radius_cui_len); + size_t (*get_radius_cui)(void *ctx, const u8 *sta_addr, const u8 **buf); + void (*set_session_timeout)(void *ctx, const u8 *sta_addr, + int session_timeout); + int (*get_session_timeout)(void *ctx, const u8 *sta_addr); + int (*send_ft_action)(void *ctx, const u8 *dst, const u8 *data, size_t data_len); int (*add_tspec)(void *ctx, const u8 *sta_addr, u8 *tspec_ie, size_t tspec_ielen); -#endif /* CONFIG_IEEE80211R */ +#endif /* CONFIG_IEEE80211R_AP */ #ifdef CONFIG_MESH int (*start_ampe)(void *ctx, const u8 *sta_addr); #endif /* CONFIG_MESH */ @@ -234,7 +303,8 @@ struct wpa_auth_callbacks { struct wpa_authenticator * wpa_init(const u8 *addr, struct wpa_auth_config *conf, - struct wpa_auth_callbacks *cb); + const struct wpa_auth_callbacks *cb, + void *cb_ctx); int wpa_init_keys(struct wpa_authenticator *wpa_auth); void wpa_deinit(struct wpa_authenticator *wpa_auth); int wpa_reconfig(struct wpa_authenticator *wpa_auth, @@ -244,17 +314,20 @@ enum { WPA_IE_OK, WPA_INVALID_IE, WPA_INVALID_GROUP, WPA_INVALID_PAIRWISE, WPA_INVALID_AKMP, WPA_NOT_ENABLED, WPA_ALLOC_FAIL, WPA_MGMT_FRAME_PROTECTION_VIOLATION, WPA_INVALID_MGMT_GROUP_CIPHER, - WPA_INVALID_MDIE, WPA_INVALID_PROTO + WPA_INVALID_MDIE, WPA_INVALID_PROTO, WPA_INVALID_PMKID }; - + int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, - struct wpa_state_machine *sm, + struct wpa_state_machine *sm, int freq, const u8 *wpa_ie, size_t wpa_ie_len, - const u8 *mdie, size_t mdie_len); + const u8 *mdie, size_t mdie_len, + const u8 *owe_dh, size_t owe_dh_len); int wpa_validate_osen(struct wpa_authenticator *wpa_auth, struct wpa_state_machine *sm, const u8 *osen_ie, size_t osen_ie_len); int wpa_auth_uses_mfp(struct wpa_state_machine *sm); +void wpa_auth_set_ocv(struct wpa_state_machine *sm, int ocv); +int wpa_auth_uses_ocv(struct wpa_state_machine *sm); struct wpa_state_machine * wpa_auth_sta_init(struct wpa_authenticator *wpa_auth, const u8 *addr, const u8 *p2p_dev_addr); @@ -267,7 +340,7 @@ void wpa_receive(struct wpa_authenticator *wpa_auth, u8 *data, size_t data_len); enum wpa_event { WPA_AUTH, WPA_ASSOC, WPA_DISASSOC, WPA_DEAUTH, WPA_REAUTH, - WPA_REAUTH_EAPOL, WPA_ASSOC_FT, WPA_DRV_STA_REMOVED + WPA_REAUTH_EAPOL, WPA_ASSOC_FT, WPA_ASSOC_FILS, WPA_DRV_STA_REMOVED }; void wpa_remove_ptk(struct wpa_state_machine *sm); int wpa_auth_sm_event(struct wpa_state_machine *sm, enum wpa_event event); @@ -278,9 +351,11 @@ int wpa_get_mib_sta(struct wpa_state_machine *sm, char *buf, size_t buflen); void wpa_auth_countermeasures_start(struct wpa_authenticator *wpa_auth); int wpa_auth_pairwise_set(struct wpa_state_machine *sm); int wpa_auth_get_pairwise(struct wpa_state_machine *sm); +const u8 * wpa_auth_get_pmk(struct wpa_state_machine *sm, int *len); int wpa_auth_sta_key_mgmt(struct wpa_state_machine *sm); int wpa_auth_sta_wpa_version(struct wpa_state_machine *sm); int wpa_auth_sta_ft_tk_already_set(struct wpa_state_machine *sm); +int wpa_auth_sta_fils_tk_already_set(struct wpa_state_machine *sm); int wpa_auth_sta_clear_pmksa(struct wpa_state_machine *sm, struct rsn_pmksa_cache_entry *entry); struct rsn_pmksa_cache_entry * @@ -297,13 +372,28 @@ int wpa_auth_pmksa_add_preauth(struct wpa_authenticator *wpa_auth, struct eapol_state_machine *eapol); int wpa_auth_pmksa_add_sae(struct wpa_authenticator *wpa_auth, const u8 *addr, const u8 *pmk, const u8 *pmkid); +void wpa_auth_add_sae_pmkid(struct wpa_state_machine *sm, const u8 *pmkid); +int wpa_auth_pmksa_add2(struct wpa_authenticator *wpa_auth, const u8 *addr, + const u8 *pmk, size_t pmk_len, const u8 *pmkid, + int session_timeout, int akmp); void wpa_auth_pmksa_remove(struct wpa_authenticator *wpa_auth, const u8 *sta_addr); int wpa_auth_pmksa_list(struct wpa_authenticator *wpa_auth, char *buf, size_t len); void wpa_auth_pmksa_flush(struct wpa_authenticator *wpa_auth); +int wpa_auth_pmksa_list_mesh(struct wpa_authenticator *wpa_auth, const u8 *addr, + char *buf, size_t len); +struct rsn_pmksa_cache_entry * +wpa_auth_pmksa_create_entry(const u8 *aa, const u8 *spa, const u8 *pmk, + const u8 *pmkid, int expiration); +int wpa_auth_pmksa_add_entry(struct wpa_authenticator *wpa_auth, + struct rsn_pmksa_cache_entry *entry); +struct rsn_pmksa_cache_entry * +wpa_auth_pmksa_get(struct wpa_authenticator *wpa_auth, const u8 *sta_addr, + const u8 *pmkid); struct rsn_pmksa_cache_entry * -wpa_auth_pmksa_get(struct wpa_authenticator *wpa_auth, const u8 *sta_addr); +wpa_auth_pmksa_get_fils_cache_id(struct wpa_authenticator *wpa_auth, + const u8 *sta_addr, const u8 *pmkid); void wpa_auth_pmksa_set_to_sm(struct rsn_pmksa_cache_entry *pmksa, struct wpa_state_machine *sm, struct wpa_authenticator *wpa_auth, @@ -312,7 +402,7 @@ int wpa_auth_sta_set_vlan(struct wpa_state_machine *sm, int vlan_id); void wpa_auth_eapol_key_tx_status(struct wpa_authenticator *wpa_auth, struct wpa_state_machine *sm, int ack); -#ifdef CONFIG_IEEE80211R +#ifdef CONFIG_IEEE80211R_AP u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos, size_t max_len, int auth_alg, const u8 *req_ies, size_t req_ies_len); @@ -327,8 +417,13 @@ u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, int wpa_ft_action_rx(struct wpa_state_machine *sm, const u8 *data, size_t len); int wpa_ft_rrb_rx(struct wpa_authenticator *wpa_auth, const u8 *src_addr, const u8 *data, size_t data_len); +void wpa_ft_rrb_oui_rx(struct wpa_authenticator *wpa_auth, const u8 *src_addr, + const u8 *dst_addr, u8 oui_suffix, const u8 *data, + size_t data_len); void wpa_ft_push_pmk_r1(struct wpa_authenticator *wpa_auth, const u8 *addr); -#endif /* CONFIG_IEEE80211R */ +void wpa_ft_deinit(struct wpa_authenticator *wpa_auth); +void wpa_ft_sta_deinit(struct wpa_state_machine *sm); +#endif /* CONFIG_IEEE80211R_AP */ void wpa_wnmsleep_rekey_gtk(struct wpa_state_machine *sm); void wpa_set_wnmsleep(struct wpa_state_machine *sm, int flag); @@ -347,5 +442,52 @@ void wpa_auth_reconfig_group_keys(struct wpa_authenticator *wpa_auth); int wpa_auth_ensure_group(struct wpa_authenticator *wpa_auth, int vlan_id); int wpa_auth_release_group(struct wpa_authenticator *wpa_auth, int vlan_id); +int fils_auth_pmk_to_ptk(struct wpa_state_machine *sm, const u8 *pmk, + size_t pmk_len, const u8 *snonce, const u8 *anonce, + const u8 *dhss, size_t dhss_len, + struct wpabuf *g_sta, struct wpabuf *g_ap); +int fils_decrypt_assoc(struct wpa_state_machine *sm, const u8 *fils_session, + const struct ieee80211_mgmt *mgmt, size_t frame_len, + u8 *pos, size_t left); +int fils_encrypt_assoc(struct wpa_state_machine *sm, u8 *buf, + size_t current_len, size_t max_len, + const struct wpabuf *hlp); +int fils_set_tk(struct wpa_state_machine *sm); +u8 * hostapd_eid_assoc_fils_session(struct wpa_state_machine *sm, u8 *eid, + const u8 *fils_session, + struct wpabuf *fils_hlp_resp); +const u8 * wpa_fils_validate_fils_session(struct wpa_state_machine *sm, + const u8 *ies, size_t ies_len, + const u8 *fils_session); +int wpa_fils_validate_key_confirm(struct wpa_state_machine *sm, const u8 *ies, + size_t ies_len); + +int get_sta_tx_parameters(struct wpa_state_machine *sm, int ap_max_chanwidth, + int ap_seg1_idx, int *bandwidth, int *seg1_idx); + +int wpa_auth_write_fte(struct wpa_authenticator *wpa_auth, int use_sha384, + u8 *buf, size_t len); +void wpa_auth_get_fils_aead_params(struct wpa_state_machine *sm, + u8 *fils_anonce, u8 *fils_snonce, + u8 *fils_kek, size_t *fils_kek_len); +void wpa_auth_add_fils_pmk_pmkid(struct wpa_state_machine *sm, const u8 *pmk, + size_t pmk_len, const u8 *pmkid); +u8 * wpa_auth_write_assoc_resp_owe(struct wpa_state_machine *sm, + u8 *pos, size_t max_len, + const u8 *req_ies, size_t req_ies_len); +void wpa_auth_set_auth_alg(struct wpa_state_machine *sm, u16 auth_alg); +void wpa_auth_set_dpp_z(struct wpa_state_machine *sm, const struct wpabuf *z); + +int wpa_auth_resend_m1(struct wpa_state_machine *sm, int change_anonce, + void (*cb)(void *ctx1, void *ctx2), + void *ctx1, void *ctx2); +int wpa_auth_resend_m3(struct wpa_state_machine *sm, + void (*cb)(void *ctx1, void *ctx2), + void *ctx1, void *ctx2); +int wpa_auth_resend_group_m1(struct wpa_state_machine *sm, + void (*cb)(void *ctx1, void *ctx2), + void *ctx1, void *ctx2); +int wpa_auth_rekey_gtk(struct wpa_authenticator *wpa_auth); +void wpa_auth_set_ptk_rekey_timer(struct wpa_state_machine *sm); #endif /* WPA_AUTH_H */ diff --git a/freebsd/contrib/wpa/src/ap/wpa_auth_ft.c b/freebsd/contrib/wpa/src/ap/wpa_auth_ft.c index fe145fad..e2eaacbd 100644 --- a/freebsd/contrib/wpa/src/ap/wpa_auth_ft.c +++ b/freebsd/contrib/wpa/src/ap/wpa_auth_ft.c @@ -2,7 +2,7 @@ /* * hostapd - IEEE 802.11r - Fast BSS Transition - * Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi> + * Copyright (c) 2004-2018, Jouni Malinen <j@w1.fi> * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -15,7 +15,12 @@ #include "utils/list.h" #include "common/ieee802_11_defs.h" #include "common/ieee802_11_common.h" +#include "common/ocv.h" +#include "drivers/driver.h" +#include "crypto/aes.h" +#include "crypto/aes_siv.h" #include "crypto/aes_wrap.h" +#include "crypto/sha384.h" #include "crypto/random.h" #include "ap_config.h" #include "ieee802_11.h" @@ -24,41 +29,735 @@ #include "wpa_auth_i.h" -#ifdef CONFIG_IEEE80211R +#ifdef CONFIG_IEEE80211R_AP + +const unsigned int ftRRBseqTimeout = 10; +const unsigned int ftRRBmaxQueueLen = 100; + static int wpa_ft_send_rrb_auth_resp(struct wpa_state_machine *sm, const u8 *current_ap, const u8 *sta_addr, u16 status, const u8 *resp_ies, size_t resp_ies_len); +static void ft_finish_pull(struct wpa_state_machine *sm); +static void wpa_ft_expire_pull(void *eloop_ctx, void *timeout_ctx); +static void wpa_ft_rrb_seq_timeout(void *eloop_ctx, void *timeout_ctx); + +struct tlv_list { + u16 type; + size_t len; + const u8 *data; +}; + + +/** + * wpa_ft_rrb_decrypt - Decrypt FT RRB message + * @key: AES-SIV key for AEAD + * @key_len: Length of key in octets + * @enc: Pointer to encrypted TLVs + * @enc_len: Length of encrypted TLVs in octets + * @auth: Pointer to authenticated TLVs + * @auth_len: Length of authenticated TLVs in octets + * @src_addr: MAC address of the frame sender + * @type: Vendor-specific subtype of the RRB frame (FT_PACKET_*) + * @plain: Pointer to return the pointer to the allocated plaintext buffer; + * needs to be freed by the caller if not NULL; + * will only be returned on success + * @plain_len: Pointer to return the length of the allocated plaintext buffer + * in octets + * Returns: 0 on success, -1 on error + */ +static int wpa_ft_rrb_decrypt(const u8 *key, const size_t key_len, + const u8 *enc, size_t enc_len, + const u8 *auth, const size_t auth_len, + const u8 *src_addr, u8 type, + u8 **plain, size_t *plain_size) +{ + const u8 *ad[3] = { src_addr, auth, &type }; + size_t ad_len[3] = { ETH_ALEN, auth_len, sizeof(type) }; + + wpa_printf(MSG_DEBUG, "FT(RRB): src_addr=" MACSTR " type=%u", + MAC2STR(src_addr), type); + wpa_hexdump_key(MSG_DEBUG, "FT(RRB): decrypt using key", key, key_len); + wpa_hexdump(MSG_DEBUG, "FT(RRB): encrypted TLVs", enc, enc_len); + wpa_hexdump(MSG_DEBUG, "FT(RRB): authenticated TLVs", auth, auth_len); + + if (!key) { /* skip decryption */ + *plain = os_memdup(enc, enc_len); + if (enc_len > 0 && !*plain) + goto err; + + *plain_size = enc_len; + + return 0; + } + + *plain = NULL; + + /* SIV overhead */ + if (enc_len < AES_BLOCK_SIZE) + goto err; + + *plain = os_zalloc(enc_len - AES_BLOCK_SIZE); + if (!*plain) + goto err; + + if (aes_siv_decrypt(key, key_len, enc, enc_len, 3, ad, ad_len, + *plain) < 0) { + if (enc_len < AES_BLOCK_SIZE + 2) + goto err; + + /* Try to work around Ethernet devices that add extra + * two octet padding even if the frame is longer than + * the minimum Ethernet frame. */ + enc_len -= 2; + if (aes_siv_decrypt(key, key_len, enc, enc_len, 3, ad, ad_len, + *plain) < 0) + goto err; + } + + *plain_size = enc_len - AES_BLOCK_SIZE; + wpa_hexdump_key(MSG_DEBUG, "FT(RRB): decrypted TLVs", + *plain, *plain_size); + return 0; +err: + os_free(*plain); + *plain = NULL; + *plain_size = 0; + + wpa_printf(MSG_ERROR, "FT(RRB): Failed to decrypt"); + + return -1; +} + + +/* get first tlv record in packet matching type + * @data (decrypted) packet + * @return 0 on success else -1 + */ +static int wpa_ft_rrb_get_tlv(const u8 *plain, size_t plain_len, + u16 type, size_t *tlv_len, const u8 **tlv_data) +{ + const struct ft_rrb_tlv *f; + size_t left; + le16 type16; + size_t len; + left = plain_len; + type16 = host_to_le16(type); + + while (left >= sizeof(*f)) { + f = (const struct ft_rrb_tlv *) plain; + + left -= sizeof(*f); + plain += sizeof(*f); + len = le_to_host16(f->len); + + if (left < len) { + wpa_printf(MSG_DEBUG, "FT: RRB message truncated"); + break; + } + + if (f->type == type16) { + *tlv_len = len; + *tlv_data = plain; + return 0; + } + + left -= len; + plain += len; + } + + return -1; +} + + +static void wpa_ft_rrb_dump(const u8 *plain, const size_t plain_len) +{ + const struct ft_rrb_tlv *f; + size_t left; + size_t len; + + left = plain_len; + + wpa_printf(MSG_DEBUG, "FT: RRB dump message"); + while (left >= sizeof(*f)) { + f = (const struct ft_rrb_tlv *) plain; + + left -= sizeof(*f); + plain += sizeof(*f); + len = le_to_host16(f->len); + + wpa_printf(MSG_DEBUG, "FT: RRB TLV type = %d, len = %zu", + le_to_host16(f->type), len); + + if (left < len) { + wpa_printf(MSG_DEBUG, + "FT: RRB message truncated: left %zu bytes, need %zu", + left, len); + break; + } + + wpa_hexdump(MSG_DEBUG, "FT: RRB TLV data", plain, len); + + left -= len; + plain += len; + } + + if (left > 0) + wpa_hexdump(MSG_DEBUG, "FT: RRB TLV padding", plain, left); + + wpa_printf(MSG_DEBUG, "FT: RRB dump message end"); +} + + +static int cmp_int(const void *a, const void *b) +{ + int x, y; + + x = *((int *) a); + y = *((int *) b); + return x - y; +} + + +static int wpa_ft_rrb_get_tlv_vlan(const u8 *plain, const size_t plain_len, + struct vlan_description *vlan) +{ + struct ft_rrb_tlv *f; + size_t left; + size_t len; + int taggedidx; + int vlan_id; + int type; + + left = plain_len; + taggedidx = 0; + os_memset(vlan, 0, sizeof(*vlan)); + + while (left >= sizeof(*f)) { + f = (struct ft_rrb_tlv *) plain; + + left -= sizeof(*f); + plain += sizeof(*f); + + len = le_to_host16(f->len); + type = le_to_host16(f->type); + + if (left < len) { + wpa_printf(MSG_DEBUG, "FT: RRB message truncated"); + return -1; + } + + if (type != FT_RRB_VLAN_UNTAGGED && type != FT_RRB_VLAN_TAGGED) + goto skip; + + if (type == FT_RRB_VLAN_UNTAGGED && len != sizeof(le16)) { + wpa_printf(MSG_DEBUG, + "FT: RRB VLAN_UNTAGGED invalid length"); + return -1; + } + + if (type == FT_RRB_VLAN_TAGGED && len % sizeof(le16) != 0) { + wpa_printf(MSG_DEBUG, + "FT: RRB VLAN_TAGGED invalid length"); + return -1; + } + + while (len >= sizeof(le16)) { + vlan_id = WPA_GET_LE16(plain); + plain += sizeof(le16); + left -= sizeof(le16); + len -= sizeof(le16); + + if (vlan_id <= 0 || vlan_id > MAX_VLAN_ID) { + wpa_printf(MSG_DEBUG, + "FT: RRB VLAN ID invalid %d", + vlan_id); + continue; + } + + if (type == FT_RRB_VLAN_UNTAGGED) + vlan->untagged = vlan_id; + + if (type == FT_RRB_VLAN_TAGGED && + taggedidx < MAX_NUM_TAGGED_VLAN) { + vlan->tagged[taggedidx] = vlan_id; + taggedidx++; + } else if (type == FT_RRB_VLAN_TAGGED) { + wpa_printf(MSG_DEBUG, "FT: RRB too many VLANs"); + } + } + + skip: + left -= len; + plain += len; + } + + if (taggedidx) + qsort(vlan->tagged, taggedidx, sizeof(int), cmp_int); + + vlan->notempty = vlan->untagged || vlan->tagged[0]; + + return 0; +} + + +static size_t wpa_ft_tlv_len(const struct tlv_list *tlvs) +{ + size_t tlv_len = 0; + int i; + + if (!tlvs) + return 0; + + for (i = 0; tlvs[i].type != FT_RRB_LAST_EMPTY; i++) { + tlv_len += sizeof(struct ft_rrb_tlv); + tlv_len += tlvs[i].len; + } + + return tlv_len; +} + + +static size_t wpa_ft_tlv_lin(const struct tlv_list *tlvs, u8 *start, + u8 *endpos) +{ + int i; + size_t tlv_len; + struct ft_rrb_tlv *hdr; + u8 *pos; + + if (!tlvs) + return 0; + + tlv_len = 0; + pos = start; + for (i = 0; tlvs[i].type != FT_RRB_LAST_EMPTY; i++) { + if (tlv_len + sizeof(*hdr) > (size_t) (endpos - start)) + return tlv_len; + tlv_len += sizeof(*hdr); + hdr = (struct ft_rrb_tlv *) pos; + hdr->type = host_to_le16(tlvs[i].type); + hdr->len = host_to_le16(tlvs[i].len); + pos = start + tlv_len; + + if (tlv_len + tlvs[i].len > (size_t) (endpos - start)) + return tlv_len; + if (tlvs[i].len == 0) + continue; + tlv_len += tlvs[i].len; + os_memcpy(pos, tlvs[i].data, tlvs[i].len); + pos = start + tlv_len; + } + + return tlv_len; +} + + +static size_t wpa_ft_vlan_len(const struct vlan_description *vlan) +{ + size_t tlv_len = 0; + int i; + + if (!vlan || !vlan->notempty) + return 0; + + if (vlan->untagged) { + tlv_len += sizeof(struct ft_rrb_tlv); + tlv_len += sizeof(le16); + } + if (vlan->tagged[0]) + tlv_len += sizeof(struct ft_rrb_tlv); + for (i = 0; i < MAX_NUM_TAGGED_VLAN && vlan->tagged[i]; i++) + tlv_len += sizeof(le16); + + return tlv_len; +} + + +static size_t wpa_ft_vlan_lin(const struct vlan_description *vlan, + u8 *start, u8 *endpos) +{ + size_t tlv_len; + int i, len; + struct ft_rrb_tlv *hdr; + u8 *pos = start; + + if (!vlan || !vlan->notempty) + return 0; + + tlv_len = 0; + if (vlan->untagged) { + tlv_len += sizeof(*hdr); + if (start + tlv_len > endpos) + return tlv_len; + hdr = (struct ft_rrb_tlv *) pos; + hdr->type = host_to_le16(FT_RRB_VLAN_UNTAGGED); + hdr->len = host_to_le16(sizeof(le16)); + pos = start + tlv_len; + + tlv_len += sizeof(le16); + if (start + tlv_len > endpos) + return tlv_len; + WPA_PUT_LE16(pos, vlan->untagged); + pos = start + tlv_len; + } + + if (!vlan->tagged[0]) + return tlv_len; + + tlv_len += sizeof(*hdr); + if (start + tlv_len > endpos) + return tlv_len; + hdr = (struct ft_rrb_tlv *) pos; + hdr->type = host_to_le16(FT_RRB_VLAN_TAGGED); + len = 0; /* len is computed below */ + pos = start + tlv_len; + + for (i = 0; i < MAX_NUM_TAGGED_VLAN && vlan->tagged[i]; i++) { + tlv_len += sizeof(le16); + if (start + tlv_len > endpos) + break; + len += sizeof(le16); + WPA_PUT_LE16(pos, vlan->tagged[i]); + pos = start + tlv_len; + } + + hdr->len = host_to_le16(len); + + return tlv_len; +} + + +static int wpa_ft_rrb_lin(const struct tlv_list *tlvs1, + const struct tlv_list *tlvs2, + const struct vlan_description *vlan, + u8 **plain, size_t *plain_len) +{ + u8 *pos, *endpos; + size_t tlv_len; + + tlv_len = wpa_ft_tlv_len(tlvs1); + tlv_len += wpa_ft_tlv_len(tlvs2); + tlv_len += wpa_ft_vlan_len(vlan); + + *plain_len = tlv_len; + *plain = os_zalloc(tlv_len); + if (!*plain) { + wpa_printf(MSG_ERROR, "FT: Failed to allocate plaintext"); + goto err; + } + + pos = *plain; + endpos = *plain + tlv_len; + pos += wpa_ft_tlv_lin(tlvs1, pos, endpos); + pos += wpa_ft_tlv_lin(tlvs2, pos, endpos); + pos += wpa_ft_vlan_lin(vlan, pos, endpos); + + /* sanity check */ + if (pos != endpos) { + wpa_printf(MSG_ERROR, "FT: Length error building RRB"); + goto err; + } + + return 0; + +err: + os_free(*plain); + *plain = NULL; + *plain_len = 0; + return -1; +} + + +static int wpa_ft_rrb_encrypt(const u8 *key, const size_t key_len, + const u8 *plain, const size_t plain_len, + const u8 *auth, const size_t auth_len, + const u8 *src_addr, u8 type, u8 *enc) +{ + const u8 *ad[3] = { src_addr, auth, &type }; + size_t ad_len[3] = { ETH_ALEN, auth_len, sizeof(type) }; + + wpa_printf(MSG_DEBUG, "FT(RRB): src_addr=" MACSTR " type=%u", + MAC2STR(src_addr), type); + wpa_hexdump_key(MSG_DEBUG, "FT(RRB): plaintext message", + plain, plain_len); + wpa_hexdump_key(MSG_DEBUG, "FT(RRB): encrypt using key", key, key_len); + wpa_hexdump(MSG_DEBUG, "FT(RRB): authenticated TLVs", auth, auth_len); + + if (!key) { + /* encryption not needed, return plaintext as packet */ + os_memcpy(enc, plain, plain_len); + } else if (aes_siv_encrypt(key, key_len, plain, plain_len, + 3, ad, ad_len, enc) < 0) { + wpa_printf(MSG_ERROR, "FT: Failed to encrypt RRB-OUI message"); + return -1; + } + wpa_hexdump(MSG_DEBUG, "FT(RRB): encrypted TLVs", + enc, plain_len + AES_BLOCK_SIZE); + + return 0; +} + + +/** + * wpa_ft_rrb_build - Build and encrypt an FT RRB message + * @key: AES-SIV key for AEAD + * @key_len: Length of key in octets + * @tlvs_enc0: First set of to-be-encrypted TLVs + * @tlvs_enc1: Second set of to-be-encrypted TLVs + * @tlvs_auth: Set of to-be-authenticated TLVs + * @src_addr: MAC address of the frame sender + * @type: Vendor-specific subtype of the RRB frame (FT_PACKET_*) + * @packet Pointer to return the pointer to the allocated packet buffer; + * needs to be freed by the caller if not null; + * will only be returned on success + * @packet_len: Pointer to return the length of the allocated buffer in octets + * Returns: 0 on success, -1 on error + */ +static int wpa_ft_rrb_build(const u8 *key, const size_t key_len, + const struct tlv_list *tlvs_enc0, + const struct tlv_list *tlvs_enc1, + const struct tlv_list *tlvs_auth, + const struct vlan_description *vlan, + const u8 *src_addr, u8 type, + u8 **packet, size_t *packet_len) +{ + u8 *plain = NULL, *auth = NULL, *pos, *tmp; + size_t plain_len = 0, auth_len = 0; + int ret = -1; + size_t pad_len = 0; + + *packet = NULL; + if (wpa_ft_rrb_lin(tlvs_enc0, tlvs_enc1, vlan, &plain, &plain_len) < 0) + goto out; + + if (wpa_ft_rrb_lin(tlvs_auth, NULL, NULL, &auth, &auth_len) < 0) + goto out; + + *packet_len = sizeof(u16) + auth_len + plain_len; + if (key) + *packet_len += AES_BLOCK_SIZE; +#define RRB_MIN_MSG_LEN 64 + if (*packet_len < RRB_MIN_MSG_LEN) { + pad_len = RRB_MIN_MSG_LEN - *packet_len; + if (pad_len < sizeof(struct ft_rrb_tlv)) + pad_len = sizeof(struct ft_rrb_tlv); + wpa_printf(MSG_DEBUG, + "FT: Pad message to minimum Ethernet frame length (%d --> %d)", + (int) *packet_len, (int) (*packet_len + pad_len)); + *packet_len += pad_len; + tmp = os_realloc(auth, auth_len + pad_len); + if (!tmp) + goto out; + auth = tmp; + pos = auth + auth_len; + WPA_PUT_LE16(pos, FT_RRB_LAST_EMPTY); + pos += 2; + WPA_PUT_LE16(pos, pad_len - sizeof(struct ft_rrb_tlv)); + pos += 2; + os_memset(pos, 0, pad_len - sizeof(struct ft_rrb_tlv)); + auth_len += pad_len; + + } + *packet = os_zalloc(*packet_len); + if (!*packet) + goto out; + + pos = *packet; + WPA_PUT_LE16(pos, auth_len); + pos += 2; + os_memcpy(pos, auth, auth_len); + pos += auth_len; + if (wpa_ft_rrb_encrypt(key, key_len, plain, plain_len, auth, + auth_len, src_addr, type, pos) < 0) + goto out; + wpa_hexdump(MSG_MSGDUMP, "FT: RRB frame payload", *packet, *packet_len); + + ret = 0; + +out: + bin_clear_free(plain, plain_len); + os_free(auth); + + if (ret) { + wpa_printf(MSG_ERROR, "FT: Failed to build RRB-OUI message"); + os_free(*packet); + *packet = NULL; + *packet_len = 0; + } + + return ret; +} + + +#define RRB_GET_SRC(srcfield, type, field, txt, checklength) do { \ + if (wpa_ft_rrb_get_tlv(srcfield, srcfield##_len, type, \ + &f_##field##_len, &f_##field) < 0 || \ + (checklength > 0 && ((size_t) checklength) != f_##field##_len)) { \ + wpa_printf(MSG_INFO, "FT: Missing required " #field \ + " in %s from " MACSTR, txt, MAC2STR(src_addr)); \ + wpa_ft_rrb_dump(srcfield, srcfield##_len); \ + goto out; \ + } \ +} while (0) + +#define RRB_GET(type, field, txt, checklength) \ + RRB_GET_SRC(plain, type, field, txt, checklength) +#define RRB_GET_AUTH(type, field, txt, checklength) \ + RRB_GET_SRC(auth, type, field, txt, checklength) + +#define RRB_GET_OPTIONAL_SRC(srcfield, type, field, txt, checklength) do { \ + if (wpa_ft_rrb_get_tlv(srcfield, srcfield##_len, type, \ + &f_##field##_len, &f_##field) < 0 || \ + (checklength > 0 && ((size_t) checklength) != f_##field##_len)) { \ + wpa_printf(MSG_DEBUG, "FT: Missing optional " #field \ + " in %s from " MACSTR, txt, MAC2STR(src_addr)); \ + f_##field##_len = 0; \ + f_##field = NULL; \ + } \ +} while (0) + +#define RRB_GET_OPTIONAL(type, field, txt, checklength) \ + RRB_GET_OPTIONAL_SRC(plain, type, field, txt, checklength) +#define RRB_GET_OPTIONAL_AUTH(type, field, txt, checklength) \ + RRB_GET_OPTIONAL_SRC(auth, type, field, txt, checklength) static int wpa_ft_rrb_send(struct wpa_authenticator *wpa_auth, const u8 *dst, const u8 *data, size_t data_len) { - if (wpa_auth->cb.send_ether == NULL) + if (wpa_auth->cb->send_ether == NULL) return -1; wpa_printf(MSG_DEBUG, "FT: RRB send to " MACSTR, MAC2STR(dst)); - return wpa_auth->cb.send_ether(wpa_auth->cb.ctx, dst, ETH_P_RRB, - data, data_len); + return wpa_auth->cb->send_ether(wpa_auth->cb_ctx, dst, ETH_P_RRB, + data, data_len); +} + + +static int wpa_ft_rrb_oui_send(struct wpa_authenticator *wpa_auth, + const u8 *dst, u8 oui_suffix, + const u8 *data, size_t data_len) +{ + if (!wpa_auth->cb->send_oui) + return -1; + wpa_printf(MSG_DEBUG, "FT: RRB-OUI type %u send to " MACSTR " (len=%u)", + oui_suffix, MAC2STR(dst), (unsigned int) data_len); + return wpa_auth->cb->send_oui(wpa_auth->cb_ctx, dst, oui_suffix, data, + data_len); } static int wpa_ft_action_send(struct wpa_authenticator *wpa_auth, const u8 *dst, const u8 *data, size_t data_len) { - if (wpa_auth->cb.send_ft_action == NULL) + if (wpa_auth->cb->send_ft_action == NULL) return -1; - return wpa_auth->cb.send_ft_action(wpa_auth->cb.ctx, dst, - data, data_len); + return wpa_auth->cb->send_ft_action(wpa_auth->cb_ctx, dst, + data, data_len); +} + + +static const u8 * wpa_ft_get_psk(struct wpa_authenticator *wpa_auth, + const u8 *addr, const u8 *p2p_dev_addr, + const u8 *prev_psk) +{ + if (wpa_auth->cb->get_psk == NULL) + return NULL; + return wpa_auth->cb->get_psk(wpa_auth->cb_ctx, addr, p2p_dev_addr, + prev_psk, NULL, NULL); } static struct wpa_state_machine * wpa_ft_add_sta(struct wpa_authenticator *wpa_auth, const u8 *sta_addr) { - if (wpa_auth->cb.add_sta == NULL) + if (wpa_auth->cb->add_sta == NULL) return NULL; - return wpa_auth->cb.add_sta(wpa_auth->cb.ctx, sta_addr); + return wpa_auth->cb->add_sta(wpa_auth->cb_ctx, sta_addr); +} + + +static int wpa_ft_set_vlan(struct wpa_authenticator *wpa_auth, + const u8 *sta_addr, struct vlan_description *vlan) +{ + if (!wpa_auth->cb->set_vlan) + return -1; + return wpa_auth->cb->set_vlan(wpa_auth->cb_ctx, sta_addr, vlan); +} + + +static int wpa_ft_get_vlan(struct wpa_authenticator *wpa_auth, + const u8 *sta_addr, struct vlan_description *vlan) +{ + if (!wpa_auth->cb->get_vlan) + return -1; + return wpa_auth->cb->get_vlan(wpa_auth->cb_ctx, sta_addr, vlan); +} + + +static int +wpa_ft_set_identity(struct wpa_authenticator *wpa_auth, const u8 *sta_addr, + const u8 *identity, size_t identity_len) +{ + if (!wpa_auth->cb->set_identity) + return -1; + return wpa_auth->cb->set_identity(wpa_auth->cb_ctx, sta_addr, identity, + identity_len); +} + + +static size_t +wpa_ft_get_identity(struct wpa_authenticator *wpa_auth, const u8 *sta_addr, + const u8 **buf) +{ + *buf = NULL; + if (!wpa_auth->cb->get_identity) + return 0; + return wpa_auth->cb->get_identity(wpa_auth->cb_ctx, sta_addr, buf); +} + + +static int +wpa_ft_set_radius_cui(struct wpa_authenticator *wpa_auth, const u8 *sta_addr, + const u8 *radius_cui, size_t radius_cui_len) +{ + if (!wpa_auth->cb->set_radius_cui) + return -1; + return wpa_auth->cb->set_radius_cui(wpa_auth->cb_ctx, sta_addr, + radius_cui, radius_cui_len); +} + + +static size_t +wpa_ft_get_radius_cui(struct wpa_authenticator *wpa_auth, const u8 *sta_addr, + const u8 **buf) +{ + *buf = NULL; + if (!wpa_auth->cb->get_radius_cui) + return 0; + return wpa_auth->cb->get_radius_cui(wpa_auth->cb_ctx, sta_addr, buf); +} + + +static void +wpa_ft_set_session_timeout(struct wpa_authenticator *wpa_auth, + const u8 *sta_addr, int session_timeout) +{ + if (!wpa_auth->cb->set_session_timeout) + return; + wpa_auth->cb->set_session_timeout(wpa_auth->cb_ctx, sta_addr, + session_timeout); +} + + +static int +wpa_ft_get_session_timeout(struct wpa_authenticator *wpa_auth, + const u8 *sta_addr) +{ + if (!wpa_auth->cb->get_session_timeout) + return 0; + return wpa_auth->cb->get_session_timeout(wpa_auth->cb_ctx, sta_addr); } @@ -66,15 +765,26 @@ static int wpa_ft_add_tspec(struct wpa_authenticator *wpa_auth, const u8 *sta_addr, u8 *tspec_ie, size_t tspec_ielen) { - if (wpa_auth->cb.add_tspec == NULL) { + if (wpa_auth->cb->add_tspec == NULL) { wpa_printf(MSG_DEBUG, "FT: add_tspec is not initialized"); return -1; } - return wpa_auth->cb.add_tspec(wpa_auth->cb.ctx, sta_addr, tspec_ie, - tspec_ielen); + return wpa_auth->cb->add_tspec(wpa_auth->cb_ctx, sta_addr, tspec_ie, + tspec_ielen); } +#ifdef CONFIG_OCV +static int wpa_channel_info(struct wpa_authenticator *wpa_auth, + struct wpa_channel_info *ci) +{ + if (!wpa_auth->cb->channel_info) + return -1; + return wpa_auth->cb->channel_info(wpa_auth->cb_ctx, ci); +} +#endif /* CONFIG_OCV */ + + int wpa_write_mdie(struct wpa_auth_config *conf, u8 *buf, size_t len) { u8 *pos = buf; @@ -95,30 +805,44 @@ int wpa_write_mdie(struct wpa_auth_config *conf, u8 *buf, size_t len) } -int wpa_write_ftie(struct wpa_auth_config *conf, const u8 *r0kh_id, - size_t r0kh_id_len, +int wpa_write_ftie(struct wpa_auth_config *conf, int use_sha384, + const u8 *r0kh_id, size_t r0kh_id_len, const u8 *anonce, const u8 *snonce, u8 *buf, size_t len, const u8 *subelem, size_t subelem_len) { u8 *pos = buf, *ielen; - struct rsn_ftie *hdr; + size_t hdrlen = use_sha384 ? sizeof(struct rsn_ftie_sha384) : + sizeof(struct rsn_ftie); - if (len < 2 + sizeof(*hdr) + 2 + FT_R1KH_ID_LEN + 2 + r0kh_id_len + + if (len < 2 + hdrlen + 2 + FT_R1KH_ID_LEN + 2 + r0kh_id_len + subelem_len) return -1; *pos++ = WLAN_EID_FAST_BSS_TRANSITION; ielen = pos++; - hdr = (struct rsn_ftie *) pos; - os_memset(hdr, 0, sizeof(*hdr)); - pos += sizeof(*hdr); - WPA_PUT_LE16(hdr->mic_control, 0); - if (anonce) - os_memcpy(hdr->anonce, anonce, WPA_NONCE_LEN); - if (snonce) - os_memcpy(hdr->snonce, snonce, WPA_NONCE_LEN); + if (use_sha384) { + struct rsn_ftie_sha384 *hdr = (struct rsn_ftie_sha384 *) pos; + + os_memset(hdr, 0, sizeof(*hdr)); + pos += sizeof(*hdr); + WPA_PUT_LE16(hdr->mic_control, 0); + if (anonce) + os_memcpy(hdr->anonce, anonce, WPA_NONCE_LEN); + if (snonce) + os_memcpy(hdr->snonce, snonce, WPA_NONCE_LEN); + } else { + struct rsn_ftie *hdr = (struct rsn_ftie *) pos; + + os_memset(hdr, 0, sizeof(*hdr)); + pos += sizeof(*hdr); + WPA_PUT_LE16(hdr->mic_control, 0); + if (anonce) + os_memcpy(hdr->anonce, anonce, WPA_NONCE_LEN); + if (snonce) + os_memcpy(hdr->snonce, snonce, WPA_NONCE_LEN); + } /* Optional Parameters */ *pos++ = FTIE_SUBELEM_R1KH_ID; @@ -144,35 +868,434 @@ int wpa_write_ftie(struct wpa_auth_config *conf, const u8 *r0kh_id, } +/* A packet to be handled after seq response */ +struct ft_remote_item { + struct dl_list list; + + u8 nonce[FT_RRB_NONCE_LEN]; + struct os_reltime nonce_ts; + + u8 src_addr[ETH_ALEN]; + u8 *enc; + size_t enc_len; + u8 *auth; + size_t auth_len; + int (*cb)(struct wpa_authenticator *wpa_auth, + const u8 *src_addr, + const u8 *enc, size_t enc_len, + const u8 *auth, size_t auth_len, + int no_defer); +}; + + +static void wpa_ft_rrb_seq_free(struct ft_remote_item *item) +{ + eloop_cancel_timeout(wpa_ft_rrb_seq_timeout, ELOOP_ALL_CTX, item); + dl_list_del(&item->list); + bin_clear_free(item->enc, item->enc_len); + os_free(item->auth); + os_free(item); +} + + +static void wpa_ft_rrb_seq_flush(struct wpa_authenticator *wpa_auth, + struct ft_remote_seq *rkh_seq, int cb) +{ + struct ft_remote_item *item, *n; + + dl_list_for_each_safe(item, n, &rkh_seq->rx.queue, + struct ft_remote_item, list) { + if (cb && item->cb) + item->cb(wpa_auth, item->src_addr, item->enc, + item->enc_len, item->auth, item->auth_len, 1); + wpa_ft_rrb_seq_free(item); + } +} + + +static void wpa_ft_rrb_seq_timeout(void *eloop_ctx, void *timeout_ctx) +{ + struct ft_remote_item *item = timeout_ctx; + + wpa_ft_rrb_seq_free(item); +} + + +static int +wpa_ft_rrb_seq_req(struct wpa_authenticator *wpa_auth, + struct ft_remote_seq *rkh_seq, const u8 *src_addr, + const u8 *f_r0kh_id, size_t f_r0kh_id_len, + const u8 *f_r1kh_id, const u8 *key, size_t key_len, + const u8 *enc, size_t enc_len, + const u8 *auth, size_t auth_len, + int (*cb)(struct wpa_authenticator *wpa_auth, + const u8 *src_addr, + const u8 *enc, size_t enc_len, + const u8 *auth, size_t auth_len, + int no_defer)) +{ + struct ft_remote_item *item = NULL; + u8 *packet = NULL; + size_t packet_len; + struct tlv_list seq_req_auth[] = { + { .type = FT_RRB_NONCE, .len = FT_RRB_NONCE_LEN, + .data = NULL /* to be filled: item->nonce */ }, + { .type = FT_RRB_R0KH_ID, .len = f_r0kh_id_len, + .data = f_r0kh_id }, + { .type = FT_RRB_R1KH_ID, .len = FT_R1KH_ID_LEN, + .data = f_r1kh_id }, + { .type = FT_RRB_LAST_EMPTY, .len = 0, .data = NULL }, + }; + + if (dl_list_len(&rkh_seq->rx.queue) >= ftRRBmaxQueueLen) { + wpa_printf(MSG_DEBUG, "FT: Sequence number queue too long"); + goto err; + } + + wpa_printf(MSG_DEBUG, "FT: Send out sequence number request to " MACSTR, + MAC2STR(src_addr)); + item = os_zalloc(sizeof(*item)); + if (!item) + goto err; + + os_memcpy(item->src_addr, src_addr, ETH_ALEN); + item->cb = cb; + + if (random_get_bytes(item->nonce, FT_RRB_NONCE_LEN) < 0) { + wpa_printf(MSG_DEBUG, "FT: Seq num nonce: out of random bytes"); + goto err; + } + + if (os_get_reltime(&item->nonce_ts) < 0) + goto err; + + if (enc && enc_len > 0) { + item->enc = os_memdup(enc, enc_len); + item->enc_len = enc_len; + if (!item->enc) + goto err; + } + + if (auth && auth_len > 0) { + item->auth = os_memdup(auth, auth_len); + item->auth_len = auth_len; + if (!item->auth) + goto err; + } + + eloop_register_timeout(ftRRBseqTimeout, 0, wpa_ft_rrb_seq_timeout, + wpa_auth, item); + + seq_req_auth[0].data = item->nonce; + + if (wpa_ft_rrb_build(key, key_len, NULL, NULL, seq_req_auth, NULL, + wpa_auth->addr, FT_PACKET_R0KH_R1KH_SEQ_REQ, + &packet, &packet_len) < 0) { + item = NULL; /* some other seq resp might still accept this */ + goto err; + } + + dl_list_add(&rkh_seq->rx.queue, &item->list); + + wpa_ft_rrb_oui_send(wpa_auth, src_addr, FT_PACKET_R0KH_R1KH_SEQ_REQ, + packet, packet_len); + + os_free(packet); + + return 0; +err: + wpa_printf(MSG_DEBUG, "FT: Failed to send sequence number request"); + if (item) { + os_free(item->auth); + bin_clear_free(item->enc, item->enc_len); + os_free(item); + } + + return -1; +} + + +#define FT_RRB_SEQ_OK 0 +#define FT_RRB_SEQ_DROP 1 +#define FT_RRB_SEQ_DEFER 2 + +static int +wpa_ft_rrb_seq_chk(struct ft_remote_seq *rkh_seq, const u8 *src_addr, + const u8 *enc, size_t enc_len, + const u8 *auth, size_t auth_len, + const char *msgtype, int no_defer) +{ + const u8 *f_seq; + size_t f_seq_len; + const struct ft_rrb_seq *msg_both; + u32 msg_seq, msg_off, rkh_off; + struct os_reltime now; + unsigned int i; + + RRB_GET_AUTH(FT_RRB_SEQ, seq, msgtype, sizeof(*msg_both)); + wpa_hexdump(MSG_DEBUG, "FT: sequence number", f_seq, f_seq_len); + msg_both = (const struct ft_rrb_seq *) f_seq; + + if (rkh_seq->rx.num_last == 0) { + /* first packet from remote */ + goto defer; + } + + if (le_to_host32(msg_both->dom) != rkh_seq->rx.dom) { + /* remote might have rebooted */ + goto defer; + } + + if (os_get_reltime(&now) == 0) { + u32 msg_ts_now_remote, msg_ts_off; + struct os_reltime now_remote; + + os_reltime_sub(&now, &rkh_seq->rx.time_offset, &now_remote); + msg_ts_now_remote = now_remote.sec; + msg_ts_off = le_to_host32(msg_both->ts) - + (msg_ts_now_remote - ftRRBseqTimeout); + if (msg_ts_off > 2 * ftRRBseqTimeout) + goto defer; + } + + msg_seq = le_to_host32(msg_both->seq); + rkh_off = rkh_seq->rx.last[rkh_seq->rx.offsetidx]; + msg_off = msg_seq - rkh_off; + if (msg_off > 0xC0000000) + goto out; /* too old message, drop it */ + + if (msg_off <= 0x40000000) { + for (i = 0; i < rkh_seq->rx.num_last; i++) { + if (rkh_seq->rx.last[i] == msg_seq) + goto out; /* duplicate message, drop it */ + } + + return FT_RRB_SEQ_OK; + } + +defer: + if (no_defer) + goto out; + + wpa_printf(MSG_DEBUG, "FT: Possibly invalid sequence number in %s from " + MACSTR, msgtype, MAC2STR(src_addr)); + + return FT_RRB_SEQ_DEFER; +out: + wpa_printf(MSG_DEBUG, "FT: Invalid sequence number in %s from " MACSTR, + msgtype, MAC2STR(src_addr)); + + return FT_RRB_SEQ_DROP; +} + + +static void +wpa_ft_rrb_seq_accept(struct wpa_authenticator *wpa_auth, + struct ft_remote_seq *rkh_seq, const u8 *src_addr, + const u8 *auth, size_t auth_len, + const char *msgtype) +{ + const u8 *f_seq; + size_t f_seq_len; + const struct ft_rrb_seq *msg_both; + u32 msg_seq, msg_off, min_off, rkh_off; + int minidx = 0; + unsigned int i; + + RRB_GET_AUTH(FT_RRB_SEQ, seq, msgtype, sizeof(*msg_both)); + msg_both = (const struct ft_rrb_seq *) f_seq; + + msg_seq = le_to_host32(msg_both->seq); + + if (rkh_seq->rx.num_last < FT_REMOTE_SEQ_BACKLOG) { + rkh_seq->rx.last[rkh_seq->rx.num_last] = msg_seq; + rkh_seq->rx.num_last++; + return; + } + + rkh_off = rkh_seq->rx.last[rkh_seq->rx.offsetidx]; + for (i = 0; i < rkh_seq->rx.num_last; i++) { + msg_off = rkh_seq->rx.last[i] - rkh_off; + min_off = rkh_seq->rx.last[minidx] - rkh_off; + if (msg_off < min_off && i != rkh_seq->rx.offsetidx) + minidx = i; + } + rkh_seq->rx.last[rkh_seq->rx.offsetidx] = msg_seq; + rkh_seq->rx.offsetidx = minidx; + + return; +out: + /* RRB_GET_AUTH should never fail here as + * wpa_ft_rrb_seq_chk() verified FT_RRB_SEQ presence. */ + wpa_printf(MSG_ERROR, "FT: %s() failed", __func__); +} + + +static int wpa_ft_new_seq(struct ft_remote_seq *rkh_seq, + struct ft_rrb_seq *f_seq) +{ + struct os_reltime now; + + if (os_get_reltime(&now) < 0) + return -1; + + if (!rkh_seq->tx.dom) { + if (random_get_bytes((u8 *) &rkh_seq->tx.seq, + sizeof(rkh_seq->tx.seq))) { + wpa_printf(MSG_ERROR, + "FT: Failed to get random data for sequence number initialization"); + rkh_seq->tx.seq = now.usec; + } + if (random_get_bytes((u8 *) &rkh_seq->tx.dom, + sizeof(rkh_seq->tx.dom))) { + wpa_printf(MSG_ERROR, + "FT: Failed to get random data for sequence number initialization"); + rkh_seq->tx.dom = now.usec; + } + rkh_seq->tx.dom |= 1; + } + + f_seq->dom = host_to_le32(rkh_seq->tx.dom); + f_seq->seq = host_to_le32(rkh_seq->tx.seq); + f_seq->ts = host_to_le32(now.sec); + + rkh_seq->tx.seq++; + + return 0; +} + + struct wpa_ft_pmk_r0_sa { - struct wpa_ft_pmk_r0_sa *next; - u8 pmk_r0[PMK_LEN]; + struct dl_list list; + u8 pmk_r0[PMK_LEN_MAX]; + size_t pmk_r0_len; u8 pmk_r0_name[WPA_PMK_NAME_LEN]; u8 spa[ETH_ALEN]; int pairwise; /* Pairwise cipher suite, WPA_CIPHER_* */ - /* TODO: expiration, identity, radius_class, EAP type, VLAN ID */ + struct vlan_description *vlan; + os_time_t expiration; /* 0 for no expiration */ + u8 *identity; + size_t identity_len; + u8 *radius_cui; + size_t radius_cui_len; + os_time_t session_timeout; /* 0 for no expiration */ + /* TODO: radius_class, EAP type */ int pmk_r1_pushed; }; struct wpa_ft_pmk_r1_sa { - struct wpa_ft_pmk_r1_sa *next; - u8 pmk_r1[PMK_LEN]; + struct dl_list list; + u8 pmk_r1[PMK_LEN_MAX]; + size_t pmk_r1_len; u8 pmk_r1_name[WPA_PMK_NAME_LEN]; u8 spa[ETH_ALEN]; int pairwise; /* Pairwise cipher suite, WPA_CIPHER_* */ - /* TODO: expiration, identity, radius_class, EAP type, VLAN ID */ + struct vlan_description *vlan; + u8 *identity; + size_t identity_len; + u8 *radius_cui; + size_t radius_cui_len; + os_time_t session_timeout; /* 0 for no expiration */ + /* TODO: radius_class, EAP type */ }; struct wpa_ft_pmk_cache { - struct wpa_ft_pmk_r0_sa *pmk_r0; - struct wpa_ft_pmk_r1_sa *pmk_r1; + struct dl_list pmk_r0; /* struct wpa_ft_pmk_r0_sa */ + struct dl_list pmk_r1; /* struct wpa_ft_pmk_r1_sa */ }; + +static void wpa_ft_expire_pmk_r0(void *eloop_ctx, void *timeout_ctx); +static void wpa_ft_expire_pmk_r1(void *eloop_ctx, void *timeout_ctx); + + +static void wpa_ft_free_pmk_r0(struct wpa_ft_pmk_r0_sa *r0) +{ + if (!r0) + return; + + dl_list_del(&r0->list); + eloop_cancel_timeout(wpa_ft_expire_pmk_r0, r0, NULL); + + os_memset(r0->pmk_r0, 0, PMK_LEN_MAX); + os_free(r0->vlan); + os_free(r0->identity); + os_free(r0->radius_cui); + os_free(r0); +} + + +static void wpa_ft_expire_pmk_r0(void *eloop_ctx, void *timeout_ctx) +{ + struct wpa_ft_pmk_r0_sa *r0 = eloop_ctx; + struct os_reltime now; + int expires_in; + int session_timeout; + + os_get_reltime(&now); + + if (!r0) + return; + + expires_in = r0->expiration - now.sec; + session_timeout = r0->session_timeout - now.sec; + /* conditions to remove from cache: + * a) r0->expiration is set and hit + * -or- + * b) r0->session_timeout is set and hit + */ + if ((!r0->expiration || expires_in > 0) && + (!r0->session_timeout || session_timeout > 0)) { + wpa_printf(MSG_ERROR, + "FT: %s() called for non-expired entry %p", + __func__, r0); + eloop_cancel_timeout(wpa_ft_expire_pmk_r0, r0, NULL); + if (r0->expiration && expires_in > 0) + eloop_register_timeout(expires_in + 1, 0, + wpa_ft_expire_pmk_r0, r0, NULL); + if (r0->session_timeout && session_timeout > 0) + eloop_register_timeout(session_timeout + 1, 0, + wpa_ft_expire_pmk_r0, r0, NULL); + return; + } + + wpa_ft_free_pmk_r0(r0); +} + + +static void wpa_ft_free_pmk_r1(struct wpa_ft_pmk_r1_sa *r1) +{ + if (!r1) + return; + + dl_list_del(&r1->list); + eloop_cancel_timeout(wpa_ft_expire_pmk_r1, r1, NULL); + + os_memset(r1->pmk_r1, 0, PMK_LEN_MAX); + os_free(r1->vlan); + os_free(r1->identity); + os_free(r1->radius_cui); + os_free(r1); +} + + +static void wpa_ft_expire_pmk_r1(void *eloop_ctx, void *timeout_ctx) +{ + struct wpa_ft_pmk_r1_sa *r1 = eloop_ctx; + + wpa_ft_free_pmk_r1(r1); +} + + struct wpa_ft_pmk_cache * wpa_ft_pmk_cache_init(void) { struct wpa_ft_pmk_cache *cache; cache = os_zalloc(sizeof(*cache)); + if (cache) { + dl_list_init(&cache->pmk_r0); + dl_list_init(&cache->pmk_r1); + } return cache; } @@ -183,21 +1306,13 @@ void wpa_ft_pmk_cache_deinit(struct wpa_ft_pmk_cache *cache) struct wpa_ft_pmk_r0_sa *r0, *r0prev; struct wpa_ft_pmk_r1_sa *r1, *r1prev; - r0 = cache->pmk_r0; - while (r0) { - r0prev = r0; - r0 = r0->next; - os_memset(r0prev->pmk_r0, 0, PMK_LEN); - os_free(r0prev); - } + dl_list_for_each_safe(r0, r0prev, &cache->pmk_r0, + struct wpa_ft_pmk_r0_sa, list) + wpa_ft_free_pmk_r0(r0); - r1 = cache->pmk_r1; - while (r1) { - r1prev = r1; - r1 = r1->next; - os_memset(r1prev->pmk_r1, 0, PMK_LEN); - os_free(r1prev); - } + dl_list_for_each_safe(r1, r1prev, &cache->pmk_r1, + struct wpa_ft_pmk_r1_sa, list) + wpa_ft_free_pmk_r1(r1); os_free(cache); } @@ -205,24 +1320,63 @@ void wpa_ft_pmk_cache_deinit(struct wpa_ft_pmk_cache *cache) static int wpa_ft_store_pmk_r0(struct wpa_authenticator *wpa_auth, const u8 *spa, const u8 *pmk_r0, - const u8 *pmk_r0_name, int pairwise) + size_t pmk_r0_len, + const u8 *pmk_r0_name, int pairwise, + const struct vlan_description *vlan, + int expires_in, int session_timeout, + const u8 *identity, size_t identity_len, + const u8 *radius_cui, size_t radius_cui_len) { struct wpa_ft_pmk_cache *cache = wpa_auth->ft_pmk_cache; struct wpa_ft_pmk_r0_sa *r0; + struct os_reltime now; - /* TODO: add expiration and limit on number of entries in cache */ + /* TODO: add limit on number of entries in cache */ + os_get_reltime(&now); r0 = os_zalloc(sizeof(*r0)); if (r0 == NULL) return -1; - os_memcpy(r0->pmk_r0, pmk_r0, PMK_LEN); + os_memcpy(r0->pmk_r0, pmk_r0, pmk_r0_len); + r0->pmk_r0_len = pmk_r0_len; os_memcpy(r0->pmk_r0_name, pmk_r0_name, WPA_PMK_NAME_LEN); os_memcpy(r0->spa, spa, ETH_ALEN); r0->pairwise = pairwise; + if (expires_in > 0) + r0->expiration = now.sec + expires_in; + if (vlan && vlan->notempty) { + r0->vlan = os_zalloc(sizeof(*vlan)); + if (!r0->vlan) { + bin_clear_free(r0, sizeof(*r0)); + return -1; + } + *r0->vlan = *vlan; + } + if (identity) { + r0->identity = os_malloc(identity_len); + if (r0->identity) { + os_memcpy(r0->identity, identity, identity_len); + r0->identity_len = identity_len; + } + } + if (radius_cui) { + r0->radius_cui = os_malloc(radius_cui_len); + if (r0->radius_cui) { + os_memcpy(r0->radius_cui, radius_cui, radius_cui_len); + r0->radius_cui_len = radius_cui_len; + } + } + if (session_timeout > 0) + r0->session_timeout = now.sec + session_timeout; - r0->next = cache->pmk_r0; - cache->pmk_r0 = r0; + dl_list_add(&cache->pmk_r0, &r0->list); + if (expires_in > 0) + eloop_register_timeout(expires_in + 1, 0, wpa_ft_expire_pmk_r0, + r0, NULL); + if (session_timeout > 0) + eloop_register_timeout(session_timeout + 1, 0, + wpa_ft_expire_pmk_r0, r0, NULL); return 0; } @@ -230,49 +1384,89 @@ static int wpa_ft_store_pmk_r0(struct wpa_authenticator *wpa_auth, static int wpa_ft_fetch_pmk_r0(struct wpa_authenticator *wpa_auth, const u8 *spa, const u8 *pmk_r0_name, - u8 *pmk_r0, int *pairwise) + const struct wpa_ft_pmk_r0_sa **r0_out) { struct wpa_ft_pmk_cache *cache = wpa_auth->ft_pmk_cache; struct wpa_ft_pmk_r0_sa *r0; + struct os_reltime now; - r0 = cache->pmk_r0; - while (r0) { + os_get_reltime(&now); + dl_list_for_each(r0, &cache->pmk_r0, struct wpa_ft_pmk_r0_sa, list) { if (os_memcmp(r0->spa, spa, ETH_ALEN) == 0 && os_memcmp_const(r0->pmk_r0_name, pmk_r0_name, WPA_PMK_NAME_LEN) == 0) { - os_memcpy(pmk_r0, r0->pmk_r0, PMK_LEN); - if (pairwise) - *pairwise = r0->pairwise; + *r0_out = r0; return 0; } - - r0 = r0->next; } + *r0_out = NULL; return -1; } static int wpa_ft_store_pmk_r1(struct wpa_authenticator *wpa_auth, const u8 *spa, const u8 *pmk_r1, - const u8 *pmk_r1_name, int pairwise) + size_t pmk_r1_len, + const u8 *pmk_r1_name, int pairwise, + const struct vlan_description *vlan, + int expires_in, int session_timeout, + const u8 *identity, size_t identity_len, + const u8 *radius_cui, size_t radius_cui_len) { struct wpa_ft_pmk_cache *cache = wpa_auth->ft_pmk_cache; + int max_expires_in = wpa_auth->conf.r1_max_key_lifetime; struct wpa_ft_pmk_r1_sa *r1; + struct os_reltime now; - /* TODO: add expiration and limit on number of entries in cache */ + /* TODO: limit on number of entries in cache */ + os_get_reltime(&now); + + if (max_expires_in && (max_expires_in < expires_in || expires_in == 0)) + expires_in = max_expires_in; r1 = os_zalloc(sizeof(*r1)); if (r1 == NULL) return -1; - os_memcpy(r1->pmk_r1, pmk_r1, PMK_LEN); + os_memcpy(r1->pmk_r1, pmk_r1, pmk_r1_len); + r1->pmk_r1_len = pmk_r1_len; os_memcpy(r1->pmk_r1_name, pmk_r1_name, WPA_PMK_NAME_LEN); os_memcpy(r1->spa, spa, ETH_ALEN); r1->pairwise = pairwise; + if (vlan && vlan->notempty) { + r1->vlan = os_zalloc(sizeof(*vlan)); + if (!r1->vlan) { + bin_clear_free(r1, sizeof(*r1)); + return -1; + } + *r1->vlan = *vlan; + } + if (identity) { + r1->identity = os_malloc(identity_len); + if (r1->identity) { + os_memcpy(r1->identity, identity, identity_len); + r1->identity_len = identity_len; + } + } + if (radius_cui) { + r1->radius_cui = os_malloc(radius_cui_len); + if (r1->radius_cui) { + os_memcpy(r1->radius_cui, radius_cui, radius_cui_len); + r1->radius_cui_len = radius_cui_len; + } + } + if (session_timeout > 0) + r1->session_timeout = now.sec + session_timeout; + + dl_list_add(&cache->pmk_r1, &r1->list); - r1->next = cache->pmk_r1; - cache->pmk_r1 = r1; + if (expires_in > 0) + eloop_register_timeout(expires_in + 1, 0, wpa_ft_expire_pmk_r1, + r1, NULL); + if (session_timeout > 0) + eloop_register_timeout(session_timeout + 1, 0, + wpa_ft_expire_pmk_r1, r1, NULL); return 0; } @@ -280,94 +1474,615 @@ static int wpa_ft_store_pmk_r1(struct wpa_authenticator *wpa_auth, static int wpa_ft_fetch_pmk_r1(struct wpa_authenticator *wpa_auth, const u8 *spa, const u8 *pmk_r1_name, - u8 *pmk_r1, int *pairwise) + u8 *pmk_r1, size_t *pmk_r1_len, int *pairwise, + struct vlan_description *vlan, + const u8 **identity, size_t *identity_len, + const u8 **radius_cui, size_t *radius_cui_len, + int *session_timeout) { struct wpa_ft_pmk_cache *cache = wpa_auth->ft_pmk_cache; struct wpa_ft_pmk_r1_sa *r1; + struct os_reltime now; - r1 = cache->pmk_r1; - while (r1) { + os_get_reltime(&now); + + dl_list_for_each(r1, &cache->pmk_r1, struct wpa_ft_pmk_r1_sa, list) { if (os_memcmp(r1->spa, spa, ETH_ALEN) == 0 && os_memcmp_const(r1->pmk_r1_name, pmk_r1_name, WPA_PMK_NAME_LEN) == 0) { - os_memcpy(pmk_r1, r1->pmk_r1, PMK_LEN); + os_memcpy(pmk_r1, r1->pmk_r1, r1->pmk_r1_len); + *pmk_r1_len = r1->pmk_r1_len; if (pairwise) *pairwise = r1->pairwise; + if (vlan && r1->vlan) + *vlan = *r1->vlan; + if (vlan && !r1->vlan) + os_memset(vlan, 0, sizeof(*vlan)); + if (identity && identity_len) { + *identity = r1->identity; + *identity_len = r1->identity_len; + } + if (radius_cui && radius_cui_len) { + *radius_cui = r1->radius_cui; + *radius_cui_len = r1->radius_cui_len; + } + if (session_timeout && r1->session_timeout > now.sec) + *session_timeout = r1->session_timeout - + now.sec; + else if (session_timeout && r1->session_timeout) + *session_timeout = 1; + else if (session_timeout) + *session_timeout = 0; return 0; } - - r1 = r1->next; } return -1; } -static int wpa_ft_pull_pmk_r1(struct wpa_state_machine *sm, - const u8 *ies, size_t ies_len, - const u8 *pmk_r0_name) +static int wpa_ft_rrb_init_r0kh_seq(struct ft_remote_r0kh *r0kh) +{ + if (r0kh->seq) + return 0; + + r0kh->seq = os_zalloc(sizeof(*r0kh->seq)); + if (!r0kh->seq) { + wpa_printf(MSG_DEBUG, "FT: Failed to allocate r0kh->seq"); + return -1; + } + + dl_list_init(&r0kh->seq->rx.queue); + + return 0; +} + + +static void wpa_ft_rrb_lookup_r0kh(struct wpa_authenticator *wpa_auth, + const u8 *f_r0kh_id, size_t f_r0kh_id_len, + struct ft_remote_r0kh **r0kh_out, + struct ft_remote_r0kh **r0kh_wildcard) { struct ft_remote_r0kh *r0kh; - struct ft_r0kh_r1kh_pull_frame frame, f; - r0kh = sm->wpa_auth->conf.r0kh_list; - while (r0kh) { - if (r0kh->id_len == sm->r0kh_id_len && - os_memcmp_const(r0kh->id, sm->r0kh_id, sm->r0kh_id_len) == - 0) + *r0kh_wildcard = NULL; + *r0kh_out = NULL; + + if (wpa_auth->conf.r0kh_list) + r0kh = *wpa_auth->conf.r0kh_list; + else + r0kh = NULL; + for (; r0kh; r0kh = r0kh->next) { + if (r0kh->id_len == 1 && r0kh->id[0] == '*') + *r0kh_wildcard = r0kh; + if (f_r0kh_id && r0kh->id_len == f_r0kh_id_len && + os_memcmp_const(f_r0kh_id, r0kh->id, f_r0kh_id_len) == 0) + *r0kh_out = r0kh; + } + + if (!*r0kh_out && !*r0kh_wildcard) + wpa_printf(MSG_DEBUG, "FT: No matching R0KH found"); + + if (*r0kh_out && wpa_ft_rrb_init_r0kh_seq(*r0kh_out) < 0) + *r0kh_out = NULL; +} + + +static int wpa_ft_rrb_init_r1kh_seq(struct ft_remote_r1kh *r1kh) +{ + if (r1kh->seq) + return 0; + + r1kh->seq = os_zalloc(sizeof(*r1kh->seq)); + if (!r1kh->seq) { + wpa_printf(MSG_DEBUG, "FT: Failed to allocate r1kh->seq"); + return -1; + } + + dl_list_init(&r1kh->seq->rx.queue); + + return 0; +} + + +static void wpa_ft_rrb_lookup_r1kh(struct wpa_authenticator *wpa_auth, + const u8 *f_r1kh_id, + struct ft_remote_r1kh **r1kh_out, + struct ft_remote_r1kh **r1kh_wildcard) +{ + struct ft_remote_r1kh *r1kh; + + *r1kh_wildcard = NULL; + *r1kh_out = NULL; + + if (wpa_auth->conf.r1kh_list) + r1kh = *wpa_auth->conf.r1kh_list; + else + r1kh = NULL; + for (; r1kh; r1kh = r1kh->next) { + if (is_zero_ether_addr(r1kh->addr) && + is_zero_ether_addr(r1kh->id)) + *r1kh_wildcard = r1kh; + if (f_r1kh_id && + os_memcmp_const(r1kh->id, f_r1kh_id, FT_R1KH_ID_LEN) == 0) + *r1kh_out = r1kh; + } + + if (!*r1kh_out && !*r1kh_wildcard) + wpa_printf(MSG_DEBUG, "FT: No matching R1KH found"); + + if (*r1kh_out && wpa_ft_rrb_init_r1kh_seq(*r1kh_out) < 0) + *r1kh_out = NULL; +} + + +static int wpa_ft_rrb_check_r0kh(struct wpa_authenticator *wpa_auth, + const u8 *f_r0kh_id, size_t f_r0kh_id_len) +{ + if (f_r0kh_id_len != wpa_auth->conf.r0_key_holder_len || + os_memcmp_const(f_r0kh_id, wpa_auth->conf.r0_key_holder, + f_r0kh_id_len) != 0) + return -1; + + return 0; +} + + +static int wpa_ft_rrb_check_r1kh(struct wpa_authenticator *wpa_auth, + const u8 *f_r1kh_id) +{ + if (os_memcmp_const(f_r1kh_id, wpa_auth->conf.r1_key_holder, + FT_R1KH_ID_LEN) != 0) + return -1; + + return 0; +} + + +static void wpa_ft_rrb_del_r0kh(void *eloop_ctx, void *timeout_ctx) +{ + struct wpa_authenticator *wpa_auth = eloop_ctx; + struct ft_remote_r0kh *r0kh, *prev = NULL; + + if (!wpa_auth->conf.r0kh_list) + return; + + for (r0kh = *wpa_auth->conf.r0kh_list; r0kh; r0kh = r0kh->next) { + if (r0kh == timeout_ctx) break; - r0kh = r0kh->next; + prev = r0kh; + } + if (!r0kh) + return; + if (prev) + prev->next = r0kh->next; + else + *wpa_auth->conf.r0kh_list = r0kh->next; + if (r0kh->seq) + wpa_ft_rrb_seq_flush(wpa_auth, r0kh->seq, 0); + os_free(r0kh->seq); + os_free(r0kh); +} + + +static void wpa_ft_rrb_r0kh_replenish(struct wpa_authenticator *wpa_auth, + struct ft_remote_r0kh *r0kh, int timeout) +{ + if (timeout > 0) + eloop_replenish_timeout(timeout, 0, wpa_ft_rrb_del_r0kh, + wpa_auth, r0kh); +} + + +static void wpa_ft_rrb_r0kh_timeout(struct wpa_authenticator *wpa_auth, + struct ft_remote_r0kh *r0kh, int timeout) +{ + eloop_cancel_timeout(wpa_ft_rrb_del_r0kh, wpa_auth, r0kh); + + if (timeout > 0) + eloop_register_timeout(timeout, 0, wpa_ft_rrb_del_r0kh, + wpa_auth, r0kh); +} + + +static struct ft_remote_r0kh * +wpa_ft_rrb_add_r0kh(struct wpa_authenticator *wpa_auth, + struct ft_remote_r0kh *r0kh_wildcard, + const u8 *src_addr, const u8 *r0kh_id, size_t id_len, + int timeout) +{ + struct ft_remote_r0kh *r0kh; + + if (!wpa_auth->conf.r0kh_list) + return NULL; + + r0kh = os_zalloc(sizeof(*r0kh)); + if (!r0kh) + return NULL; + + if (src_addr) + os_memcpy(r0kh->addr, src_addr, sizeof(r0kh->addr)); + + if (id_len > FT_R0KH_ID_MAX_LEN) + id_len = FT_R0KH_ID_MAX_LEN; + os_memcpy(r0kh->id, r0kh_id, id_len); + r0kh->id_len = id_len; + + os_memcpy(r0kh->key, r0kh_wildcard->key, sizeof(r0kh->key)); + + r0kh->next = *wpa_auth->conf.r0kh_list; + *wpa_auth->conf.r0kh_list = r0kh; + + if (timeout > 0) + eloop_register_timeout(timeout, 0, wpa_ft_rrb_del_r0kh, + wpa_auth, r0kh); + + if (wpa_ft_rrb_init_r0kh_seq(r0kh) < 0) + return NULL; + + return r0kh; +} + + +static void wpa_ft_rrb_del_r1kh(void *eloop_ctx, void *timeout_ctx) +{ + struct wpa_authenticator *wpa_auth = eloop_ctx; + struct ft_remote_r1kh *r1kh, *prev = NULL; + + if (!wpa_auth->conf.r1kh_list) + return; + + for (r1kh = *wpa_auth->conf.r1kh_list; r1kh; r1kh = r1kh->next) { + if (r1kh == timeout_ctx) + break; + prev = r1kh; + } + if (!r1kh) + return; + if (prev) + prev->next = r1kh->next; + else + *wpa_auth->conf.r1kh_list = r1kh->next; + if (r1kh->seq) + wpa_ft_rrb_seq_flush(wpa_auth, r1kh->seq, 0); + os_free(r1kh->seq); + os_free(r1kh); +} + + +static void wpa_ft_rrb_r1kh_replenish(struct wpa_authenticator *wpa_auth, + struct ft_remote_r1kh *r1kh, int timeout) +{ + if (timeout > 0) + eloop_replenish_timeout(timeout, 0, wpa_ft_rrb_del_r1kh, + wpa_auth, r1kh); +} + + +static struct ft_remote_r1kh * +wpa_ft_rrb_add_r1kh(struct wpa_authenticator *wpa_auth, + struct ft_remote_r1kh *r1kh_wildcard, + const u8 *src_addr, const u8 *r1kh_id, int timeout) +{ + struct ft_remote_r1kh *r1kh; + + if (!wpa_auth->conf.r1kh_list) + return NULL; + + r1kh = os_zalloc(sizeof(*r1kh)); + if (!r1kh) + return NULL; + + os_memcpy(r1kh->addr, src_addr, sizeof(r1kh->addr)); + os_memcpy(r1kh->id, r1kh_id, sizeof(r1kh->id)); + os_memcpy(r1kh->key, r1kh_wildcard->key, sizeof(r1kh->key)); + r1kh->next = *wpa_auth->conf.r1kh_list; + *wpa_auth->conf.r1kh_list = r1kh; + + if (timeout > 0) + eloop_register_timeout(timeout, 0, wpa_ft_rrb_del_r1kh, + wpa_auth, r1kh); + + if (wpa_ft_rrb_init_r1kh_seq(r1kh) < 0) + return NULL; + + return r1kh; +} + + +void wpa_ft_sta_deinit(struct wpa_state_machine *sm) +{ + eloop_cancel_timeout(wpa_ft_expire_pull, sm, NULL); +} + + +static void wpa_ft_deinit_seq(struct wpa_authenticator *wpa_auth) +{ + struct ft_remote_r0kh *r0kh; + struct ft_remote_r1kh *r1kh; + + eloop_cancel_timeout(wpa_ft_rrb_seq_timeout, wpa_auth, ELOOP_ALL_CTX); + + if (wpa_auth->conf.r0kh_list) + r0kh = *wpa_auth->conf.r0kh_list; + else + r0kh = NULL; + for (; r0kh; r0kh = r0kh->next) { + if (!r0kh->seq) + continue; + wpa_ft_rrb_seq_flush(wpa_auth, r0kh->seq, 0); + os_free(r0kh->seq); + r0kh->seq = NULL; + } + + if (wpa_auth->conf.r1kh_list) + r1kh = *wpa_auth->conf.r1kh_list; + else + r1kh = NULL; + for (; r1kh; r1kh = r1kh->next) { + if (!r1kh->seq) + continue; + wpa_ft_rrb_seq_flush(wpa_auth, r1kh->seq, 0); + os_free(r1kh->seq); + r1kh->seq = NULL; + } +} + + +static void wpa_ft_deinit_rkh_tmp(struct wpa_authenticator *wpa_auth) +{ + struct ft_remote_r0kh *r0kh, *r0kh_next, *r0kh_prev = NULL; + struct ft_remote_r1kh *r1kh, *r1kh_next, *r1kh_prev = NULL; + + if (wpa_auth->conf.r0kh_list) + r0kh = *wpa_auth->conf.r0kh_list; + else + r0kh = NULL; + while (r0kh) { + r0kh_next = r0kh->next; + if (eloop_cancel_timeout(wpa_ft_rrb_del_r0kh, wpa_auth, + r0kh) > 0) { + if (r0kh_prev) + r0kh_prev->next = r0kh_next; + else + *wpa_auth->conf.r0kh_list = r0kh_next; + os_free(r0kh); + } else { + r0kh_prev = r0kh; + } + r0kh = r0kh_next; + } + + if (wpa_auth->conf.r1kh_list) + r1kh = *wpa_auth->conf.r1kh_list; + else + r1kh = NULL; + while (r1kh) { + r1kh_next = r1kh->next; + if (eloop_cancel_timeout(wpa_ft_rrb_del_r1kh, wpa_auth, + r1kh) > 0) { + if (r1kh_prev) + r1kh_prev->next = r1kh_next; + else + *wpa_auth->conf.r1kh_list = r1kh_next; + os_free(r1kh); + } else { + r1kh_prev = r1kh; + } + r1kh = r1kh_next; + } +} + + +void wpa_ft_deinit(struct wpa_authenticator *wpa_auth) +{ + wpa_ft_deinit_seq(wpa_auth); + wpa_ft_deinit_rkh_tmp(wpa_auth); +} + + +static void wpa_ft_block_r0kh(struct wpa_authenticator *wpa_auth, + const u8 *f_r0kh_id, size_t f_r0kh_id_len) +{ + struct ft_remote_r0kh *r0kh, *r0kh_wildcard; + + if (!wpa_auth->conf.rkh_neg_timeout) + return; + + wpa_ft_rrb_lookup_r0kh(wpa_auth, f_r0kh_id, f_r0kh_id_len, + &r0kh, &r0kh_wildcard); + + if (!r0kh_wildcard) { + /* r0kh removed after neg_timeout and might need re-adding */ + return; + } + + wpa_hexdump(MSG_DEBUG, "FT: Blacklist R0KH-ID", + f_r0kh_id, f_r0kh_id_len); + + if (r0kh) { + wpa_ft_rrb_r0kh_timeout(wpa_auth, r0kh, + wpa_auth->conf.rkh_neg_timeout); + os_memset(r0kh->addr, 0, ETH_ALEN); + } else + wpa_ft_rrb_add_r0kh(wpa_auth, r0kh_wildcard, NULL, f_r0kh_id, + f_r0kh_id_len, + wpa_auth->conf.rkh_neg_timeout); +} + + +static void wpa_ft_expire_pull(void *eloop_ctx, void *timeout_ctx) +{ + struct wpa_state_machine *sm = eloop_ctx; + + wpa_printf(MSG_DEBUG, "FT: Timeout pending pull request for " MACSTR, + MAC2STR(sm->addr)); + if (sm->ft_pending_pull_left_retries <= 0) + wpa_ft_block_r0kh(sm->wpa_auth, sm->r0kh_id, sm->r0kh_id_len); + + /* cancel multiple timeouts */ + eloop_cancel_timeout(wpa_ft_expire_pull, sm, NULL); + ft_finish_pull(sm); +} + + +static int wpa_ft_pull_pmk_r1(struct wpa_state_machine *sm, + const u8 *ies, size_t ies_len, + const u8 *pmk_r0_name) +{ + struct ft_remote_r0kh *r0kh, *r0kh_wildcard; + u8 *packet = NULL; + const u8 *key, *f_r1kh_id = sm->wpa_auth->conf.r1_key_holder; + size_t packet_len, key_len; + struct ft_rrb_seq f_seq; + int tsecs, tusecs, first; + struct wpabuf *ft_pending_req_ies; + int r0kh_timeout; + struct tlv_list req_enc[] = { + { .type = FT_RRB_PMK_R0_NAME, .len = WPA_PMK_NAME_LEN, + .data = pmk_r0_name }, + { .type = FT_RRB_S1KH_ID, .len = ETH_ALEN, + .data = sm->addr }, + { .type = FT_RRB_LAST_EMPTY, .len = 0, .data = NULL }, + }; + struct tlv_list req_auth[] = { + { .type = FT_RRB_NONCE, .len = FT_RRB_NONCE_LEN, + .data = sm->ft_pending_pull_nonce }, + { .type = FT_RRB_SEQ, .len = sizeof(f_seq), + .data = (u8 *) &f_seq }, + { .type = FT_RRB_R0KH_ID, .len = sm->r0kh_id_len, + .data = sm->r0kh_id }, + { .type = FT_RRB_R1KH_ID, .len = FT_R1KH_ID_LEN, + .data = f_r1kh_id }, + { .type = FT_RRB_LAST_EMPTY, .len = 0, .data = NULL }, + }; + + if (sm->ft_pending_pull_left_retries <= 0) + return -1; + first = sm->ft_pending_pull_left_retries == + sm->wpa_auth->conf.rkh_pull_retries; + sm->ft_pending_pull_left_retries--; + + wpa_ft_rrb_lookup_r0kh(sm->wpa_auth, sm->r0kh_id, sm->r0kh_id_len, + &r0kh, &r0kh_wildcard); + + /* Keep r0kh sufficiently long in the list for seq num check */ + r0kh_timeout = sm->wpa_auth->conf.rkh_pull_timeout / 1000 + + 1 + ftRRBseqTimeout; + if (r0kh) { + wpa_ft_rrb_r0kh_replenish(sm->wpa_auth, r0kh, r0kh_timeout); + } else if (r0kh_wildcard) { + wpa_printf(MSG_DEBUG, "FT: Using wildcard R0KH-ID"); + /* r0kh->addr: updated by SEQ_RESP and wpa_ft_expire_pull */ + r0kh = wpa_ft_rrb_add_r0kh(sm->wpa_auth, r0kh_wildcard, + r0kh_wildcard->addr, + sm->r0kh_id, sm->r0kh_id_len, + r0kh_timeout); } if (r0kh == NULL) { wpa_hexdump(MSG_DEBUG, "FT: Did not find R0KH-ID", sm->r0kh_id, sm->r0kh_id_len); return -1; } + if (is_zero_ether_addr(r0kh->addr)) { + wpa_hexdump(MSG_DEBUG, "FT: R0KH-ID is blacklisted", + sm->r0kh_id, sm->r0kh_id_len); + return -1; + } + if (os_memcmp(r0kh->addr, sm->wpa_auth->addr, ETH_ALEN) == 0) { + wpa_printf(MSG_DEBUG, + "FT: R0KH-ID points to self - no matching key available"); + return -1; + } + + key = r0kh->key; + key_len = sizeof(r0kh->key); wpa_printf(MSG_DEBUG, "FT: Send PMK-R1 pull request to remote R0KH " "address " MACSTR, MAC2STR(r0kh->addr)); - os_memset(&frame, 0, sizeof(frame)); - frame.frame_type = RSN_REMOTE_FRAME_TYPE_FT_RRB; - frame.packet_type = FT_PACKET_R0KH_R1KH_PULL; - frame.data_length = host_to_le16(FT_R0KH_R1KH_PULL_DATA_LEN); - os_memcpy(frame.ap_address, sm->wpa_auth->addr, ETH_ALEN); + if (r0kh->seq->rx.num_last == 0) { + /* A sequence request will be sent out anyway when pull + * response is received. Send it out now to avoid one RTT. */ + wpa_ft_rrb_seq_req(sm->wpa_auth, r0kh->seq, r0kh->addr, + r0kh->id, r0kh->id_len, f_r1kh_id, key, + key_len, NULL, 0, NULL, 0, NULL); + } - /* aes_wrap() does not support inplace encryption, so use a temporary - * buffer for the data. */ - if (random_get_bytes(f.nonce, FT_R0KH_R1KH_PULL_NONCE_LEN)) { + if (first && + random_get_bytes(sm->ft_pending_pull_nonce, FT_RRB_NONCE_LEN) < 0) { wpa_printf(MSG_DEBUG, "FT: Failed to get random data for " "nonce"); return -1; } - os_memcpy(sm->ft_pending_pull_nonce, f.nonce, - FT_R0KH_R1KH_PULL_NONCE_LEN); - os_memcpy(f.pmk_r0_name, pmk_r0_name, WPA_PMK_NAME_LEN); - os_memcpy(f.r1kh_id, sm->wpa_auth->conf.r1_key_holder, FT_R1KH_ID_LEN); - os_memcpy(f.s1kh_id, sm->addr, ETH_ALEN); - os_memset(f.pad, 0, sizeof(f.pad)); - if (aes_wrap(r0kh->key, sizeof(r0kh->key), - (FT_R0KH_R1KH_PULL_DATA_LEN + 7) / 8, - f.nonce, frame.nonce) < 0) + if (wpa_ft_new_seq(r0kh->seq, &f_seq) < 0) { + wpa_printf(MSG_DEBUG, "FT: Failed to get seq num"); + return -1; + } + + if (wpa_ft_rrb_build(key, key_len, req_enc, NULL, req_auth, NULL, + sm->wpa_auth->addr, FT_PACKET_R0KH_R1KH_PULL, + &packet, &packet_len) < 0) return -1; + ft_pending_req_ies = wpabuf_alloc_copy(ies, ies_len); wpabuf_free(sm->ft_pending_req_ies); - sm->ft_pending_req_ies = wpabuf_alloc_copy(ies, ies_len); - if (sm->ft_pending_req_ies == NULL) + sm->ft_pending_req_ies = ft_pending_req_ies; + if (!sm->ft_pending_req_ies) { + os_free(packet); return -1; + } + + tsecs = sm->wpa_auth->conf.rkh_pull_timeout / 1000; + tusecs = (sm->wpa_auth->conf.rkh_pull_timeout % 1000) * 1000; + eloop_register_timeout(tsecs, tusecs, wpa_ft_expire_pull, sm, NULL); + + wpa_ft_rrb_oui_send(sm->wpa_auth, r0kh->addr, FT_PACKET_R0KH_R1KH_PULL, + packet, packet_len); - wpa_ft_rrb_send(sm->wpa_auth, r0kh->addr, (u8 *) &frame, sizeof(frame)); + os_free(packet); return 0; } -int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, const u8 *pmk, - struct wpa_ptk *ptk) +int wpa_ft_store_pmk_fils(struct wpa_state_machine *sm, + const u8 *pmk_r0, const u8 *pmk_r0_name) { - u8 pmk_r0[PMK_LEN], pmk_r0_name[WPA_PMK_NAME_LEN]; - u8 pmk_r1[PMK_LEN]; + int expires_in = sm->wpa_auth->conf.r0_key_lifetime; + struct vlan_description vlan; + const u8 *identity, *radius_cui; + size_t identity_len, radius_cui_len; + int session_timeout; + size_t pmk_r0_len = wpa_key_mgmt_sha384(sm->wpa_key_mgmt) ? + SHA384_MAC_LEN : PMK_LEN; + + if (wpa_ft_get_vlan(sm->wpa_auth, sm->addr, &vlan) < 0) { + wpa_printf(MSG_DEBUG, "FT: vlan not available for STA " MACSTR, + MAC2STR(sm->addr)); + return -1; + } + + identity_len = wpa_ft_get_identity(sm->wpa_auth, sm->addr, &identity); + radius_cui_len = wpa_ft_get_radius_cui(sm->wpa_auth, sm->addr, + &radius_cui); + session_timeout = wpa_ft_get_session_timeout(sm->wpa_auth, sm->addr); + + return wpa_ft_store_pmk_r0(sm->wpa_auth, sm->addr, pmk_r0, pmk_r0_len, + pmk_r0_name, sm->pairwise, &vlan, expires_in, + session_timeout, identity, identity_len, + radius_cui, radius_cui_len); +} + + +int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, struct wpa_ptk *ptk) +{ + u8 pmk_r0[PMK_LEN_MAX], pmk_r0_name[WPA_PMK_NAME_LEN]; + size_t pmk_r0_len = wpa_key_mgmt_sha384(sm->wpa_key_mgmt) ? + SHA384_MAC_LEN : PMK_LEN; + size_t pmk_r1_len = pmk_r0_len; + u8 pmk_r1[PMK_LEN_MAX]; u8 ptk_name[WPA_PMK_NAME_LEN]; const u8 *mdid = sm->wpa_auth->conf.mobility_domain; const u8 *r0kh = sm->wpa_auth->conf.r0_key_holder; @@ -375,6 +2090,12 @@ int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, const u8 *pmk, const u8 *r1kh = sm->wpa_auth->conf.r1_key_holder; const u8 *ssid = sm->wpa_auth->conf.ssid; size_t ssid_len = sm->wpa_auth->conf.ssid_len; + int psk_local = sm->wpa_auth->conf.ft_psk_generate_local; + int expires_in = sm->wpa_auth->conf.r0_key_lifetime; + struct vlan_description vlan; + const u8 *identity, *radius_cui; + size_t identity_len, radius_cui_len; + int session_timeout; if (sm->xxkey_len == 0) { wpa_printf(MSG_DEBUG, "FT: XXKey not available for key " @@ -382,23 +2103,45 @@ int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, const u8 *pmk, return -1; } - wpa_derive_pmk_r0(sm->xxkey, sm->xxkey_len, ssid, ssid_len, mdid, - r0kh, r0kh_len, sm->addr, pmk_r0, pmk_r0_name); - wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R0", pmk_r0, PMK_LEN); - wpa_hexdump(MSG_DEBUG, "FT: PMKR0Name", pmk_r0_name, WPA_PMK_NAME_LEN); - wpa_ft_store_pmk_r0(sm->wpa_auth, sm->addr, pmk_r0, pmk_r0_name, - sm->pairwise); + if (wpa_ft_get_vlan(sm->wpa_auth, sm->addr, &vlan) < 0) { + wpa_printf(MSG_DEBUG, "FT: vlan not available for STA " MACSTR, + MAC2STR(sm->addr)); + return -1; + } + + identity_len = wpa_ft_get_identity(sm->wpa_auth, sm->addr, &identity); + radius_cui_len = wpa_ft_get_radius_cui(sm->wpa_auth, sm->addr, + &radius_cui); + session_timeout = wpa_ft_get_session_timeout(sm->wpa_auth, sm->addr); - wpa_derive_pmk_r1(pmk_r0, pmk_r0_name, r1kh, sm->addr, - pmk_r1, sm->pmk_r1_name); - wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", pmk_r1, PMK_LEN); + if (wpa_derive_pmk_r0(sm->xxkey, sm->xxkey_len, ssid, ssid_len, mdid, + r0kh, r0kh_len, sm->addr, + pmk_r0, pmk_r0_name, + wpa_key_mgmt_sha384(sm->wpa_key_mgmt)) < 0) + return -1; + wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R0", pmk_r0, pmk_r0_len); + wpa_hexdump(MSG_DEBUG, "FT: PMKR0Name", pmk_r0_name, WPA_PMK_NAME_LEN); + if (!psk_local || !wpa_key_mgmt_ft_psk(sm->wpa_key_mgmt)) + wpa_ft_store_pmk_r0(sm->wpa_auth, sm->addr, pmk_r0, pmk_r0_len, + pmk_r0_name, + sm->pairwise, &vlan, expires_in, + session_timeout, identity, identity_len, + radius_cui, radius_cui_len); + + if (wpa_derive_pmk_r1(pmk_r0, pmk_r0_len, pmk_r0_name, r1kh, sm->addr, + pmk_r1, sm->pmk_r1_name) < 0) + return -1; + wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", pmk_r1, pmk_r1_len); wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", sm->pmk_r1_name, WPA_PMK_NAME_LEN); - wpa_ft_store_pmk_r1(sm->wpa_auth, sm->addr, pmk_r1, sm->pmk_r1_name, - sm->pairwise); - - return wpa_pmk_r1_to_ptk(pmk_r1, sm->SNonce, sm->ANonce, sm->addr, - sm->wpa_auth->addr, sm->pmk_r1_name, + if (!psk_local || !wpa_key_mgmt_ft_psk(sm->wpa_key_mgmt)) + wpa_ft_store_pmk_r1(sm->wpa_auth, sm->addr, pmk_r1, pmk_r1_len, + sm->pmk_r1_name, sm->pairwise, &vlan, + expires_in, session_timeout, identity, + identity_len, radius_cui, radius_cui_len); + + return wpa_pmk_r1_to_ptk(pmk_r1, pmk_r1_len, sm->SNonce, sm->ANonce, + sm->addr, sm->wpa_auth->addr, sm->pmk_r1_name, ptk, ptk_name, sm->wpa_key_mgmt, sm->pairwise); } @@ -406,9 +2149,9 @@ int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, const u8 *pmk, static inline int wpa_auth_get_seqnum(struct wpa_authenticator *wpa_auth, const u8 *addr, int idx, u8 *seq) { - if (wpa_auth->cb.get_seqnum == NULL) + if (wpa_auth->cb->get_seqnum == NULL) return -1; - return wpa_auth->cb.get_seqnum(wpa_auth->cb.ctx, addr, idx, seq); + return wpa_auth->cb->get_seqnum(wpa_auth->cb_ctx, addr, idx, seq); } @@ -420,6 +2163,16 @@ static u8 * wpa_ft_gtk_subelem(struct wpa_state_machine *sm, size_t *len) const u8 *key; size_t key_len; u8 keybuf[32]; + const u8 *kek; + size_t kek_len; + + if (wpa_key_mgmt_fils(sm->wpa_key_mgmt)) { + kek = sm->PTK.kek2; + kek_len = sm->PTK.kek2_len; + } else { + kek = sm->PTK.kek; + kek_len = sm->PTK.kek_len; + } key_len = gsm->GTK_len; if (key_len > sizeof(keybuf)) @@ -458,8 +2211,10 @@ static u8 * wpa_ft_gtk_subelem(struct wpa_state_machine *sm, size_t *len) WPA_PUT_LE16(&subelem[2], gsm->GN & 0x03); subelem[4] = gsm->GTK_len; wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, subelem + 5); - if (aes_wrap(sm->PTK.kek, sm->PTK.kek_len, key_len / 8, key, - subelem + 13)) { + if (aes_wrap(kek, kek_len, key_len / 8, key, subelem + 13)) { + wpa_printf(MSG_DEBUG, + "FT: GTK subelem encryption failed: kek_len=%d", + (int) kek_len); os_free(subelem); return NULL; } @@ -475,10 +2230,23 @@ static u8 * wpa_ft_igtk_subelem(struct wpa_state_machine *sm, size_t *len) u8 *subelem, *pos; struct wpa_group *gsm = sm->group; size_t subelem_len; + const u8 *kek; + size_t kek_len; + size_t igtk_len; + + if (wpa_key_mgmt_fils(sm->wpa_key_mgmt)) { + kek = sm->PTK.kek2; + kek_len = sm->PTK.kek2_len; + } else { + kek = sm->PTK.kek; + kek_len = sm->PTK.kek_len; + } + + igtk_len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher); /* Sub-elem ID[1] | Length[1] | KeyID[2] | IPN[6] | Key Length[1] | * Key[16+8] */ - subelem_len = 1 + 1 + 2 + 6 + 1 + WPA_IGTK_LEN + 8; + subelem_len = 1 + 1 + 2 + 6 + 1 + igtk_len + 8; subelem = os_zalloc(subelem_len); if (subelem == NULL) return NULL; @@ -490,9 +2258,12 @@ static u8 * wpa_ft_igtk_subelem(struct wpa_state_machine *sm, size_t *len) pos += 2; wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, pos); pos += 6; - *pos++ = WPA_IGTK_LEN; - if (aes_wrap(sm->PTK.kek, sm->PTK.kek_len, WPA_IGTK_LEN / 8, + *pos++ = igtk_len; + if (aes_wrap(kek, kek_len, igtk_len / 8, gsm->IGTK[gsm->GN_igtk - 4], pos)) { + wpa_printf(MSG_DEBUG, + "FT: IGTK subelem encryption failed: kek_len=%d", + (int) kek_len); os_free(subelem); return NULL; } @@ -639,17 +2410,21 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos, const u8 *req_ies, size_t req_ies_len) { u8 *end, *mdie, *ftie, *rsnie = NULL, *r0kh_id, *subelem = NULL; + u8 *fte_mic, *elem_count; size_t mdie_len, ftie_len, rsnie_len = 0, r0kh_id_len, subelem_len = 0; int res; struct wpa_auth_config *conf; - struct rsn_ftie *_ftie; struct wpa_ft_ies parse; u8 *ric_start; u8 *anonce, *snonce; + const u8 *kck; + size_t kck_len; + int use_sha384; if (sm == NULL) return pos; + use_sha384 = wpa_key_mgmt_sha384(sm->wpa_key_mgmt); conf = &sm->wpa_auth->conf; if (!wpa_key_mgmt_ft(sm->wpa_key_mgmt)) @@ -657,14 +2432,28 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos, end = pos + max_len; - if (auth_alg == WLAN_AUTH_FT) { + if (auth_alg == WLAN_AUTH_FT || + ((auth_alg == WLAN_AUTH_FILS_SK || + auth_alg == WLAN_AUTH_FILS_SK_PFS || + auth_alg == WLAN_AUTH_FILS_PK) && + (sm->wpa_key_mgmt & (WPA_KEY_MGMT_FT_FILS_SHA256 | + WPA_KEY_MGMT_FT_FILS_SHA384)))) { + if (!sm->pmk_r1_name_valid) { + wpa_printf(MSG_ERROR, + "FT: PMKR1Name is not valid for Assoc Resp RSNE"); + return NULL; + } + wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name for Assoc Resp RSNE", + sm->pmk_r1_name, WPA_PMK_NAME_LEN); /* * RSN (only present if this is a Reassociation Response and - * part of a fast BSS transition) + * part of a fast BSS transition; or if this is a + * (Re)Association Response frame during an FT initial mobility + * domain association using FILS) */ res = wpa_write_rsn_ie(conf, pos, end - pos, sm->pmk_r1_name); if (res < 0) - return pos; + return NULL; rsnie = pos; rsnie_len = res; pos += res; @@ -673,7 +2462,7 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos, /* Mobility Domain Information */ res = wpa_write_mdie(conf, pos, end - pos); if (res < 0) - return pos; + return NULL; mdie = pos; mdie_len = res; pos += res; @@ -681,6 +2470,11 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos, /* Fast BSS Transition Information */ if (auth_alg == WLAN_AUTH_FT) { subelem = wpa_ft_gtk_subelem(sm, &subelem_len); + if (!subelem) { + wpa_printf(MSG_DEBUG, + "FT: Failed to add GTK subelement"); + return NULL; + } r0kh_id = sm->r0kh_id; r0kh_id_len = sm->r0kh_id_len; anonce = sm->ANonce; @@ -692,14 +2486,16 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos, u8 *nbuf; igtk = wpa_ft_igtk_subelem(sm, &igtk_len); if (igtk == NULL) { + wpa_printf(MSG_DEBUG, + "FT: Failed to add IGTK subelement"); os_free(subelem); - return pos; + return NULL; } nbuf = os_realloc(subelem, subelem_len + igtk_len); if (nbuf == NULL) { os_free(subelem); os_free(igtk); - return pos; + return NULL; } subelem = nbuf; os_memcpy(subelem + subelem_len, igtk, igtk_len); @@ -707,50 +2503,101 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos, os_free(igtk); } #endif /* CONFIG_IEEE80211W */ +#ifdef CONFIG_OCV + if (wpa_auth_uses_ocv(sm)) { + struct wpa_channel_info ci; + u8 *nbuf, *ocipos; + + if (wpa_channel_info(sm->wpa_auth, &ci) != 0) { + wpa_printf(MSG_WARNING, + "Failed to get channel info for OCI element"); + os_free(subelem); + return NULL; + } + + subelem_len += 2 + OCV_OCI_LEN; + nbuf = os_realloc(subelem, subelem_len); + if (!nbuf) { + os_free(subelem); + return NULL; + } + subelem = nbuf; + + ocipos = subelem + subelem_len - 2 - OCV_OCI_LEN; + *ocipos++ = FTIE_SUBELEM_OCI; + *ocipos++ = OCV_OCI_LEN; + if (ocv_insert_oci(&ci, &ocipos) < 0) { + os_free(subelem); + return NULL; + } + } +#endif /* CONFIG_OCV */ } else { r0kh_id = conf->r0_key_holder; r0kh_id_len = conf->r0_key_holder_len; anonce = NULL; snonce = NULL; } - res = wpa_write_ftie(conf, r0kh_id, r0kh_id_len, anonce, snonce, pos, - end - pos, subelem, subelem_len); + res = wpa_write_ftie(conf, use_sha384, r0kh_id, r0kh_id_len, + anonce, snonce, pos, end - pos, + subelem, subelem_len); os_free(subelem); if (res < 0) - return pos; + return NULL; ftie = pos; ftie_len = res; pos += res; - _ftie = (struct rsn_ftie *) (ftie + 2); + if (use_sha384) { + struct rsn_ftie_sha384 *_ftie = + (struct rsn_ftie_sha384 *) (ftie + 2); + + fte_mic = _ftie->mic; + elem_count = &_ftie->mic_control[1]; + } else { + struct rsn_ftie *_ftie = (struct rsn_ftie *) (ftie + 2); + + fte_mic = _ftie->mic; + elem_count = &_ftie->mic_control[1]; + } if (auth_alg == WLAN_AUTH_FT) - _ftie->mic_control[1] = 3; /* Information element count */ + *elem_count = 3; /* Information element count */ ric_start = pos; - if (wpa_ft_parse_ies(req_ies, req_ies_len, &parse) == 0 && parse.ric) { + if (wpa_ft_parse_ies(req_ies, req_ies_len, &parse, use_sha384) == 0 + && parse.ric) { pos = wpa_ft_process_ric(sm, pos, end, parse.ric, parse.ric_len); if (auth_alg == WLAN_AUTH_FT) - _ftie->mic_control[1] += + *elem_count += ieee802_11_ie_count(ric_start, pos - ric_start); } if (ric_start == pos) ric_start = NULL; + if (wpa_key_mgmt_fils(sm->wpa_key_mgmt)) { + kck = sm->PTK.kck2; + kck_len = sm->PTK.kck2_len; + } else { + kck = sm->PTK.kck; + kck_len = sm->PTK.kck_len; + } if (auth_alg == WLAN_AUTH_FT && - wpa_ft_mic(sm->PTK.kck, sm->PTK.kck_len, sm->addr, - sm->wpa_auth->addr, 6, + wpa_ft_mic(kck, kck_len, sm->addr, sm->wpa_auth->addr, 6, mdie, mdie_len, ftie, ftie_len, rsnie, rsnie_len, ric_start, ric_start ? pos - ric_start : 0, - _ftie->mic) < 0) + fte_mic) < 0) { wpa_printf(MSG_DEBUG, "FT: Failed to calculate MIC"); + return NULL; + } os_free(sm->assoc_resp_ftie); sm->assoc_resp_ftie = os_malloc(ftie_len); - if (sm->assoc_resp_ftie) - os_memcpy(sm->assoc_resp_ftie, ftie, ftie_len); + if (!sm->assoc_resp_ftie) + return NULL; + os_memcpy(sm->assoc_resp_ftie, ftie, ftie_len); return pos; } @@ -761,10 +2608,10 @@ static inline int wpa_auth_set_key(struct wpa_authenticator *wpa_auth, enum wpa_alg alg, const u8 *addr, int idx, u8 *key, size_t key_len) { - if (wpa_auth->cb.set_key == NULL) + 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); + return wpa_auth->cb->set_key(wpa_auth->cb_ctx, vlan_id, alg, addr, idx, + key, key_len); } @@ -806,20 +2653,221 @@ void wpa_ft_install_ptk(struct wpa_state_machine *sm) } +/* Derive PMK-R1 from PSK, check all available PSK */ +static int wpa_ft_psk_pmk_r1(struct wpa_state_machine *sm, + const u8 *req_pmk_r1_name, + u8 *out_pmk_r1, int *out_pairwise, + struct vlan_description *out_vlan, + const u8 **out_identity, size_t *out_identity_len, + const u8 **out_radius_cui, + size_t *out_radius_cui_len, + int *out_session_timeout) +{ + const u8 *pmk = NULL; + u8 pmk_r0[PMK_LEN], pmk_r0_name[WPA_PMK_NAME_LEN]; + u8 pmk_r1[PMK_LEN], pmk_r1_name[WPA_PMK_NAME_LEN]; + struct wpa_authenticator *wpa_auth = sm->wpa_auth; + const u8 *mdid = wpa_auth->conf.mobility_domain; + const u8 *r0kh = sm->r0kh_id; + size_t r0kh_len = sm->r0kh_id_len; + const u8 *r1kh = wpa_auth->conf.r1_key_holder; + const u8 *ssid = wpa_auth->conf.ssid; + size_t ssid_len = wpa_auth->conf.ssid_len; + int pairwise; + + pairwise = sm->pairwise; + + for (;;) { + pmk = wpa_ft_get_psk(wpa_auth, sm->addr, sm->p2p_dev_addr, + pmk); + if (pmk == NULL) + break; + + if (wpa_derive_pmk_r0(pmk, PMK_LEN, ssid, ssid_len, mdid, r0kh, + r0kh_len, sm->addr, + pmk_r0, pmk_r0_name, 0) < 0 || + wpa_derive_pmk_r1(pmk_r0, PMK_LEN, pmk_r0_name, r1kh, + sm->addr, pmk_r1, pmk_r1_name) < 0 || + os_memcmp_const(pmk_r1_name, req_pmk_r1_name, + WPA_PMK_NAME_LEN) != 0) + continue; + + /* We found a PSK that matches the requested pmk_r1_name */ + wpa_printf(MSG_DEBUG, + "FT: Found PSK to generate PMK-R1 locally"); + os_memcpy(out_pmk_r1, pmk_r1, PMK_LEN); + if (out_pairwise) + *out_pairwise = pairwise; + os_memcpy(sm->PMK, pmk, PMK_LEN); + sm->pmk_len = PMK_LEN; + if (out_vlan && + wpa_ft_get_vlan(sm->wpa_auth, sm->addr, out_vlan) < 0) { + wpa_printf(MSG_DEBUG, "FT: vlan not available for STA " + MACSTR, MAC2STR(sm->addr)); + return -1; + } + + if (out_identity && out_identity_len) { + *out_identity_len = wpa_ft_get_identity( + sm->wpa_auth, sm->addr, out_identity); + } + + if (out_radius_cui && out_radius_cui_len) { + *out_radius_cui_len = wpa_ft_get_radius_cui( + sm->wpa_auth, sm->addr, out_radius_cui); + } + + if (out_session_timeout) { + *out_session_timeout = wpa_ft_get_session_timeout( + sm->wpa_auth, sm->addr); + } + + return 0; + } + + wpa_printf(MSG_DEBUG, + "FT: Did not find PSK to generate PMK-R1 locally"); + return -1; +} + + +/* Detect the configuration the station asked for. + * Required to detect FT-PSK and pairwise cipher. + */ +static int wpa_ft_set_key_mgmt(struct wpa_state_machine *sm, + struct wpa_ft_ies *parse) +{ + int key_mgmt, ciphers; + + if (sm->wpa_key_mgmt) + return 0; + + key_mgmt = parse->key_mgmt & sm->wpa_auth->conf.wpa_key_mgmt; + if (!key_mgmt) { + wpa_printf(MSG_DEBUG, "FT: Invalid key mgmt (0x%x) from " + MACSTR, parse->key_mgmt, MAC2STR(sm->addr)); + return -1; + } + if (key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) + sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X; +#ifdef CONFIG_SHA384 + else if (key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X_SHA384) + sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X_SHA384; +#endif /* CONFIG_SHA384 */ + else if (key_mgmt & WPA_KEY_MGMT_FT_PSK) + sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_PSK; +#ifdef CONFIG_FILS + else if (key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA256) + sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA256; + else if (key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA384) + sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA384; +#endif /* CONFIG_FILS */ + ciphers = parse->pairwise_cipher & sm->wpa_auth->conf.rsn_pairwise; + if (!ciphers) { + wpa_printf(MSG_DEBUG, "FT: Invalid pairwise cipher (0x%x) from " + MACSTR, + parse->pairwise_cipher, MAC2STR(sm->addr)); + return -1; + } + sm->pairwise = wpa_pick_pairwise_cipher(ciphers, 0); + + return 0; +} + + +static int wpa_ft_local_derive_pmk_r1(struct wpa_authenticator *wpa_auth, + struct wpa_state_machine *sm, + const u8 *r0kh_id, size_t r0kh_id_len, + const u8 *req_pmk_r0_name, + const u8 *req_pmk_r1_name, + u8 *out_pmk_r1, int *out_pairwise, + struct vlan_description *vlan, + const u8 **identity, size_t *identity_len, + const u8 **radius_cui, + size_t *radius_cui_len, + int *out_session_timeout) +{ + struct wpa_auth_config *conf = &wpa_auth->conf; + const struct wpa_ft_pmk_r0_sa *r0; + u8 pmk_r1_name[WPA_PMK_NAME_LEN]; + int expires_in = 0; + int session_timeout = 0; + struct os_reltime now; + + if (conf->r0_key_holder_len != r0kh_id_len || + os_memcmp(conf->r0_key_holder, r0kh_id, conf->r0_key_holder_len) != + 0) + return -1; /* not our R0KH-ID */ + + wpa_printf(MSG_DEBUG, "FT: STA R0KH-ID matching local configuration"); + if (wpa_ft_fetch_pmk_r0(sm->wpa_auth, sm->addr, req_pmk_r0_name, &r0) < + 0) + return -1; /* no matching PMKR0Name in local cache */ + + wpa_printf(MSG_DEBUG, "FT: Requested PMKR0Name found in local cache"); + + if (wpa_derive_pmk_r1(r0->pmk_r0, r0->pmk_r0_len, r0->pmk_r0_name, + conf->r1_key_holder, + sm->addr, out_pmk_r1, pmk_r1_name) < 0) + return -1; + wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", out_pmk_r1, r0->pmk_r0_len); + wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", pmk_r1_name, WPA_PMK_NAME_LEN); + + os_get_reltime(&now); + if (r0->expiration) + expires_in = r0->expiration - now.sec; + + if (r0->session_timeout) + session_timeout = r0->session_timeout - now.sec; + + wpa_ft_store_pmk_r1(wpa_auth, sm->addr, out_pmk_r1, r0->pmk_r0_len, + pmk_r1_name, + sm->pairwise, r0->vlan, expires_in, session_timeout, + r0->identity, r0->identity_len, + r0->radius_cui, r0->radius_cui_len); + + *out_pairwise = sm->pairwise; + if (vlan) { + if (r0->vlan) + *vlan = *r0->vlan; + else + os_memset(vlan, 0, sizeof(*vlan)); + } + + if (identity && identity_len) { + *identity = r0->identity; + *identity_len = r0->identity_len; + } + + if (radius_cui && radius_cui_len) { + *radius_cui = r0->radius_cui; + *radius_cui_len = r0->radius_cui_len; + } + + *out_session_timeout = session_timeout; + + return 0; +} + + static int wpa_ft_process_auth_req(struct wpa_state_machine *sm, const u8 *ies, size_t ies_len, u8 **resp_ies, size_t *resp_ies_len) { struct rsn_mdie *mdie; - struct rsn_ftie *ftie; - u8 pmk_r1[PMK_LEN], pmk_r1_name[WPA_PMK_NAME_LEN]; + u8 pmk_r1[PMK_LEN_MAX], pmk_r1_name[WPA_PMK_NAME_LEN]; u8 ptk_name[WPA_PMK_NAME_LEN]; struct wpa_auth_config *conf; struct wpa_ft_ies parse; size_t buflen; int ret; u8 *pos, *end; - int pairwise; + int pairwise, session_timeout = 0; + struct vlan_description vlan; + const u8 *identity, *radius_cui; + size_t identity_len = 0, radius_cui_len = 0; + int use_sha384; + size_t pmk_r1_len; *resp_ies = NULL; *resp_ies_len = 0; @@ -830,10 +2878,12 @@ static int wpa_ft_process_auth_req(struct wpa_state_machine *sm, wpa_hexdump(MSG_DEBUG, "FT: Received authentication frame IEs", ies, ies_len); - if (wpa_ft_parse_ies(ies, ies_len, &parse) < 0) { + if (wpa_ft_parse_ies(ies, ies_len, &parse, -1)) { wpa_printf(MSG_DEBUG, "FT: Failed to parse FT IEs"); return WLAN_STATUS_UNSPECIFIED_FAILURE; } + use_sha384 = wpa_key_mgmt_sha384(parse.key_mgmt); + pmk_r1_len = use_sha384 ? SHA384_MAC_LEN : PMK_LEN; mdie = (struct rsn_mdie *) parse.mdie; if (mdie == NULL || parse.mdie_len < sizeof(*mdie) || @@ -844,13 +2894,27 @@ static int wpa_ft_process_auth_req(struct wpa_state_machine *sm, return WLAN_STATUS_INVALID_MDIE; } - ftie = (struct rsn_ftie *) parse.ftie; - if (ftie == NULL || parse.ftie_len < sizeof(*ftie)) { - wpa_printf(MSG_DEBUG, "FT: Invalid FTIE"); - return WLAN_STATUS_INVALID_FTIE; - } + if (use_sha384) { + struct rsn_ftie_sha384 *ftie; + + ftie = (struct rsn_ftie_sha384 *) parse.ftie; + if (!ftie || parse.ftie_len < sizeof(*ftie)) { + wpa_printf(MSG_DEBUG, "FT: Invalid FTIE"); + return WLAN_STATUS_INVALID_FTIE; + } + + os_memcpy(sm->SNonce, ftie->snonce, WPA_NONCE_LEN); + } else { + struct rsn_ftie *ftie; + + ftie = (struct rsn_ftie *) parse.ftie; + if (!ftie || parse.ftie_len < sizeof(*ftie)) { + wpa_printf(MSG_DEBUG, "FT: Invalid FTIE"); + return WLAN_STATUS_INVALID_FTIE; + } - os_memcpy(sm->SNonce, ftie->snonce, WPA_NONCE_LEN); + os_memcpy(sm->SNonce, ftie->snonce, WPA_NONCE_LEN); + } if (parse.r0kh_id == NULL) { wpa_printf(MSG_DEBUG, "FT: Invalid FTIE - no R0KH-ID"); @@ -867,28 +2931,62 @@ static int wpa_ft_process_auth_req(struct wpa_state_machine *sm, return WLAN_STATUS_INVALID_PMKID; } + if (wpa_ft_set_key_mgmt(sm, &parse) < 0) + return WLAN_STATUS_UNSPECIFIED_FAILURE; + wpa_hexdump(MSG_DEBUG, "FT: Requested PMKR0Name", parse.rsn_pmkid, WPA_PMK_NAME_LEN); - wpa_derive_pmk_r1_name(parse.rsn_pmkid, - sm->wpa_auth->conf.r1_key_holder, sm->addr, - pmk_r1_name); + if (wpa_derive_pmk_r1_name(parse.rsn_pmkid, + sm->wpa_auth->conf.r1_key_holder, sm->addr, + pmk_r1_name, use_sha384) < 0) + return WLAN_STATUS_UNSPECIFIED_FAILURE; wpa_hexdump(MSG_DEBUG, "FT: Derived requested PMKR1Name", pmk_r1_name, WPA_PMK_NAME_LEN); - if (wpa_ft_fetch_pmk_r1(sm->wpa_auth, sm->addr, pmk_r1_name, pmk_r1, - &pairwise) < 0) { + if (conf->ft_psk_generate_local && + wpa_key_mgmt_ft_psk(sm->wpa_key_mgmt)) { + if (wpa_ft_psk_pmk_r1(sm, pmk_r1_name, pmk_r1, &pairwise, + &vlan, &identity, &identity_len, + &radius_cui, &radius_cui_len, + &session_timeout) < 0) + return WLAN_STATUS_INVALID_PMKID; + wpa_printf(MSG_DEBUG, + "FT: Generated PMK-R1 for FT-PSK locally"); + } else if (wpa_ft_fetch_pmk_r1(sm->wpa_auth, sm->addr, pmk_r1_name, + pmk_r1, &pmk_r1_len, &pairwise, &vlan, + &identity, &identity_len, &radius_cui, + &radius_cui_len, &session_timeout) < 0) { + wpa_printf(MSG_DEBUG, + "FT: No PMK-R1 available in local cache for the requested PMKR1Name"); + if (wpa_ft_local_derive_pmk_r1(sm->wpa_auth, sm, + parse.r0kh_id, parse.r0kh_id_len, + parse.rsn_pmkid, + pmk_r1_name, pmk_r1, &pairwise, + &vlan, &identity, &identity_len, + &radius_cui, &radius_cui_len, + &session_timeout) == 0) { + wpa_printf(MSG_DEBUG, + "FT: Generated PMK-R1 based on local PMK-R0"); + goto pmk_r1_derived; + } + if (wpa_ft_pull_pmk_r1(sm, ies, ies_len, parse.rsn_pmkid) < 0) { - wpa_printf(MSG_DEBUG, "FT: Did not have matching " - "PMK-R1 and unknown R0KH-ID"); + wpa_printf(MSG_DEBUG, + "FT: Did not have matching PMK-R1 and either unknown or blocked R0KH-ID or NAK from R0KH"); return WLAN_STATUS_INVALID_PMKID; } return -1; /* Status pending */ + } else { + wpa_printf(MSG_DEBUG, "FT: Found PMKR1Name from local cache"); } - wpa_hexdump_key(MSG_DEBUG, "FT: Selected PMK-R1", pmk_r1, PMK_LEN); +pmk_r1_derived: + wpa_hexdump_key(MSG_DEBUG, "FT: Selected PMK-R1", pmk_r1, pmk_r1_len); sm->pmk_r1_name_valid = 1; os_memcpy(sm->pmk_r1_name, pmk_r1_name, WPA_PMK_NAME_LEN); + os_memcpy(sm->pmk_r1, pmk_r1, pmk_r1_len); + sm->pmk_r1_len = pmk_r1_len; if (random_get_bytes(sm->ANonce, WPA_NONCE_LEN)) { wpa_printf(MSG_DEBUG, "FT: Failed to get random data for " @@ -901,8 +2999,8 @@ static int wpa_ft_process_auth_req(struct wpa_state_machine *sm, wpa_hexdump(MSG_DEBUG, "FT: Generated ANonce", sm->ANonce, WPA_NONCE_LEN); - if (wpa_pmk_r1_to_ptk(pmk_r1, sm->SNonce, sm->ANonce, sm->addr, - sm->wpa_auth->addr, pmk_r1_name, + if (wpa_pmk_r1_to_ptk(pmk_r1, pmk_r1_len, sm->SNonce, sm->ANonce, + sm->addr, sm->wpa_auth->addr, pmk_r1_name, &sm->PTK, ptk_name, sm->wpa_key_mgmt, pairwise) < 0) return WLAN_STATUS_UNSPECIFIED_FAILURE; @@ -912,44 +3010,51 @@ static int wpa_ft_process_auth_req(struct wpa_state_machine *sm, sm->tk_already_set = FALSE; wpa_ft_install_ptk(sm); + if (wpa_ft_set_vlan(sm->wpa_auth, sm->addr, &vlan) < 0) { + wpa_printf(MSG_DEBUG, "FT: Failed to configure VLAN"); + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + if (wpa_ft_set_identity(sm->wpa_auth, sm->addr, + identity, identity_len) < 0 || + wpa_ft_set_radius_cui(sm->wpa_auth, sm->addr, + radius_cui, radius_cui_len) < 0) { + wpa_printf(MSG_DEBUG, "FT: Failed to configure identity/CUI"); + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + wpa_ft_set_session_timeout(sm->wpa_auth, sm->addr, session_timeout); + buflen = 2 + sizeof(struct rsn_mdie) + 2 + sizeof(struct rsn_ftie) + 2 + FT_R1KH_ID_LEN + 200; *resp_ies = os_zalloc(buflen); - if (*resp_ies == NULL) { - return WLAN_STATUS_UNSPECIFIED_FAILURE; - } + if (*resp_ies == NULL) + goto fail; pos = *resp_ies; end = *resp_ies + buflen; ret = wpa_write_rsn_ie(conf, pos, end - pos, parse.rsn_pmkid); - if (ret < 0) { - os_free(*resp_ies); - *resp_ies = NULL; - return WLAN_STATUS_UNSPECIFIED_FAILURE; - } + if (ret < 0) + goto fail; pos += ret; ret = wpa_write_mdie(conf, pos, end - pos); - if (ret < 0) { - os_free(*resp_ies); - *resp_ies = NULL; - return WLAN_STATUS_UNSPECIFIED_FAILURE; - } + if (ret < 0) + goto fail; pos += ret; - ret = wpa_write_ftie(conf, parse.r0kh_id, parse.r0kh_id_len, + ret = wpa_write_ftie(conf, use_sha384, parse.r0kh_id, parse.r0kh_id_len, sm->ANonce, sm->SNonce, pos, end - pos, NULL, 0); - if (ret < 0) { - os_free(*resp_ies); - *resp_ies = NULL; - return WLAN_STATUS_UNSPECIFIED_FAILURE; - } + if (ret < 0) + goto fail; pos += ret; *resp_ies_len = pos - *resp_ies; return WLAN_STATUS_SUCCESS; +fail: + os_free(*resp_ies); + *resp_ies = NULL; + return WLAN_STATUS_UNSPECIFIED_FAILURE; } @@ -977,6 +3082,7 @@ void wpa_ft_process_auth(struct wpa_state_machine *sm, const u8 *bssid, sm->ft_pending_cb = cb; sm->ft_pending_cb_ctx = ctx; sm->ft_pending_auth_transaction = auth_transaction; + sm->ft_pending_pull_left_retries = sm->wpa_auth->conf.rkh_pull_retries; res = wpa_ft_process_auth_req(sm, ies, ies_len, &resp_ies, &resp_ies_len); if (res < 0) { @@ -1000,17 +3106,23 @@ u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, { struct wpa_ft_ies parse; struct rsn_mdie *mdie; - struct rsn_ftie *ftie; u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN]; size_t mic_len = 16; unsigned int count; + const u8 *kck; + size_t kck_len; + int use_sha384; + const u8 *anonce, *snonce, *fte_mic; + u8 fte_elem_count; if (sm == NULL) return WLAN_STATUS_UNSPECIFIED_FAILURE; + use_sha384 = wpa_key_mgmt_sha384(sm->wpa_key_mgmt); + wpa_hexdump(MSG_DEBUG, "FT: Reassoc Req IEs", ies, ies_len); - if (wpa_ft_parse_ies(ies, ies_len, &parse) < 0) { + if (wpa_ft_parse_ies(ies, ies_len, &parse, use_sha384) < 0) { wpa_printf(MSG_DEBUG, "FT: Failed to parse FT IEs"); return WLAN_STATUS_UNSPECIFIED_FAILURE; } @@ -1041,34 +3153,56 @@ u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, return WLAN_STATUS_INVALID_MDIE; } - ftie = (struct rsn_ftie *) parse.ftie; - if (ftie == NULL || parse.ftie_len < sizeof(*ftie)) { - wpa_printf(MSG_DEBUG, "FT: Invalid FTIE"); - return WLAN_STATUS_INVALID_FTIE; + if (use_sha384) { + struct rsn_ftie_sha384 *ftie; + + ftie = (struct rsn_ftie_sha384 *) parse.ftie; + if (ftie == NULL || parse.ftie_len < sizeof(*ftie)) { + wpa_printf(MSG_DEBUG, "FT: Invalid FTIE"); + return WLAN_STATUS_INVALID_FTIE; + } + + anonce = ftie->anonce; + snonce = ftie->snonce; + fte_elem_count = ftie->mic_control[1]; + fte_mic = ftie->mic; + } else { + struct rsn_ftie *ftie; + + ftie = (struct rsn_ftie *) parse.ftie; + if (ftie == NULL || parse.ftie_len < sizeof(*ftie)) { + wpa_printf(MSG_DEBUG, "FT: Invalid FTIE"); + return WLAN_STATUS_INVALID_FTIE; + } + + anonce = ftie->anonce; + snonce = ftie->snonce; + fte_elem_count = ftie->mic_control[1]; + fte_mic = ftie->mic; } - if (os_memcmp(ftie->snonce, sm->SNonce, WPA_NONCE_LEN) != 0) { + if (os_memcmp(snonce, sm->SNonce, WPA_NONCE_LEN) != 0) { wpa_printf(MSG_DEBUG, "FT: SNonce mismatch in FTIE"); wpa_hexdump(MSG_DEBUG, "FT: Received SNonce", - ftie->snonce, WPA_NONCE_LEN); + snonce, WPA_NONCE_LEN); wpa_hexdump(MSG_DEBUG, "FT: Expected SNonce", sm->SNonce, WPA_NONCE_LEN); - return -1; + return WLAN_STATUS_INVALID_FTIE; } - if (os_memcmp(ftie->anonce, sm->ANonce, WPA_NONCE_LEN) != 0) { + if (os_memcmp(anonce, sm->ANonce, WPA_NONCE_LEN) != 0) { wpa_printf(MSG_DEBUG, "FT: ANonce mismatch in FTIE"); wpa_hexdump(MSG_DEBUG, "FT: Received ANonce", - ftie->anonce, WPA_NONCE_LEN); + anonce, WPA_NONCE_LEN); wpa_hexdump(MSG_DEBUG, "FT: Expected ANonce", sm->ANonce, WPA_NONCE_LEN); - return -1; + return WLAN_STATUS_INVALID_FTIE; } if (parse.r0kh_id == NULL) { wpa_printf(MSG_DEBUG, "FT: No R0KH-ID subelem in FTIE"); - return -1; + return WLAN_STATUS_INVALID_FTIE; } if (parse.r0kh_id_len != sm->r0kh_id_len || @@ -1080,12 +3214,12 @@ u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, parse.r0kh_id, parse.r0kh_id_len); wpa_hexdump(MSG_DEBUG, "FT: The current R0KH-ID", sm->r0kh_id, sm->r0kh_id_len); - return -1; + return WLAN_STATUS_INVALID_FTIE; } if (parse.r1kh_id == NULL) { wpa_printf(MSG_DEBUG, "FT: No R1KH-ID subelem in FTIE"); - return -1; + return WLAN_STATUS_INVALID_FTIE; } if (os_memcmp_const(parse.r1kh_id, sm->wpa_auth->conf.r1_key_holder, @@ -1096,7 +3230,7 @@ u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, parse.r1kh_id, FT_R1KH_ID_LEN); wpa_hexdump(MSG_DEBUG, "FT: Expected R1KH-ID", sm->wpa_auth->conf.r1_key_holder, FT_R1KH_ID_LEN); - return -1; + return WLAN_STATUS_INVALID_FTIE; } if (parse.rsn_pmkid == NULL || @@ -1104,21 +3238,27 @@ u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, { wpa_printf(MSG_DEBUG, "FT: No matching PMKR1Name (PMKID) in " "RSNIE (pmkid=%d)", !!parse.rsn_pmkid); - return -1; + return WLAN_STATUS_INVALID_PMKID; } count = 3; if (parse.ric) count += ieee802_11_ie_count(parse.ric, parse.ric_len); - if (ftie->mic_control[1] != count) { + if (fte_elem_count != count) { wpa_printf(MSG_DEBUG, "FT: Unexpected IE count in MIC " "Control: received %u expected %u", - ftie->mic_control[1], count); - return -1; + fte_elem_count, count); + return WLAN_STATUS_UNSPECIFIED_FAILURE; } - if (wpa_ft_mic(sm->PTK.kck, sm->PTK.kck_len, sm->addr, - sm->wpa_auth->addr, 5, + if (wpa_key_mgmt_fils(sm->wpa_key_mgmt)) { + kck = sm->PTK.kck2; + kck_len = sm->PTK.kck2_len; + } else { + kck = sm->PTK.kck; + kck_len = sm->PTK.kck_len; + } + if (wpa_ft_mic(kck, kck_len, sm->addr, sm->wpa_auth->addr, 5, parse.mdie - 2, parse.mdie_len + 2, parse.ftie - 2, parse.ftie_len + 2, parse.rsn - 2, parse.rsn_len + 2, @@ -1128,12 +3268,12 @@ u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, return WLAN_STATUS_UNSPECIFIED_FAILURE; } - if (os_memcmp_const(mic, ftie->mic, mic_len) != 0) { + if (os_memcmp_const(mic, fte_mic, mic_len) != 0) { wpa_printf(MSG_DEBUG, "FT: Invalid MIC in FTIE"); wpa_printf(MSG_DEBUG, "FT: addr=" MACSTR " auth_addr=" MACSTR, MAC2STR(sm->addr), MAC2STR(sm->wpa_auth->addr)); wpa_hexdump(MSG_MSGDUMP, "FT: Received MIC", - ftie->mic, mic_len); + fte_mic, mic_len); wpa_hexdump(MSG_MSGDUMP, "FT: Calculated MIC", mic, mic_len); wpa_hexdump(MSG_MSGDUMP, "FT: MDIE", parse.mdie - 2, parse.mdie_len + 2); @@ -1144,6 +3284,32 @@ u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, return WLAN_STATUS_INVALID_FTIE; } +#ifdef CONFIG_OCV + if (wpa_auth_uses_ocv(sm)) { + struct wpa_channel_info ci; + int tx_chanwidth; + int tx_seg1_idx; + + if (wpa_channel_info(sm->wpa_auth, &ci) != 0) { + wpa_printf(MSG_WARNING, + "Failed to get channel info to validate received OCI in (Re)Assoc Request"); + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + + if (get_sta_tx_parameters(sm, + channel_width_to_int(ci.chanwidth), + ci.seg1_idx, &tx_chanwidth, + &tx_seg1_idx) < 0) + return WLAN_STATUS_UNSPECIFIED_FAILURE; + + if (ocv_verify_tx_params(parse.oci, parse.oci_len, &ci, + tx_chanwidth, tx_seg1_idx) != 0) { + wpa_printf(MSG_WARNING, "%s", ocv_errorstr); + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + } +#endif /* CONFIG_OCV */ + return WLAN_STATUS_SUCCESS; } @@ -1201,6 +3367,11 @@ int wpa_ft_action_rx(struct wpa_state_machine *sm, const u8 *data, size_t len) wpa_hexdump(MSG_MSGDUMP, "FT: Action frame body", ies, ies_len); + if (!sm->wpa_auth->conf.ft_over_ds) { + wpa_printf(MSG_DEBUG, "FT: Over-DS option disabled - reject"); + return -1; + } + /* RRB - Forward action frame to the target AP */ frame = os_malloc(sizeof(*frame) + len); if (frame == NULL) @@ -1253,6 +3424,7 @@ static int wpa_ft_rrb_rx_request(struct wpa_authenticator *wpa_auth, sm->ft_pending_cb = wpa_ft_rrb_rx_request_cb; sm->ft_pending_cb_ctx = sm; os_memcpy(sm->ft_pending_current_ap, current_ap, ETH_ALEN); + sm->ft_pending_pull_left_retries = sm->wpa_auth->conf.rkh_pull_retries; res = wpa_ft_process_auth_req(sm, body, len, &resp_ies, &resp_ies_len); if (res < 0) { @@ -1318,112 +3490,431 @@ static int wpa_ft_send_rrb_auth_resp(struct wpa_state_machine *sm, } +static int wpa_ft_rrb_build_r0(const u8 *key, const size_t key_len, + const struct tlv_list *tlvs, + const struct wpa_ft_pmk_r0_sa *pmk_r0, + const u8 *r1kh_id, const u8 *s1kh_id, + const struct tlv_list *tlv_auth, + const u8 *src_addr, u8 type, + u8 **packet, size_t *packet_len) +{ + u8 pmk_r1[PMK_LEN_MAX]; + size_t pmk_r1_len = pmk_r0->pmk_r0_len; + u8 pmk_r1_name[WPA_PMK_NAME_LEN]; + u8 f_pairwise[sizeof(le16)]; + u8 f_expires_in[sizeof(le16)]; + u8 f_session_timeout[sizeof(le32)]; + int expires_in; + int session_timeout; + struct os_reltime now; + int ret; + struct tlv_list sess_tlv[] = { + { .type = FT_RRB_PMK_R1, .len = pmk_r1_len, + .data = pmk_r1 }, + { .type = FT_RRB_PMK_R1_NAME, .len = sizeof(pmk_r1_name), + .data = pmk_r1_name }, + { .type = FT_RRB_PAIRWISE, .len = sizeof(f_pairwise), + .data = f_pairwise }, + { .type = FT_RRB_EXPIRES_IN, .len = sizeof(f_expires_in), + .data = f_expires_in }, + { .type = FT_RRB_IDENTITY, .len = pmk_r0->identity_len, + .data = pmk_r0->identity }, + { .type = FT_RRB_RADIUS_CUI, .len = pmk_r0->radius_cui_len, + .data = pmk_r0->radius_cui }, + { .type = FT_RRB_SESSION_TIMEOUT, + .len = sizeof(f_session_timeout), + .data = f_session_timeout }, + { .type = FT_RRB_LAST_EMPTY, .len = 0, .data = NULL }, + }; + + if (wpa_derive_pmk_r1(pmk_r0->pmk_r0, pmk_r0->pmk_r0_len, + pmk_r0->pmk_r0_name, r1kh_id, + s1kh_id, pmk_r1, pmk_r1_name) < 0) + return -1; + wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1 (for peer AP)", + pmk_r1, pmk_r1_len); + wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name (for peer AP)", + pmk_r1_name, WPA_PMK_NAME_LEN); + WPA_PUT_LE16(f_pairwise, pmk_r0->pairwise); + + os_get_reltime(&now); + if (pmk_r0->expiration > now.sec) + expires_in = pmk_r0->expiration - now.sec; + else if (pmk_r0->expiration) + expires_in = 1; + else + expires_in = 0; + WPA_PUT_LE16(f_expires_in, expires_in); + + if (pmk_r0->session_timeout > now.sec) + session_timeout = pmk_r0->session_timeout - now.sec; + else if (pmk_r0->session_timeout) + session_timeout = 1; + else + session_timeout = 0; + WPA_PUT_LE32(f_session_timeout, session_timeout); + + ret = wpa_ft_rrb_build(key, key_len, tlvs, sess_tlv, tlv_auth, + pmk_r0->vlan, src_addr, type, + packet, packet_len); + + os_memset(pmk_r1, 0, sizeof(pmk_r1)); + + return ret; +} + + static int wpa_ft_rrb_rx_pull(struct wpa_authenticator *wpa_auth, const u8 *src_addr, - const u8 *data, size_t data_len) + const u8 *enc, size_t enc_len, + const u8 *auth, size_t auth_len, + int no_defer) { - struct ft_r0kh_r1kh_pull_frame f; - const u8 *crypt; - u8 *plain; - struct ft_remote_r1kh *r1kh; - struct ft_r0kh_r1kh_resp_frame resp, r; - u8 pmk_r0[PMK_LEN]; - int pairwise; + const char *msgtype = "pull request"; + u8 *plain = NULL, *packet = NULL; + size_t plain_len = 0, packet_len = 0; + struct ft_remote_r1kh *r1kh, *r1kh_wildcard; + const u8 *key; + size_t key_len; + int seq_ret; + const u8 *f_nonce, *f_r0kh_id, *f_r1kh_id, *f_s1kh_id, *f_pmk_r0_name; + size_t f_nonce_len, f_r0kh_id_len, f_r1kh_id_len, f_s1kh_id_len; + size_t f_pmk_r0_name_len; + const struct wpa_ft_pmk_r0_sa *r0; + int ret; + struct tlv_list resp[2]; + struct tlv_list resp_auth[5]; + struct ft_rrb_seq f_seq; wpa_printf(MSG_DEBUG, "FT: Received PMK-R1 pull"); - if (data_len < sizeof(f)) - return -1; + RRB_GET_AUTH(FT_RRB_R0KH_ID, r0kh_id, msgtype, -1); + wpa_hexdump(MSG_DEBUG, "FT: R0KH-ID", f_r0kh_id, f_r0kh_id_len); - r1kh = wpa_auth->conf.r1kh_list; - while (r1kh) { - if (os_memcmp(r1kh->addr, src_addr, ETH_ALEN) == 0) - break; - r1kh = r1kh->next; + if (wpa_ft_rrb_check_r0kh(wpa_auth, f_r0kh_id, f_r0kh_id_len)) { + wpa_printf(MSG_DEBUG, "FT: R0KH-ID mismatch"); + goto out; } - if (r1kh == NULL) { - wpa_printf(MSG_DEBUG, "FT: No matching R1KH address found for " - "PMK-R1 pull source address " MACSTR, - MAC2STR(src_addr)); - return -1; + + RRB_GET_AUTH(FT_RRB_R1KH_ID, r1kh_id, msgtype, FT_R1KH_ID_LEN); + wpa_printf(MSG_DEBUG, "FT: R1KH-ID=" MACSTR, MAC2STR(f_r1kh_id)); + + wpa_ft_rrb_lookup_r1kh(wpa_auth, f_r1kh_id, &r1kh, &r1kh_wildcard); + if (r1kh) { + key = r1kh->key; + key_len = sizeof(r1kh->key); + } else if (r1kh_wildcard) { + wpa_printf(MSG_DEBUG, "FT: Using wildcard R1KH-ID"); + key = r1kh_wildcard->key; + key_len = sizeof(r1kh_wildcard->key); + } else { + goto out; } - crypt = data + offsetof(struct ft_r0kh_r1kh_pull_frame, nonce); - os_memset(&f, 0, sizeof(f)); - plain = ((u8 *) &f) + offsetof(struct ft_r0kh_r1kh_pull_frame, nonce); - /* aes_unwrap() does not support inplace decryption, so use a temporary - * buffer for the data. */ - if (aes_unwrap(r1kh->key, sizeof(r1kh->key), - (FT_R0KH_R1KH_PULL_DATA_LEN + 7) / 8, - crypt, plain) < 0) { - wpa_printf(MSG_DEBUG, "FT: Failed to decrypt PMK-R1 pull " - "request from " MACSTR, MAC2STR(src_addr)); - return -1; + RRB_GET_AUTH(FT_RRB_NONCE, nonce, "pull request", FT_RRB_NONCE_LEN); + wpa_hexdump(MSG_DEBUG, "FT: nonce", f_nonce, f_nonce_len); + + seq_ret = FT_RRB_SEQ_DROP; + if (r1kh) + seq_ret = wpa_ft_rrb_seq_chk(r1kh->seq, src_addr, enc, enc_len, + auth, auth_len, msgtype, no_defer); + if (!no_defer && r1kh_wildcard && + (!r1kh || os_memcmp(r1kh->addr, src_addr, ETH_ALEN) != 0)) { + /* wildcard: r1kh-id unknown or changed addr -> do a seq req */ + seq_ret = FT_RRB_SEQ_DEFER; } - wpa_hexdump(MSG_DEBUG, "FT: PMK-R1 pull - nonce", - f.nonce, sizeof(f.nonce)); - wpa_hexdump(MSG_DEBUG, "FT: PMK-R1 pull - PMKR0Name", - f.pmk_r0_name, WPA_PMK_NAME_LEN); - wpa_printf(MSG_DEBUG, "FT: PMK-R1 pull - R1KH-ID=" MACSTR " S1KH-ID=" - MACSTR, MAC2STR(f.r1kh_id), MAC2STR(f.s1kh_id)); - - os_memset(&resp, 0, sizeof(resp)); - resp.frame_type = RSN_REMOTE_FRAME_TYPE_FT_RRB; - resp.packet_type = FT_PACKET_R0KH_R1KH_RESP; - resp.data_length = host_to_le16(FT_R0KH_R1KH_RESP_DATA_LEN); - os_memcpy(resp.ap_address, wpa_auth->addr, ETH_ALEN); - - /* aes_wrap() does not support inplace encryption, so use a temporary - * buffer for the data. */ - os_memcpy(r.nonce, f.nonce, sizeof(f.nonce)); - os_memcpy(r.r1kh_id, f.r1kh_id, FT_R1KH_ID_LEN); - os_memcpy(r.s1kh_id, f.s1kh_id, ETH_ALEN); - if (wpa_ft_fetch_pmk_r0(wpa_auth, f.s1kh_id, f.pmk_r0_name, pmk_r0, - &pairwise) < 0) { - wpa_printf(MSG_DEBUG, "FT: No matching PMKR0Name found for " - "PMK-R1 pull"); - return -1; + if (seq_ret == FT_RRB_SEQ_DROP) + goto out; + + if (wpa_ft_rrb_decrypt(key, key_len, enc, enc_len, auth, auth_len, + src_addr, FT_PACKET_R0KH_R1KH_PULL, + &plain, &plain_len) < 0) + goto out; + + if (!r1kh) + r1kh = wpa_ft_rrb_add_r1kh(wpa_auth, r1kh_wildcard, src_addr, + f_r1kh_id, + wpa_auth->conf.rkh_pos_timeout); + if (!r1kh) + goto out; + + if (seq_ret == FT_RRB_SEQ_DEFER) { + wpa_ft_rrb_seq_req(wpa_auth, r1kh->seq, src_addr, f_r0kh_id, + f_r0kh_id_len, f_r1kh_id, key, key_len, + enc, enc_len, auth, auth_len, + &wpa_ft_rrb_rx_pull); + goto out; } - wpa_derive_pmk_r1(pmk_r0, f.pmk_r0_name, f.r1kh_id, f.s1kh_id, - r.pmk_r1, r.pmk_r1_name); - wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", r.pmk_r1, PMK_LEN); - wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", r.pmk_r1_name, - WPA_PMK_NAME_LEN); - r.pairwise = host_to_le16(pairwise); - os_memset(r.pad, 0, sizeof(r.pad)); + wpa_ft_rrb_seq_accept(wpa_auth, r1kh->seq, src_addr, auth, auth_len, + msgtype); + wpa_ft_rrb_r1kh_replenish(wpa_auth, r1kh, + wpa_auth->conf.rkh_pos_timeout); - if (aes_wrap(r1kh->key, sizeof(r1kh->key), - (FT_R0KH_R1KH_RESP_DATA_LEN + 7) / 8, - r.nonce, resp.nonce) < 0) { - os_memset(pmk_r0, 0, PMK_LEN); - return -1; + RRB_GET(FT_RRB_PMK_R0_NAME, pmk_r0_name, msgtype, WPA_PMK_NAME_LEN); + wpa_hexdump(MSG_DEBUG, "FT: PMKR0Name", f_pmk_r0_name, + f_pmk_r0_name_len); + + RRB_GET(FT_RRB_S1KH_ID, s1kh_id, msgtype, ETH_ALEN); + wpa_printf(MSG_DEBUG, "FT: S1KH-ID=" MACSTR, MAC2STR(f_s1kh_id)); + + if (wpa_ft_new_seq(r1kh->seq, &f_seq) < 0) { + wpa_printf(MSG_DEBUG, "FT: Failed to get seq num"); + goto out; + } + + resp[0].type = FT_RRB_S1KH_ID; + resp[0].len = f_s1kh_id_len; + resp[0].data = f_s1kh_id; + resp[1].type = FT_RRB_LAST_EMPTY; + resp[1].len = 0; + resp[1].data = NULL; + + resp_auth[0].type = FT_RRB_NONCE; + resp_auth[0].len = f_nonce_len; + resp_auth[0].data = f_nonce; + resp_auth[1].type = FT_RRB_SEQ; + resp_auth[1].len = sizeof(f_seq); + resp_auth[1].data = (u8 *) &f_seq; + resp_auth[2].type = FT_RRB_R0KH_ID; + resp_auth[2].len = f_r0kh_id_len; + resp_auth[2].data = f_r0kh_id; + resp_auth[3].type = FT_RRB_R1KH_ID; + resp_auth[3].len = f_r1kh_id_len; + resp_auth[3].data = f_r1kh_id; + resp_auth[4].type = FT_RRB_LAST_EMPTY; + resp_auth[4].len = 0; + resp_auth[4].data = NULL; + + if (wpa_ft_fetch_pmk_r0(wpa_auth, f_s1kh_id, f_pmk_r0_name, &r0) < 0) { + wpa_printf(MSG_DEBUG, "FT: No matching PMK-R0-Name found"); + ret = wpa_ft_rrb_build(key, key_len, resp, NULL, resp_auth, + NULL, wpa_auth->addr, + FT_PACKET_R0KH_R1KH_RESP, + &packet, &packet_len); + } else { + ret = wpa_ft_rrb_build_r0(key, key_len, resp, r0, f_r1kh_id, + f_s1kh_id, resp_auth, wpa_auth->addr, + FT_PACKET_R0KH_R1KH_RESP, + &packet, &packet_len); } - os_memset(pmk_r0, 0, PMK_LEN); + if (!ret) + wpa_ft_rrb_oui_send(wpa_auth, src_addr, + FT_PACKET_R0KH_R1KH_RESP, packet, + packet_len); - wpa_ft_rrb_send(wpa_auth, src_addr, (u8 *) &resp, sizeof(resp)); +out: + os_free(plain); + os_free(packet); return 0; } -static void ft_pull_resp_cb_finish(void *eloop_ctx, void *timeout_ctx) +/* @returns 0 on success + * -1 on error + * -2 if FR_RRB_PAIRWISE is missing + */ +static int wpa_ft_rrb_rx_r1(struct wpa_authenticator *wpa_auth, + const u8 *src_addr, u8 type, + const u8 *enc, size_t enc_len, + const u8 *auth, size_t auth_len, + const char *msgtype, u8 *s1kh_id_out, + int (*cb)(struct wpa_authenticator *wpa_auth, + const u8 *src_addr, + const u8 *enc, size_t enc_len, + const u8 *auth, size_t auth_len, + int no_defer)) +{ + u8 *plain = NULL; + size_t plain_len = 0; + struct ft_remote_r0kh *r0kh, *r0kh_wildcard; + const u8 *key; + size_t key_len; + int seq_ret; + const u8 *f_r1kh_id, *f_s1kh_id, *f_r0kh_id; + const u8 *f_pmk_r1_name, *f_pairwise, *f_pmk_r1; + const u8 *f_expires_in; + size_t f_r1kh_id_len, f_s1kh_id_len, f_r0kh_id_len; + const u8 *f_identity, *f_radius_cui; + const u8 *f_session_timeout; + size_t f_pmk_r1_name_len, f_pairwise_len, f_pmk_r1_len; + size_t f_expires_in_len; + size_t f_identity_len, f_radius_cui_len; + size_t f_session_timeout_len; + int pairwise; + int ret = -1; + int expires_in; + int session_timeout; + struct vlan_description vlan; + size_t pmk_r1_len; + + RRB_GET_AUTH(FT_RRB_R0KH_ID, r0kh_id, msgtype, -1); + wpa_hexdump(MSG_DEBUG, "FT: R0KH-ID", f_r0kh_id, f_r0kh_id_len); + + RRB_GET_AUTH(FT_RRB_R1KH_ID, r1kh_id, msgtype, FT_R1KH_ID_LEN); + wpa_printf(MSG_DEBUG, "FT: R1KH-ID=" MACSTR, MAC2STR(f_r1kh_id)); + + if (wpa_ft_rrb_check_r1kh(wpa_auth, f_r1kh_id)) { + wpa_printf(MSG_DEBUG, "FT: R1KH-ID mismatch"); + goto out; + } + + wpa_ft_rrb_lookup_r0kh(wpa_auth, f_r0kh_id, f_r0kh_id_len, &r0kh, + &r0kh_wildcard); + if (r0kh) { + key = r0kh->key; + key_len = sizeof(r0kh->key); + } else if (r0kh_wildcard) { + wpa_printf(MSG_DEBUG, "FT: Using wildcard R0KH-ID"); + key = r0kh_wildcard->key; + key_len = sizeof(r0kh_wildcard->key); + } else { + goto out; + } + + seq_ret = FT_RRB_SEQ_DROP; + if (r0kh) { + seq_ret = wpa_ft_rrb_seq_chk(r0kh->seq, src_addr, enc, enc_len, + auth, auth_len, msgtype, + cb ? 0 : 1); + } + if (cb && r0kh_wildcard && + (!r0kh || os_memcmp(r0kh->addr, src_addr, ETH_ALEN) != 0)) { + /* wildcard: r0kh-id unknown or changed addr -> do a seq req */ + seq_ret = FT_RRB_SEQ_DEFER; + } + + if (seq_ret == FT_RRB_SEQ_DROP) + goto out; + + if (wpa_ft_rrb_decrypt(key, key_len, enc, enc_len, auth, auth_len, + src_addr, type, &plain, &plain_len) < 0) + goto out; + + if (!r0kh) + r0kh = wpa_ft_rrb_add_r0kh(wpa_auth, r0kh_wildcard, src_addr, + f_r0kh_id, f_r0kh_id_len, + wpa_auth->conf.rkh_pos_timeout); + if (!r0kh) + goto out; + + if (seq_ret == FT_RRB_SEQ_DEFER) { + wpa_ft_rrb_seq_req(wpa_auth, r0kh->seq, src_addr, f_r0kh_id, + f_r0kh_id_len, f_r1kh_id, key, key_len, + enc, enc_len, auth, auth_len, cb); + goto out; + } + + wpa_ft_rrb_seq_accept(wpa_auth, r0kh->seq, src_addr, auth, auth_len, + msgtype); + wpa_ft_rrb_r0kh_replenish(wpa_auth, r0kh, + wpa_auth->conf.rkh_pos_timeout); + + RRB_GET(FT_RRB_S1KH_ID, s1kh_id, msgtype, ETH_ALEN); + wpa_printf(MSG_DEBUG, "FT: S1KH-ID=" MACSTR, MAC2STR(f_s1kh_id)); + + if (s1kh_id_out) + os_memcpy(s1kh_id_out, f_s1kh_id, ETH_ALEN); + + ret = -2; + RRB_GET(FT_RRB_PAIRWISE, pairwise, msgtype, sizeof(le16)); + wpa_hexdump(MSG_DEBUG, "FT: pairwise", f_pairwise, f_pairwise_len); + + ret = -1; + RRB_GET(FT_RRB_PMK_R1_NAME, pmk_r1_name, msgtype, WPA_PMK_NAME_LEN); + wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", + f_pmk_r1_name, WPA_PMK_NAME_LEN); + + pmk_r1_len = PMK_LEN; + if (wpa_ft_rrb_get_tlv(plain, plain_len, FT_RRB_PMK_R1, &f_pmk_r1_len, + &f_pmk_r1) == 0 && + (f_pmk_r1_len == PMK_LEN || f_pmk_r1_len == SHA384_MAC_LEN)) + pmk_r1_len = f_pmk_r1_len; + RRB_GET(FT_RRB_PMK_R1, pmk_r1, msgtype, pmk_r1_len); + wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", f_pmk_r1, pmk_r1_len); + + pairwise = WPA_GET_LE16(f_pairwise); + + RRB_GET_OPTIONAL(FT_RRB_EXPIRES_IN, expires_in, msgtype, + sizeof(le16)); + if (f_expires_in) + expires_in = WPA_GET_LE16(f_expires_in); + else + expires_in = 0; + + wpa_printf(MSG_DEBUG, "FT: PMK-R1 %s - expires_in=%d", msgtype, + expires_in); + + if (wpa_ft_rrb_get_tlv_vlan(plain, plain_len, &vlan) < 0) { + wpa_printf(MSG_DEBUG, "FT: Cannot parse vlan"); + wpa_ft_rrb_dump(plain, plain_len); + goto out; + } + + wpa_printf(MSG_DEBUG, "FT: vlan %d%s", + le_to_host16(vlan.untagged), vlan.tagged[0] ? "+" : ""); + + RRB_GET_OPTIONAL(FT_RRB_IDENTITY, identity, msgtype, -1); + if (f_identity) + wpa_hexdump_ascii(MSG_DEBUG, "FT: Identity", f_identity, + f_identity_len); + + RRB_GET_OPTIONAL(FT_RRB_RADIUS_CUI, radius_cui, msgtype, -1); + if (f_radius_cui) + wpa_hexdump_ascii(MSG_DEBUG, "FT: CUI", f_radius_cui, + f_radius_cui_len); + + RRB_GET_OPTIONAL(FT_RRB_SESSION_TIMEOUT, session_timeout, msgtype, + sizeof(le32)); + if (f_session_timeout) + session_timeout = WPA_GET_LE32(f_session_timeout); + else + session_timeout = 0; + wpa_printf(MSG_DEBUG, "FT: session_timeout %d", session_timeout); + + if (wpa_ft_store_pmk_r1(wpa_auth, f_s1kh_id, f_pmk_r1, pmk_r1_len, + f_pmk_r1_name, + pairwise, &vlan, expires_in, session_timeout, + f_identity, f_identity_len, f_radius_cui, + f_radius_cui_len) < 0) + goto out; + + ret = 0; +out: + if (plain) { + os_memset(plain, 0, plain_len); + os_free(plain); + } + + return ret; + +} + + +static void ft_finish_pull(struct wpa_state_machine *sm) { - struct wpa_state_machine *sm = eloop_ctx; int res; u8 *resp_ies; size_t resp_ies_len; u16 status; + if (!sm->ft_pending_cb || !sm->ft_pending_req_ies) + return; + res = wpa_ft_process_auth_req(sm, wpabuf_head(sm->ft_pending_req_ies), wpabuf_len(sm->ft_pending_req_ies), &resp_ies, &resp_ies_len); + if (res < 0) { + /* this loop is broken by ft_pending_pull_left_retries */ + wpa_printf(MSG_DEBUG, + "FT: Callback postponed until response is available"); + return; + } wpabuf_free(sm->ft_pending_req_ies); sm->ft_pending_req_ies = NULL; - if (res < 0) - res = WLAN_STATUS_UNSPECIFIED_FAILURE; status = res; wpa_printf(MSG_DEBUG, "FT: Postponed auth callback result for " MACSTR " - status %u", MAC2STR(sm->addr), status); @@ -1435,171 +3926,383 @@ static void ft_pull_resp_cb_finish(void *eloop_ctx, void *timeout_ctx) } -static int ft_pull_resp_cb(struct wpa_state_machine *sm, void *ctx) +struct ft_get_sta_ctx { + const u8 *nonce; + const u8 *s1kh_id; + struct wpa_state_machine *sm; +}; + + +static int ft_get_sta_cb(struct wpa_state_machine *sm, void *ctx) { - struct ft_r0kh_r1kh_resp_frame *frame = ctx; + struct ft_get_sta_ctx *info = ctx; - if (os_memcmp(frame->s1kh_id, sm->addr, ETH_ALEN) != 0) - return 0; - if (os_memcmp(frame->nonce, sm->ft_pending_pull_nonce, - FT_R0KH_R1KH_PULL_NONCE_LEN) != 0) - return 0; - if (sm->ft_pending_cb == NULL || sm->ft_pending_req_ies == NULL) + if ((info->s1kh_id && + os_memcmp(info->s1kh_id, sm->addr, ETH_ALEN) != 0) || + os_memcmp(info->nonce, sm->ft_pending_pull_nonce, + FT_RRB_NONCE_LEN) != 0 || + sm->ft_pending_cb == NULL || sm->ft_pending_req_ies == NULL) return 0; - wpa_printf(MSG_DEBUG, "FT: Response to a pending pull request for " - MACSTR " - process from timeout", MAC2STR(sm->addr)); - eloop_register_timeout(0, 0, ft_pull_resp_cb_finish, sm, NULL); + info->sm = sm; + return 1; } static int wpa_ft_rrb_rx_resp(struct wpa_authenticator *wpa_auth, const u8 *src_addr, - const u8 *data, size_t data_len) + const u8 *enc, size_t enc_len, + const u8 *auth, size_t auth_len, + int no_defer) { - struct ft_r0kh_r1kh_resp_frame f; - const u8 *crypt; - u8 *plain; - struct ft_remote_r0kh *r0kh; - int pairwise, res; + const char *msgtype = "pull response"; + int nak, ret = -1; + struct ft_get_sta_ctx ctx; + u8 s1kh_id[ETH_ALEN]; + const u8 *f_nonce; + size_t f_nonce_len; wpa_printf(MSG_DEBUG, "FT: Received PMK-R1 pull response"); - if (data_len < sizeof(f)) - return -1; + RRB_GET_AUTH(FT_RRB_NONCE, nonce, msgtype, FT_RRB_NONCE_LEN); + wpa_hexdump(MSG_DEBUG, "FT: nonce", f_nonce, f_nonce_len); - r0kh = wpa_auth->conf.r0kh_list; - while (r0kh) { - if (os_memcmp(r0kh->addr, src_addr, ETH_ALEN) == 0) - break; - r0kh = r0kh->next; - } - if (r0kh == NULL) { - wpa_printf(MSG_DEBUG, "FT: No matching R0KH address found for " - "PMK-R0 pull response source address " MACSTR, - MAC2STR(src_addr)); + os_memset(&ctx, 0, sizeof(ctx)); + ctx.nonce = f_nonce; + if (!wpa_auth_for_each_sta(wpa_auth, ft_get_sta_cb, &ctx)) { + /* nonce not found */ + wpa_printf(MSG_DEBUG, "FT: Invalid nonce"); return -1; } - crypt = data + offsetof(struct ft_r0kh_r1kh_resp_frame, nonce); - os_memset(&f, 0, sizeof(f)); - plain = ((u8 *) &f) + offsetof(struct ft_r0kh_r1kh_resp_frame, nonce); - /* aes_unwrap() does not support inplace decryption, so use a temporary - * buffer for the data. */ - if (aes_unwrap(r0kh->key, sizeof(r0kh->key), - (FT_R0KH_R1KH_RESP_DATA_LEN + 7) / 8, - crypt, plain) < 0) { - wpa_printf(MSG_DEBUG, "FT: Failed to decrypt PMK-R1 pull " - "response from " MACSTR, MAC2STR(src_addr)); - return -1; + ret = wpa_ft_rrb_rx_r1(wpa_auth, src_addr, FT_PACKET_R0KH_R1KH_RESP, + enc, enc_len, auth, auth_len, msgtype, s1kh_id, + no_defer ? NULL : &wpa_ft_rrb_rx_resp); + if (ret == -2) { + ret = 0; + nak = 1; + } else { + nak = 0; } - - if (os_memcmp_const(f.r1kh_id, wpa_auth->conf.r1_key_holder, - FT_R1KH_ID_LEN) != 0) { - wpa_printf(MSG_DEBUG, "FT: PMK-R1 pull response did not use a " - "matching R1KH-ID"); + if (ret < 0) return -1; - } - - pairwise = le_to_host16(f.pairwise); - wpa_hexdump(MSG_DEBUG, "FT: PMK-R1 pull - nonce", - f.nonce, sizeof(f.nonce)); - wpa_printf(MSG_DEBUG, "FT: PMK-R1 pull - R1KH-ID=" MACSTR " S1KH-ID=" - MACSTR " pairwise=0x%x", - MAC2STR(f.r1kh_id), MAC2STR(f.s1kh_id), pairwise); - wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1 pull - PMK-R1", - f.pmk_r1, PMK_LEN); - wpa_hexdump(MSG_DEBUG, "FT: PMK-R1 pull - PMKR1Name", - f.pmk_r1_name, WPA_PMK_NAME_LEN); - res = wpa_ft_store_pmk_r1(wpa_auth, f.s1kh_id, f.pmk_r1, f.pmk_r1_name, - pairwise); - wpa_printf(MSG_DEBUG, "FT: Look for pending pull request"); - wpa_auth_for_each_sta(wpa_auth, ft_pull_resp_cb, &f); - os_memset(f.pmk_r1, 0, PMK_LEN); + ctx.s1kh_id = s1kh_id; + if (wpa_auth_for_each_sta(wpa_auth, ft_get_sta_cb, &ctx)) { + wpa_printf(MSG_DEBUG, + "FT: Response to a pending pull request for " MACSTR, + MAC2STR(ctx.sm->addr)); + eloop_cancel_timeout(wpa_ft_expire_pull, ctx.sm, NULL); + if (nak) + ctx.sm->ft_pending_pull_left_retries = 0; + ft_finish_pull(ctx.sm); + } - return res ? 0 : -1; +out: + return ret; } static int wpa_ft_rrb_rx_push(struct wpa_authenticator *wpa_auth, const u8 *src_addr, - const u8 *data, size_t data_len) + const u8 *enc, size_t enc_len, + const u8 *auth, size_t auth_len, int no_defer) { - struct ft_r0kh_r1kh_push_frame f; - const u8 *crypt; - u8 *plain; - struct ft_remote_r0kh *r0kh; - struct os_time now; - os_time_t tsend; - int pairwise; + const char *msgtype = "push"; wpa_printf(MSG_DEBUG, "FT: Received PMK-R1 push"); - if (data_len < sizeof(f)) + if (wpa_ft_rrb_rx_r1(wpa_auth, src_addr, FT_PACKET_R0KH_R1KH_PUSH, + enc, enc_len, auth, auth_len, msgtype, NULL, + no_defer ? NULL : wpa_ft_rrb_rx_push) < 0) return -1; - r0kh = wpa_auth->conf.r0kh_list; - while (r0kh) { - if (os_memcmp(r0kh->addr, src_addr, ETH_ALEN) == 0) - break; - r0kh = r0kh->next; + return 0; +} + + +static int wpa_ft_rrb_rx_seq(struct wpa_authenticator *wpa_auth, + const u8 *src_addr, int type, + const u8 *enc, size_t enc_len, + const u8 *auth, size_t auth_len, + struct ft_remote_seq **rkh_seq, + u8 **key, size_t *key_len, + struct ft_remote_r0kh **r0kh_out, + struct ft_remote_r1kh **r1kh_out, + struct ft_remote_r0kh **r0kh_wildcard_out, + struct ft_remote_r1kh **r1kh_wildcard_out) +{ + struct ft_remote_r0kh *r0kh = NULL; + struct ft_remote_r1kh *r1kh = NULL; + const u8 *f_r0kh_id, *f_r1kh_id; + size_t f_r0kh_id_len, f_r1kh_id_len; + int to_r0kh, to_r1kh; + u8 *plain = NULL; + size_t plain_len = 0; + struct ft_remote_r0kh *r0kh_wildcard; + struct ft_remote_r1kh *r1kh_wildcard; + + RRB_GET_AUTH(FT_RRB_R0KH_ID, r0kh_id, "seq", -1); + RRB_GET_AUTH(FT_RRB_R1KH_ID, r1kh_id, "seq", FT_R1KH_ID_LEN); + + to_r0kh = !wpa_ft_rrb_check_r0kh(wpa_auth, f_r0kh_id, f_r0kh_id_len); + to_r1kh = !wpa_ft_rrb_check_r1kh(wpa_auth, f_r1kh_id); + + if (to_r0kh && to_r1kh) { + wpa_printf(MSG_DEBUG, "FT: seq - local R0KH-ID and R1KH-ID"); + goto out; } - if (r0kh == NULL) { - wpa_printf(MSG_DEBUG, "FT: No matching R0KH address found for " - "PMK-R0 push source address " MACSTR, - MAC2STR(src_addr)); - return -1; + + if (!to_r0kh && !to_r1kh) { + wpa_printf(MSG_DEBUG, "FT: seq - remote R0KH-ID and R1KH-ID"); + goto out; } - crypt = data + offsetof(struct ft_r0kh_r1kh_push_frame, timestamp); - os_memset(&f, 0, sizeof(f)); - plain = ((u8 *) &f) + offsetof(struct ft_r0kh_r1kh_push_frame, - timestamp); - /* aes_unwrap() does not support inplace decryption, so use a temporary - * buffer for the data. */ - if (aes_unwrap(r0kh->key, sizeof(r0kh->key), - (FT_R0KH_R1KH_PUSH_DATA_LEN + 7) / 8, - crypt, plain) < 0) { - wpa_printf(MSG_DEBUG, "FT: Failed to decrypt PMK-R1 push from " - MACSTR, MAC2STR(src_addr)); - return -1; + if (!to_r0kh) { + wpa_ft_rrb_lookup_r0kh(wpa_auth, f_r0kh_id, f_r0kh_id_len, + &r0kh, &r0kh_wildcard); + if (!r0kh_wildcard && + (!r0kh || os_memcmp(r0kh->addr, src_addr, ETH_ALEN) != 0)) { + wpa_hexdump(MSG_DEBUG, "FT: Did not find R0KH-ID", + f_r0kh_id, f_r0kh_id_len); + goto out; + } + if (r0kh) { + *key = r0kh->key; + *key_len = sizeof(r0kh->key); + } else { + *key = r0kh_wildcard->key; + *key_len = sizeof(r0kh_wildcard->key); + } } - os_get_time(&now); - tsend = WPA_GET_LE32(f.timestamp); - if ((now.sec > tsend && now.sec - tsend > 60) || - (now.sec < tsend && tsend - now.sec > 60)) { - wpa_printf(MSG_DEBUG, "FT: PMK-R1 push did not have a valid " - "timestamp: sender time %d own time %d\n", - (int) tsend, (int) now.sec); - return -1; + if (!to_r1kh) { + wpa_ft_rrb_lookup_r1kh(wpa_auth, f_r1kh_id, &r1kh, + &r1kh_wildcard); + if (!r1kh_wildcard && + (!r1kh || os_memcmp(r1kh->addr, src_addr, ETH_ALEN) != 0)) { + wpa_hexdump(MSG_DEBUG, "FT: Did not find R1KH-ID", + f_r1kh_id, FT_R1KH_ID_LEN); + goto out; + } + if (r1kh) { + *key = r1kh->key; + *key_len = sizeof(r1kh->key); + } else { + *key = r1kh_wildcard->key; + *key_len = sizeof(r1kh_wildcard->key); + } } - if (os_memcmp_const(f.r1kh_id, wpa_auth->conf.r1_key_holder, - FT_R1KH_ID_LEN) != 0) { - wpa_printf(MSG_DEBUG, "FT: PMK-R1 push did not use a matching " - "R1KH-ID (received " MACSTR " own " MACSTR ")", - MAC2STR(f.r1kh_id), - MAC2STR(wpa_auth->conf.r1_key_holder)); - return -1; + if (wpa_ft_rrb_decrypt(*key, *key_len, enc, enc_len, auth, auth_len, + src_addr, type, &plain, &plain_len) < 0) + goto out; + + os_free(plain); + + if (!to_r0kh) { + if (!r0kh) + r0kh = wpa_ft_rrb_add_r0kh(wpa_auth, r0kh_wildcard, + src_addr, f_r0kh_id, + f_r0kh_id_len, + ftRRBseqTimeout); + if (!r0kh) + goto out; + + wpa_ft_rrb_r0kh_replenish(wpa_auth, r0kh, ftRRBseqTimeout); + *rkh_seq = r0kh->seq; + if (r0kh_out) + *r0kh_out = r0kh; + if (r0kh_wildcard_out) + *r0kh_wildcard_out = r0kh_wildcard; + } + + if (!to_r1kh) { + if (!r1kh) + r1kh = wpa_ft_rrb_add_r1kh(wpa_auth, r1kh_wildcard, + src_addr, f_r1kh_id, + ftRRBseqTimeout); + if (!r1kh) + goto out; + + wpa_ft_rrb_r1kh_replenish(wpa_auth, r1kh, ftRRBseqTimeout); + *rkh_seq = r1kh->seq; + if (r1kh_out) + *r1kh_out = r1kh; + if (r1kh_wildcard_out) + *r1kh_wildcard_out = r1kh_wildcard; } - pairwise = le_to_host16(f.pairwise); - wpa_printf(MSG_DEBUG, "FT: PMK-R1 push - R1KH-ID=" MACSTR " S1KH-ID=" - MACSTR " pairwise=0x%x", - MAC2STR(f.r1kh_id), MAC2STR(f.s1kh_id), pairwise); - wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1 push - PMK-R1", - f.pmk_r1, PMK_LEN); - wpa_hexdump(MSG_DEBUG, "FT: PMK-R1 push - PMKR1Name", - f.pmk_r1_name, WPA_PMK_NAME_LEN); + return 0; +out: + return -1; +} + - wpa_ft_store_pmk_r1(wpa_auth, f.s1kh_id, f.pmk_r1, f.pmk_r1_name, - pairwise); - os_memset(f.pmk_r1, 0, PMK_LEN); +static int wpa_ft_rrb_rx_seq_req(struct wpa_authenticator *wpa_auth, + const u8 *src_addr, + const u8 *enc, size_t enc_len, + const u8 *auth, size_t auth_len, + int no_defer) +{ + int ret = -1; + struct ft_rrb_seq f_seq; + const u8 *f_nonce, *f_r0kh_id, *f_r1kh_id; + size_t f_nonce_len, f_r0kh_id_len, f_r1kh_id_len; + struct ft_remote_seq *rkh_seq = NULL; + u8 *packet = NULL, *key = NULL; + size_t packet_len = 0, key_len = 0; + struct tlv_list seq_resp_auth[5]; + + wpa_printf(MSG_DEBUG, "FT: Received sequence number request"); + + if (wpa_ft_rrb_rx_seq(wpa_auth, src_addr, FT_PACKET_R0KH_R1KH_SEQ_REQ, + enc, enc_len, auth, auth_len, &rkh_seq, &key, + &key_len, NULL, NULL, NULL, NULL) < 0) + goto out; + + RRB_GET_AUTH(FT_RRB_NONCE, nonce, "seq request", FT_RRB_NONCE_LEN); + wpa_hexdump(MSG_DEBUG, "FT: seq request - nonce", f_nonce, f_nonce_len); + + RRB_GET_AUTH(FT_RRB_R0KH_ID, r0kh_id, "seq", -1); + RRB_GET_AUTH(FT_RRB_R1KH_ID, r1kh_id, "seq", FT_R1KH_ID_LEN); + + if (wpa_ft_new_seq(rkh_seq, &f_seq) < 0) { + wpa_printf(MSG_DEBUG, "FT: Failed to get seq num"); + goto out; + } + + seq_resp_auth[0].type = FT_RRB_NONCE; + seq_resp_auth[0].len = f_nonce_len; + seq_resp_auth[0].data = f_nonce; + seq_resp_auth[1].type = FT_RRB_SEQ; + seq_resp_auth[1].len = sizeof(f_seq); + seq_resp_auth[1].data = (u8 *) &f_seq; + seq_resp_auth[2].type = FT_RRB_R0KH_ID; + seq_resp_auth[2].len = f_r0kh_id_len; + seq_resp_auth[2].data = f_r0kh_id; + seq_resp_auth[3].type = FT_RRB_R1KH_ID; + seq_resp_auth[3].len = FT_R1KH_ID_LEN; + seq_resp_auth[3].data = f_r1kh_id; + seq_resp_auth[4].type = FT_RRB_LAST_EMPTY; + seq_resp_auth[4].len = 0; + seq_resp_auth[4].data = NULL; + + if (wpa_ft_rrb_build(key, key_len, NULL, NULL, seq_resp_auth, NULL, + wpa_auth->addr, FT_PACKET_R0KH_R1KH_SEQ_RESP, + &packet, &packet_len) < 0) + goto out; + + wpa_ft_rrb_oui_send(wpa_auth, src_addr, + FT_PACKET_R0KH_R1KH_SEQ_RESP, packet, + packet_len); + +out: + os_free(packet); + + return ret; +} + + +static int wpa_ft_rrb_rx_seq_resp(struct wpa_authenticator *wpa_auth, + const u8 *src_addr, + const u8 *enc, size_t enc_len, + const u8 *auth, size_t auth_len, + int no_defer) +{ + u8 *key = NULL; + size_t key_len = 0; + struct ft_remote_r0kh *r0kh = NULL, *r0kh_wildcard = NULL; + struct ft_remote_r1kh *r1kh = NULL, *r1kh_wildcard = NULL; + const u8 *f_nonce, *f_seq; + size_t f_nonce_len, f_seq_len; + struct ft_remote_seq *rkh_seq = NULL; + struct ft_remote_item *item; + struct os_reltime now, now_remote; + int seq_ret, found; + const struct ft_rrb_seq *msg_both; + u32 msg_dom, msg_seq; + + wpa_printf(MSG_DEBUG, "FT: Received sequence number response"); + + if (wpa_ft_rrb_rx_seq(wpa_auth, src_addr, FT_PACKET_R0KH_R1KH_SEQ_RESP, + enc, enc_len, auth, auth_len, &rkh_seq, &key, + &key_len, &r0kh, &r1kh, &r0kh_wildcard, + &r1kh_wildcard) < 0) + goto out; + + RRB_GET_AUTH(FT_RRB_NONCE, nonce, "seq response", FT_RRB_NONCE_LEN); + wpa_hexdump(MSG_DEBUG, "FT: seq response - nonce", f_nonce, + f_nonce_len); + + found = 0; + dl_list_for_each(item, &rkh_seq->rx.queue, struct ft_remote_item, + list) { + if (os_memcmp_const(f_nonce, item->nonce, + FT_RRB_NONCE_LEN) != 0 || + os_get_reltime(&now) < 0 || + os_reltime_expired(&now, &item->nonce_ts, ftRRBseqTimeout)) + continue; + + found = 1; + break; + } + if (!found) { + wpa_printf(MSG_DEBUG, "FT: seq response - bad nonce"); + goto out; + } + + if (r0kh) { + wpa_ft_rrb_r0kh_replenish(wpa_auth, r0kh, + wpa_auth->conf.rkh_pos_timeout); + if (r0kh_wildcard) + os_memcpy(r0kh->addr, src_addr, ETH_ALEN); + } + + if (r1kh) { + wpa_ft_rrb_r1kh_replenish(wpa_auth, r1kh, + wpa_auth->conf.rkh_pos_timeout); + if (r1kh_wildcard) + os_memcpy(r1kh->addr, src_addr, ETH_ALEN); + } + + seq_ret = wpa_ft_rrb_seq_chk(rkh_seq, src_addr, enc, enc_len, auth, + auth_len, "seq response", 1); + if (seq_ret == FT_RRB_SEQ_OK) { + wpa_printf(MSG_DEBUG, "FT: seq response - valid seq number"); + wpa_ft_rrb_seq_accept(wpa_auth, rkh_seq, src_addr, auth, + auth_len, "seq response"); + } else { + wpa_printf(MSG_DEBUG, "FT: seq response - reset seq number"); + + RRB_GET_AUTH(FT_RRB_SEQ, seq, "seq response", + sizeof(*msg_both)); + msg_both = (const struct ft_rrb_seq *) f_seq; + + msg_dom = le_to_host32(msg_both->dom); + msg_seq = le_to_host32(msg_both->seq); + now_remote.sec = le_to_host32(msg_both->ts); + now_remote.usec = 0; + + rkh_seq->rx.num_last = 2; + rkh_seq->rx.dom = msg_dom; + rkh_seq->rx.offsetidx = 0; + /* Accept some older, possibly cached packets as well */ + rkh_seq->rx.last[0] = msg_seq - FT_REMOTE_SEQ_BACKLOG - + dl_list_len(&rkh_seq->rx.queue); + rkh_seq->rx.last[1] = msg_seq; + + /* local time - offset = remote time + * <=> local time - remote time = offset */ + os_reltime_sub(&now, &now_remote, &rkh_seq->rx.time_offset); + } + + wpa_ft_rrb_seq_flush(wpa_auth, rkh_seq, 1); return 0; +out: + return -1; } @@ -1644,13 +4347,6 @@ int wpa_ft_rrb_rx(struct wpa_authenticator *wpa_auth, const u8 *src_addr, return -1; } - if (frame->packet_type == FT_PACKET_R0KH_R1KH_PULL) - return wpa_ft_rrb_rx_pull(wpa_auth, src_addr, data, data_len); - if (frame->packet_type == FT_PACKET_R0KH_R1KH_RESP) - return wpa_ft_rrb_rx_resp(wpa_auth, src_addr, data, data_len); - if (frame->packet_type == FT_PACKET_R0KH_R1KH_PUSH) - return wpa_ft_rrb_rx_push(wpa_auth, src_addr, data, data_len); - wpa_hexdump(MSG_MSGDUMP, "FT: RRB - FT Action frame", pos, alen); if (alen < 1 + 1 + 2 * ETH_ALEN) { @@ -1728,65 +4424,140 @@ int wpa_ft_rrb_rx(struct wpa_authenticator *wpa_auth, const u8 *src_addr, } -static void wpa_ft_generate_pmk_r1(struct wpa_authenticator *wpa_auth, - struct wpa_ft_pmk_r0_sa *pmk_r0, - struct ft_remote_r1kh *r1kh, - const u8 *s1kh_id, int pairwise) -{ - struct ft_r0kh_r1kh_push_frame frame, f; - struct os_time now; - const u8 *plain; - u8 *crypt; - - os_memset(&frame, 0, sizeof(frame)); - frame.frame_type = RSN_REMOTE_FRAME_TYPE_FT_RRB; - frame.packet_type = FT_PACKET_R0KH_R1KH_PUSH; - frame.data_length = host_to_le16(FT_R0KH_R1KH_PUSH_DATA_LEN); - os_memcpy(frame.ap_address, wpa_auth->addr, ETH_ALEN); - - /* aes_wrap() does not support inplace encryption, so use a temporary - * buffer for the data. */ - os_memcpy(f.r1kh_id, r1kh->id, FT_R1KH_ID_LEN); - os_memcpy(f.s1kh_id, s1kh_id, ETH_ALEN); - os_memcpy(f.pmk_r0_name, pmk_r0->pmk_r0_name, WPA_PMK_NAME_LEN); - wpa_derive_pmk_r1(pmk_r0->pmk_r0, pmk_r0->pmk_r0_name, r1kh->id, - s1kh_id, f.pmk_r1, f.pmk_r1_name); - wpa_printf(MSG_DEBUG, "FT: R1KH-ID " MACSTR, MAC2STR(r1kh->id)); - wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", f.pmk_r1, PMK_LEN); - wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", f.pmk_r1_name, - WPA_PMK_NAME_LEN); - os_get_time(&now); - WPA_PUT_LE32(f.timestamp, now.sec); - f.pairwise = host_to_le16(pairwise); - os_memset(f.pad, 0, sizeof(f.pad)); - plain = ((const u8 *) &f) + offsetof(struct ft_r0kh_r1kh_push_frame, - timestamp); - crypt = ((u8 *) &frame) + offsetof(struct ft_r0kh_r1kh_push_frame, - timestamp); - if (aes_wrap(r1kh->key, sizeof(r1kh->key), - (FT_R0KH_R1KH_PUSH_DATA_LEN + 7) / 8, - plain, crypt) < 0) +void wpa_ft_rrb_oui_rx(struct wpa_authenticator *wpa_auth, const u8 *src_addr, + const u8 *dst_addr, u8 oui_suffix, const u8 *data, + size_t data_len) +{ + const u8 *auth, *enc; + size_t alen, elen; + int no_defer = 0; + + wpa_printf(MSG_DEBUG, "FT: RRB-OUI received frame from remote AP " + MACSTR, MAC2STR(src_addr)); + wpa_printf(MSG_DEBUG, "FT: RRB-OUI frame - oui_suffix=%d", oui_suffix); + wpa_hexdump(MSG_MSGDUMP, "FT: RRB frame payload", data, data_len); + + if (is_multicast_ether_addr(src_addr)) { + wpa_printf(MSG_DEBUG, + "FT: RRB-OUI received frame from multicast address " + MACSTR, MAC2STR(src_addr)); + return; + } + + if (is_multicast_ether_addr(dst_addr)) { + wpa_printf(MSG_DEBUG, + "FT: RRB-OUI received frame from remote AP " MACSTR + " to multicast address " MACSTR, + MAC2STR(src_addr), MAC2STR(dst_addr)); + no_defer = 1; + } + + if (data_len < sizeof(u16)) { + wpa_printf(MSG_DEBUG, "FT: RRB-OUI frame too short"); return; + } + + alen = WPA_GET_LE16(data); + if (data_len < sizeof(u16) + alen) { + wpa_printf(MSG_DEBUG, "FT: RRB-OUI frame too short"); + return; + } + + auth = data + sizeof(u16); + wpa_hexdump(MSG_MSGDUMP, "FT: Authenticated payload", auth, alen); + enc = data + sizeof(u16) + alen; + elen = data_len - sizeof(u16) - alen; + wpa_hexdump(MSG_MSGDUMP, "FT: Encrypted payload", enc, elen); + + switch (oui_suffix) { + case FT_PACKET_R0KH_R1KH_PULL: + wpa_ft_rrb_rx_pull(wpa_auth, src_addr, enc, elen, auth, alen, + no_defer); + break; + case FT_PACKET_R0KH_R1KH_RESP: + wpa_ft_rrb_rx_resp(wpa_auth, src_addr, enc, elen, auth, alen, + no_defer); + break; + case FT_PACKET_R0KH_R1KH_PUSH: + wpa_ft_rrb_rx_push(wpa_auth, src_addr, enc, elen, auth, alen, + no_defer); + break; + case FT_PACKET_R0KH_R1KH_SEQ_REQ: + wpa_ft_rrb_rx_seq_req(wpa_auth, src_addr, enc, elen, auth, alen, + no_defer); + break; + case FT_PACKET_R0KH_R1KH_SEQ_RESP: + wpa_ft_rrb_rx_seq_resp(wpa_auth, src_addr, enc, elen, auth, + alen, no_defer); + break; + } +} - wpa_ft_rrb_send(wpa_auth, r1kh->addr, (u8 *) &frame, sizeof(frame)); + +static int wpa_ft_generate_pmk_r1(struct wpa_authenticator *wpa_auth, + struct wpa_ft_pmk_r0_sa *pmk_r0, + struct ft_remote_r1kh *r1kh, + const u8 *s1kh_id) +{ + u8 *packet; + size_t packet_len; + struct ft_rrb_seq f_seq; + struct tlv_list push[] = { + { .type = FT_RRB_S1KH_ID, .len = ETH_ALEN, + .data = s1kh_id }, + { .type = FT_RRB_PMK_R0_NAME, .len = WPA_PMK_NAME_LEN, + .data = pmk_r0->pmk_r0_name }, + { .type = FT_RRB_LAST_EMPTY, .len = 0, .data = NULL }, + }; + struct tlv_list push_auth[] = { + { .type = FT_RRB_SEQ, .len = sizeof(f_seq), + .data = (u8 *) &f_seq }, + { .type = FT_RRB_R0KH_ID, + .len = wpa_auth->conf.r0_key_holder_len, + .data = wpa_auth->conf.r0_key_holder }, + { .type = FT_RRB_R1KH_ID, .len = FT_R1KH_ID_LEN, + .data = r1kh->id }, + { .type = FT_RRB_LAST_EMPTY, .len = 0, .data = NULL }, + }; + + if (wpa_ft_new_seq(r1kh->seq, &f_seq) < 0) { + wpa_printf(MSG_DEBUG, "FT: Failed to get seq num"); + return -1; + } + + if (wpa_ft_rrb_build_r0(r1kh->key, sizeof(r1kh->key), push, pmk_r0, + r1kh->id, s1kh_id, push_auth, wpa_auth->addr, + FT_PACKET_R0KH_R1KH_PUSH, + &packet, &packet_len) < 0) + return -1; + + wpa_ft_rrb_oui_send(wpa_auth, r1kh->addr, FT_PACKET_R0KH_R1KH_PUSH, + packet, packet_len); + + os_free(packet); + return 0; } void wpa_ft_push_pmk_r1(struct wpa_authenticator *wpa_auth, const u8 *addr) { - struct wpa_ft_pmk_r0_sa *r0; + struct wpa_ft_pmk_cache *cache = wpa_auth->ft_pmk_cache; + struct wpa_ft_pmk_r0_sa *r0, *r0found = NULL; struct ft_remote_r1kh *r1kh; if (!wpa_auth->conf.pmk_r1_push) return; + if (!wpa_auth->conf.r1kh_list) + return; - r0 = wpa_auth->ft_pmk_cache->pmk_r0; - while (r0) { - if (os_memcmp(r0->spa, addr, ETH_ALEN) == 0) + dl_list_for_each(r0, &cache->pmk_r0, struct wpa_ft_pmk_r0_sa, list) { + if (os_memcmp(r0->spa, addr, ETH_ALEN) == 0) { + r0found = r0; break; - r0 = r0->next; + } } + r0 = r0found; if (r0 == NULL || r0->pmk_r1_pushed) return; r0->pmk_r1_pushed = 1; @@ -1794,11 +4565,14 @@ void wpa_ft_push_pmk_r1(struct wpa_authenticator *wpa_auth, const u8 *addr) wpa_printf(MSG_DEBUG, "FT: Deriving and pushing PMK-R1 keys to R1KHs " "for STA " MACSTR, MAC2STR(addr)); - r1kh = wpa_auth->conf.r1kh_list; - while (r1kh) { - wpa_ft_generate_pmk_r1(wpa_auth, r0, r1kh, addr, r0->pairwise); - r1kh = r1kh->next; + for (r1kh = *wpa_auth->conf.r1kh_list; r1kh; r1kh = r1kh->next) { + if (is_zero_ether_addr(r1kh->addr) || + is_zero_ether_addr(r1kh->id)) + continue; + if (wpa_ft_rrb_init_r1kh_seq(r1kh) < 0) + continue; + wpa_ft_generate_pmk_r1(wpa_auth, r0, r1kh, addr); } } -#endif /* CONFIG_IEEE80211R */ +#endif /* CONFIG_IEEE80211R_AP */ diff --git a/freebsd/contrib/wpa/src/ap/wpa_auth_i.h b/freebsd/contrib/wpa/src/ap/wpa_auth_i.h index 7fd8f05f..4babd0cb 100644 --- a/freebsd/contrib/wpa/src/ap/wpa_auth_i.h +++ b/freebsd/contrib/wpa/src/ap/wpa_auth_i.h @@ -9,24 +9,20 @@ #ifndef WPA_AUTH_I_H #define WPA_AUTH_I_H +#include "utils/list.h" + /* max(dot11RSNAConfigGroupUpdateCount,dot11RSNAConfigPairwiseUpdateCount) */ #define RSNA_MAX_EAPOL_RETRIES 4 struct wpa_group; -struct wpa_stsl_negotiation { - struct wpa_stsl_negotiation *next; - u8 initiator[ETH_ALEN]; - u8 peer[ETH_ALEN]; -}; - - struct wpa_state_machine { struct wpa_authenticator *wpa_auth; struct wpa_group *group; u8 addr[ETH_ALEN]; u8 p2p_dev_addr[ETH_ALEN]; + u16 auth_alg; enum { WPA_PTK_INITIALIZE, WPA_PTK_DISCONNECT, WPA_PTK_DISCONNECTED, @@ -48,8 +44,9 @@ struct wpa_state_machine { Boolean AuthenticationRequest; Boolean ReAuthenticationRequest; Boolean Disconnect; - int TimeoutCtr; - int GTimeoutCtr; + u16 disconnect_reason; /* specific reason code to use with Disconnect */ + u32 TimeoutCtr; + u32 GTimeoutCtr; Boolean TimeoutEvt; Boolean EAPOLKeyReceived; Boolean EAPOLKeyPairwise; @@ -62,6 +59,7 @@ struct wpa_state_machine { u8 alt_replay_counter[WPA_REPLAY_COUNTER_LEN]; u8 PMK[PMK_LEN_MAX]; unsigned int pmk_len; + u8 pmkid[PMKID_LEN]; /* valid if pmkid_set == 1 */ struct wpa_ptk PTK; Boolean PTK_valid; Boolean pairwise_set; @@ -89,11 +87,15 @@ struct wpa_state_machine { unsigned int rx_eapol_key_secure:1; unsigned int update_snonce:1; unsigned int alt_snonce_valid:1; -#ifdef CONFIG_IEEE80211R +#ifdef CONFIG_IEEE80211R_AP unsigned int ft_completed:1; unsigned int pmk_r1_name_valid:1; -#endif /* CONFIG_IEEE80211R */ +#endif /* CONFIG_IEEE80211R_AP */ unsigned int is_wnmsleep:1; + unsigned int pmkid_set:1; +#ifdef CONFIG_OCV + unsigned int ocv_enabled:1; +#endif /* CONFIG_OCV */ u8 req_replay_counter[WPA_REPLAY_COUNTER_LEN]; int req_replay_counter_used; @@ -113,9 +115,12 @@ struct wpa_state_machine { u32 dot11RSNAStatsTKIPLocalMICFailures; u32 dot11RSNAStatsTKIPRemoteMICFailures; -#ifdef CONFIG_IEEE80211R - u8 xxkey[PMK_LEN]; /* PSK or the second 256 bits of MSK */ +#ifdef CONFIG_IEEE80211R_AP + u8 xxkey[PMK_LEN_MAX]; /* PSK or the second 256 bits of MSK, or the + * first 384 bits of MSK */ size_t xxkey_len; + u8 pmk_r1[PMK_LEN_MAX]; + unsigned int pmk_r1_len; u8 pmk_r1_name[WPA_PMK_NAME_LEN]; /* PMKR1Name derived from FT Auth * Request */ u8 r0kh_id[FT_R0KH_ID_MAX_LEN]; /* R0KH-ID from FT Auth Request */ @@ -129,16 +134,34 @@ struct wpa_state_machine { const u8 *ies, size_t ies_len); void *ft_pending_cb_ctx; struct wpabuf *ft_pending_req_ies; - u8 ft_pending_pull_nonce[FT_R0KH_R1KH_PULL_NONCE_LEN]; + u8 ft_pending_pull_nonce[FT_RRB_NONCE_LEN]; u8 ft_pending_auth_transaction; u8 ft_pending_current_ap[ETH_ALEN]; -#endif /* CONFIG_IEEE80211R */ + int ft_pending_pull_left_retries; +#endif /* CONFIG_IEEE80211R_AP */ int pending_1_of_4_timeout; #ifdef CONFIG_P2P u8 ip_addr[4]; #endif /* CONFIG_P2P */ + +#ifdef CONFIG_FILS + u8 fils_key_auth_sta[FILS_MAX_KEY_AUTH_LEN]; + u8 fils_key_auth_ap[FILS_MAX_KEY_AUTH_LEN]; + size_t fils_key_auth_len; + unsigned int fils_completed:1; +#endif /* CONFIG_FILS */ + +#ifdef CONFIG_DPP2 + struct wpabuf *dpp_z; +#endif /* CONFIG_DPP2 */ + +#ifdef CONFIG_TESTING_OPTIONS + void (*eapol_status_cb)(void *ctx1, void *ctx2); + void *eapol_status_cb_ctx1; + void *eapol_status_cb_ctx2; +#endif /* CONFIG_TESTING_OPTIONS */ }; @@ -194,10 +217,9 @@ struct wpa_authenticator { unsigned int dot11RSNATKIPCounterMeasuresInvoked; unsigned int dot11RSNA4WayHandshakeFailures; - struct wpa_stsl_negotiation *stsl_negotiations; - struct wpa_auth_config conf; - struct wpa_auth_callbacks cb; + const struct wpa_auth_callbacks *cb; + void *cb_ctx; u8 *wpa_ie; size_t wpa_ie_len; @@ -213,6 +235,38 @@ struct wpa_authenticator { }; +#ifdef CONFIG_IEEE80211R_AP + +#define FT_REMOTE_SEQ_BACKLOG 16 +struct ft_remote_seq_rx { + u32 dom; + struct os_reltime time_offset; /* local time - offset = remote time */ + + /* accepted sequence numbers: (offset ... offset + 0x40000000] + * (except those in last) + * dropped sequence numbers: (offset - 0x40000000 ... offset] + * all others trigger SEQ_REQ message (except first message) + */ + u32 last[FT_REMOTE_SEQ_BACKLOG]; + unsigned int num_last; + u32 offsetidx; + + struct dl_list queue; /* send nonces + rrb msgs awaiting seq resp */ +}; + +struct ft_remote_seq_tx { + u32 dom; /* non zero if initialized */ + u32 seq; +}; + +struct ft_remote_seq { + struct ft_remote_seq_rx rx; + struct ft_remote_seq_tx tx; +}; + +#endif /* CONFIG_IEEE80211R_AP */ + + int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len, const u8 *pmkid); void wpa_auth_logger(struct wpa_authenticator *wpa_auth, const u8 *addr, @@ -231,32 +285,19 @@ int wpa_auth_for_each_auth(struct wpa_authenticator *wpa_auth, int (*cb)(struct wpa_authenticator *a, void *ctx), void *cb_ctx); -#ifdef CONFIG_PEERKEY -int wpa_stsl_remove(struct wpa_authenticator *wpa_auth, - struct wpa_stsl_negotiation *neg); -void wpa_smk_error(struct wpa_authenticator *wpa_auth, - struct wpa_state_machine *sm, - const u8 *key_data, size_t key_data_len); -void wpa_smk_m1(struct wpa_authenticator *wpa_auth, - struct wpa_state_machine *sm, struct wpa_eapol_key *key, - const u8 *key_data, size_t key_data_len); -void wpa_smk_m3(struct wpa_authenticator *wpa_auth, - struct wpa_state_machine *sm, struct wpa_eapol_key *key, - const u8 *key_data, size_t key_data_len); -#endif /* CONFIG_PEERKEY */ - -#ifdef CONFIG_IEEE80211R +#ifdef CONFIG_IEEE80211R_AP int wpa_write_mdie(struct wpa_auth_config *conf, u8 *buf, size_t len); -int wpa_write_ftie(struct wpa_auth_config *conf, const u8 *r0kh_id, - size_t r0kh_id_len, +int wpa_write_ftie(struct wpa_auth_config *conf, int use_sha384, + const u8 *r0kh_id, size_t r0kh_id_len, const u8 *anonce, const u8 *snonce, u8 *buf, size_t len, const u8 *subelem, size_t subelem_len); -int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, const u8 *pmk, - struct wpa_ptk *ptk); +int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, struct wpa_ptk *ptk); struct wpa_ft_pmk_cache * wpa_ft_pmk_cache_init(void); void wpa_ft_pmk_cache_deinit(struct wpa_ft_pmk_cache *cache); void wpa_ft_install_ptk(struct wpa_state_machine *sm); -#endif /* CONFIG_IEEE80211R */ +int wpa_ft_store_pmk_fils(struct wpa_state_machine *sm, const u8 *pmk_r0, + const u8 *pmk_r0_name); +#endif /* CONFIG_IEEE80211R_AP */ #endif /* WPA_AUTH_I_H */ diff --git a/freebsd/contrib/wpa/src/ap/wpa_auth_ie.h b/freebsd/contrib/wpa/src/ap/wpa_auth_ie.h index d2067ba3..a38b206f 100644 --- a/freebsd/contrib/wpa/src/ap/wpa_auth_ie.h +++ b/freebsd/contrib/wpa/src/ap/wpa_auth_ie.h @@ -19,30 +19,24 @@ struct wpa_eapol_ie_parse { size_t gtk_len; const u8 *mac_addr; size_t mac_addr_len; -#ifdef CONFIG_PEERKEY - const u8 *smk; - size_t smk_len; - const u8 *nonce; - size_t nonce_len; - const u8 *lifetime; - size_t lifetime_len; - const u8 *error; - size_t error_len; -#endif /* CONFIG_PEERKEY */ #ifdef CONFIG_IEEE80211W const u8 *igtk; size_t igtk_len; #endif /* CONFIG_IEEE80211W */ -#ifdef CONFIG_IEEE80211R +#ifdef CONFIG_IEEE80211R_AP const u8 *mdie; size_t mdie_len; const u8 *ftie; size_t ftie_len; -#endif /* CONFIG_IEEE80211R */ +#endif /* CONFIG_IEEE80211R_AP */ #ifdef CONFIG_P2P const u8 *ip_addr_req; const u8 *ip_addr_alloc; #endif /* CONFIG_P2P */ +#ifdef CONFIG_OCV + const u8 *oci; + size_t oci_len; +#endif /* CONFIG_OCV */ const u8 *osen; size_t osen_len; diff --git a/freebsd/contrib/wpa/src/common/ctrl_iface_common.c b/freebsd/contrib/wpa/src/common/ctrl_iface_common.c index 72f539c4..265eda35 100644 --- a/freebsd/contrib/wpa/src/common/ctrl_iface_common.c +++ b/freebsd/contrib/wpa/src/common/ctrl_iface_common.c @@ -115,17 +115,53 @@ void sockaddr_print(int level, const char *msg, struct sockaddr_storage *sock, } +static int ctrl_set_events(struct wpa_ctrl_dst *dst, const char *input) +{ + const char *value; + int val; + + if (!input) + return 0; + + value = os_strchr(input, '='); + if (!value) + return -1; + value++; + val = atoi(value); + if (val < 0 || val > 1) + return -1; + + if (str_starts(input, "probe_rx_events=")) { + if (val) + dst->events |= WPA_EVENT_RX_PROBE_REQUEST; + else + dst->events &= ~WPA_EVENT_RX_PROBE_REQUEST; + } + + return 0; +} + + int ctrl_iface_attach(struct dl_list *ctrl_dst, struct sockaddr_storage *from, - socklen_t fromlen) + socklen_t fromlen, const char *input) { struct wpa_ctrl_dst *dst; + /* Update event registration if already attached */ + dl_list_for_each(dst, ctrl_dst, struct wpa_ctrl_dst, list) { + if (!sockaddr_compare(from, fromlen, + &dst->addr, dst->addrlen)) + return ctrl_set_events(dst, input); + } + + /* New attachment */ dst = os_zalloc(sizeof(*dst)); if (dst == NULL) return -1; os_memcpy(&dst->addr, from, fromlen); dst->addrlen = fromlen; dst->debug_level = MSG_INFO; + ctrl_set_events(dst, input); dl_list_add(ctrl_dst, &dst->list); sockaddr_print(MSG_DEBUG, "CTRL_IFACE monitor attached", from, fromlen); diff --git a/freebsd/contrib/wpa/src/common/ctrl_iface_common.h b/freebsd/contrib/wpa/src/common/ctrl_iface_common.h index 0b6e3e74..85e258e9 100644 --- a/freebsd/contrib/wpa/src/common/ctrl_iface_common.h +++ b/freebsd/contrib/wpa/src/common/ctrl_iface_common.h @@ -11,6 +11,9 @@ #include "utils/list.h" +/* Events enable bits (wpa_ctrl_dst::events) */ +#define WPA_EVENT_RX_PROBE_REQUEST BIT(0) + /** * struct wpa_ctrl_dst - Data structure of control interface monitors * @@ -23,13 +26,14 @@ struct wpa_ctrl_dst { socklen_t addrlen; int debug_level; int errors; + u32 events; /* WPA_EVENT_* bitmap */ }; void sockaddr_print(int level, const char *msg, struct sockaddr_storage *sock, socklen_t socklen); int ctrl_iface_attach(struct dl_list *ctrl_dst, struct sockaddr_storage *from, - socklen_t fromlen); + socklen_t fromlen, const char *input); int ctrl_iface_detach(struct dl_list *ctrl_dst, struct sockaddr_storage *from, socklen_t fromlen); int ctrl_iface_level(struct dl_list *ctrl_dst, struct sockaddr_storage *from, diff --git a/freebsd/contrib/wpa/src/common/defs.h b/freebsd/contrib/wpa/src/common/defs.h index 4f567945..4faf1c86 100644 --- a/freebsd/contrib/wpa/src/common/defs.h +++ b/freebsd/contrib/wpa/src/common/defs.h @@ -1,6 +1,6 @@ /* * WPA Supplicant - Common definitions - * Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi> + * Copyright (c) 2004-2018, Jouni Malinen <j@w1.fi> * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -51,16 +51,35 @@ typedef enum { FALSE = 0, TRUE = 1 } Boolean; #define WPA_KEY_MGMT_OSEN BIT(15) #define WPA_KEY_MGMT_IEEE8021X_SUITE_B BIT(16) #define WPA_KEY_MGMT_IEEE8021X_SUITE_B_192 BIT(17) +#define WPA_KEY_MGMT_FILS_SHA256 BIT(18) +#define WPA_KEY_MGMT_FILS_SHA384 BIT(19) +#define WPA_KEY_MGMT_FT_FILS_SHA256 BIT(20) +#define WPA_KEY_MGMT_FT_FILS_SHA384 BIT(21) +#define WPA_KEY_MGMT_OWE BIT(22) +#define WPA_KEY_MGMT_DPP BIT(23) +#define WPA_KEY_MGMT_FT_IEEE8021X_SHA384 BIT(24) + +#define WPA_KEY_MGMT_FT (WPA_KEY_MGMT_FT_PSK | \ + WPA_KEY_MGMT_FT_IEEE8021X | \ + WPA_KEY_MGMT_FT_IEEE8021X_SHA384 | \ + WPA_KEY_MGMT_FT_SAE | \ + WPA_KEY_MGMT_FT_FILS_SHA256 | \ + WPA_KEY_MGMT_FT_FILS_SHA384) static inline int wpa_key_mgmt_wpa_ieee8021x(int akm) { return !!(akm & (WPA_KEY_MGMT_IEEE8021X | WPA_KEY_MGMT_FT_IEEE8021X | + WPA_KEY_MGMT_FT_IEEE8021X_SHA384 | WPA_KEY_MGMT_CCKM | WPA_KEY_MGMT_OSEN | WPA_KEY_MGMT_IEEE8021X_SHA256 | WPA_KEY_MGMT_IEEE8021X_SUITE_B | - WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)); + WPA_KEY_MGMT_IEEE8021X_SUITE_B_192 | + WPA_KEY_MGMT_FILS_SHA256 | + WPA_KEY_MGMT_FILS_SHA384 | + WPA_KEY_MGMT_FT_FILS_SHA256 | + WPA_KEY_MGMT_FT_FILS_SHA384)); } static inline int wpa_key_mgmt_wpa_psk(int akm) @@ -74,9 +93,19 @@ static inline int wpa_key_mgmt_wpa_psk(int akm) static inline int wpa_key_mgmt_ft(int akm) { - return !!(akm & (WPA_KEY_MGMT_FT_PSK | - WPA_KEY_MGMT_FT_IEEE8021X | - WPA_KEY_MGMT_FT_SAE)); + return !!(akm & WPA_KEY_MGMT_FT); +} + +static inline int wpa_key_mgmt_only_ft(int akm) +{ + int ft = wpa_key_mgmt_ft(akm); + akm &= ~WPA_KEY_MGMT_FT; + return ft && !akm; +} + +static inline int wpa_key_mgmt_ft_psk(int akm) +{ + return !!(akm & WPA_KEY_MGMT_FT_PSK); } static inline int wpa_key_mgmt_sae(int akm) @@ -85,17 +114,32 @@ static inline int wpa_key_mgmt_sae(int akm) WPA_KEY_MGMT_FT_SAE)); } +static inline int wpa_key_mgmt_fils(int akm) +{ + return !!(akm & (WPA_KEY_MGMT_FILS_SHA256 | + WPA_KEY_MGMT_FILS_SHA384 | + WPA_KEY_MGMT_FT_FILS_SHA256 | + WPA_KEY_MGMT_FT_FILS_SHA384)); +} + static inline int wpa_key_mgmt_sha256(int akm) { return !!(akm & (WPA_KEY_MGMT_PSK_SHA256 | WPA_KEY_MGMT_IEEE8021X_SHA256 | + WPA_KEY_MGMT_SAE | + WPA_KEY_MGMT_FT_SAE | WPA_KEY_MGMT_OSEN | - WPA_KEY_MGMT_IEEE8021X_SUITE_B)); + WPA_KEY_MGMT_IEEE8021X_SUITE_B | + WPA_KEY_MGMT_FILS_SHA256 | + WPA_KEY_MGMT_FT_FILS_SHA256)); } static inline int wpa_key_mgmt_sha384(int akm) { - return !!(akm & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192); + return !!(akm & (WPA_KEY_MGMT_IEEE8021X_SUITE_B_192 | + WPA_KEY_MGMT_FT_IEEE8021X_SHA384 | + WPA_KEY_MGMT_FILS_SHA384 | + WPA_KEY_MGMT_FT_FILS_SHA384)); } static inline int wpa_key_mgmt_suite_b(int akm) @@ -108,7 +152,10 @@ static inline int wpa_key_mgmt_wpa(int akm) { return wpa_key_mgmt_wpa_ieee8021x(akm) || wpa_key_mgmt_wpa_psk(akm) || - wpa_key_mgmt_sae(akm); + wpa_key_mgmt_fils(akm) || + wpa_key_mgmt_sae(akm) || + akm == WPA_KEY_MGMT_OWE || + akm == WPA_KEY_MGMT_DPP; } static inline int wpa_key_mgmt_wpa_any(int akm) @@ -132,7 +179,13 @@ static inline int wpa_key_mgmt_cckm(int akm) #define WPA_AUTH_ALG_LEAP BIT(2) #define WPA_AUTH_ALG_FT BIT(3) #define WPA_AUTH_ALG_SAE BIT(4) +#define WPA_AUTH_ALG_FILS BIT(5) +#define WPA_AUTH_ALG_FILS_SK_PFS BIT(6) +static inline int wpa_auth_alg_fils(int alg) +{ + return !!(alg & (WPA_AUTH_ALG_FILS | WPA_AUTH_ALG_FILS_SK_PFS)); +} enum wpa_alg { WPA_ALG_NONE, @@ -341,4 +394,29 @@ enum wpa_radio_work_band { BAND_60_GHZ = BIT(2), }; +enum beacon_rate_type { + BEACON_RATE_LEGACY, + BEACON_RATE_HT, + BEACON_RATE_VHT +}; + +enum eap_proxy_sim_state { + SIM_STATE_ERROR, +}; + +#define OCE_STA BIT(0) +#define OCE_STA_CFON BIT(1) +#define OCE_AP BIT(2) + +/* enum chan_width - Channel width definitions */ +enum chan_width { + CHAN_WIDTH_20_NOHT, + CHAN_WIDTH_20, + CHAN_WIDTH_40, + CHAN_WIDTH_80, + CHAN_WIDTH_80P80, + CHAN_WIDTH_160, + CHAN_WIDTH_UNKNOWN +}; + #endif /* DEFS_H */ diff --git a/freebsd/contrib/wpa/src/common/dpp.h b/freebsd/contrib/wpa/src/common/dpp.h new file mode 100644 index 00000000..5a6d8cc7 --- /dev/null +++ b/freebsd/contrib/wpa/src/common/dpp.h @@ -0,0 +1,505 @@ +/* + * DPP functionality shared between hostapd and wpa_supplicant + * Copyright (c) 2017, Qualcomm Atheros, Inc. + * Copyright (c) 2018-2019, The Linux Foundation + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef DPP_H +#define DPP_H + +#ifdef CONFIG_DPP +#include <openssl/x509.h> + +#include "utils/list.h" +#include "common/wpa_common.h" +#include "crypto/sha256.h" + +struct crypto_ecdh; +struct dpp_global; + +#define DPP_HDR_LEN (4 + 2) /* OUI, OUI Type, Crypto Suite, DPP frame type */ + +enum dpp_public_action_frame_type { + DPP_PA_AUTHENTICATION_REQ = 0, + DPP_PA_AUTHENTICATION_RESP = 1, + DPP_PA_AUTHENTICATION_CONF = 2, + DPP_PA_PEER_DISCOVERY_REQ = 5, + DPP_PA_PEER_DISCOVERY_RESP = 6, + DPP_PA_PKEX_EXCHANGE_REQ = 7, + DPP_PA_PKEX_EXCHANGE_RESP = 8, + DPP_PA_PKEX_COMMIT_REVEAL_REQ = 9, + DPP_PA_PKEX_COMMIT_REVEAL_RESP = 10, + DPP_PA_CONFIGURATION_RESULT = 11, +}; + +enum dpp_attribute_id { + DPP_ATTR_STATUS = 0x1000, + DPP_ATTR_I_BOOTSTRAP_KEY_HASH = 0x1001, + DPP_ATTR_R_BOOTSTRAP_KEY_HASH = 0x1002, + DPP_ATTR_I_PROTOCOL_KEY = 0x1003, + DPP_ATTR_WRAPPED_DATA = 0x1004, + DPP_ATTR_I_NONCE = 0x1005, + DPP_ATTR_I_CAPABILITIES = 0x1006, + DPP_ATTR_R_NONCE = 0x1007, + DPP_ATTR_R_CAPABILITIES = 0x1008, + DPP_ATTR_R_PROTOCOL_KEY = 0x1009, + DPP_ATTR_I_AUTH_TAG = 0x100A, + DPP_ATTR_R_AUTH_TAG = 0x100B, + DPP_ATTR_CONFIG_OBJ = 0x100C, + DPP_ATTR_CONNECTOR = 0x100D, + DPP_ATTR_CONFIG_ATTR_OBJ = 0x100E, + DPP_ATTR_BOOTSTRAP_KEY = 0x100F, + DPP_ATTR_OWN_NET_NK_HASH = 0x1011, + DPP_ATTR_FINITE_CYCLIC_GROUP = 0x1012, + DPP_ATTR_ENCRYPTED_KEY = 0x1013, + DPP_ATTR_ENROLLEE_NONCE = 0x1014, + DPP_ATTR_CODE_IDENTIFIER = 0x1015, + DPP_ATTR_TRANSACTION_ID = 0x1016, + DPP_ATTR_BOOTSTRAP_INFO = 0x1017, + DPP_ATTR_CHANNEL = 0x1018, + DPP_ATTR_PROTOCOL_VERSION = 0x1019, + DPP_ATTR_ENVELOPED_DATA = 0x101A, +}; + +enum dpp_status_error { + DPP_STATUS_OK = 0, + DPP_STATUS_NOT_COMPATIBLE = 1, + DPP_STATUS_AUTH_FAILURE = 2, + DPP_STATUS_UNWRAP_FAILURE = 3, + DPP_STATUS_BAD_GROUP = 4, + DPP_STATUS_CONFIGURE_FAILURE = 5, + DPP_STATUS_RESPONSE_PENDING = 6, + DPP_STATUS_INVALID_CONNECTOR = 7, + DPP_STATUS_NO_MATCH = 8, + DPP_STATUS_CONFIG_REJECTED = 9, +}; + +#define DPP_CAPAB_ENROLLEE BIT(0) +#define DPP_CAPAB_CONFIGURATOR BIT(1) +#define DPP_CAPAB_ROLE_MASK (BIT(0) | BIT(1)) + +#define DPP_BOOTSTRAP_MAX_FREQ 30 +#define DPP_MAX_NONCE_LEN 32 +#define DPP_MAX_HASH_LEN 64 +#define DPP_MAX_SHARED_SECRET_LEN 66 + +struct dpp_curve_params { + const char *name; + size_t hash_len; + size_t aes_siv_key_len; + size_t nonce_len; + size_t prime_len; + const char *jwk_crv; + u16 ike_group; + const char *jws_alg; +}; + +enum dpp_bootstrap_type { + DPP_BOOTSTRAP_QR_CODE, + DPP_BOOTSTRAP_PKEX, +}; + +struct dpp_bootstrap_info { + struct dl_list list; + unsigned int id; + enum dpp_bootstrap_type type; + char *uri; + u8 mac_addr[ETH_ALEN]; + char *info; + unsigned int freq[DPP_BOOTSTRAP_MAX_FREQ]; + unsigned int num_freq; + int own; + EVP_PKEY *pubkey; + u8 pubkey_hash[SHA256_MAC_LEN]; + const struct dpp_curve_params *curve; + unsigned int pkex_t; /* number of failures before dpp_pkex + * instantiation */ +}; + +#define PKEX_COUNTER_T_LIMIT 5 + +struct dpp_pkex { + void *msg_ctx; + unsigned int initiator:1; + unsigned int exchange_done:1; + unsigned int failed:1; + struct dpp_bootstrap_info *own_bi; + u8 own_mac[ETH_ALEN]; + u8 peer_mac[ETH_ALEN]; + char *identifier; + char *code; + EVP_PKEY *x; + EVP_PKEY *y; + u8 Mx[DPP_MAX_SHARED_SECRET_LEN]; + u8 Nx[DPP_MAX_SHARED_SECRET_LEN]; + u8 z[DPP_MAX_HASH_LEN]; + EVP_PKEY *peer_bootstrap_key; + struct wpabuf *exchange_req; + struct wpabuf *exchange_resp; + unsigned int t; /* number of failures on code use */ + unsigned int exch_req_wait_time; + unsigned int exch_req_tries; + unsigned int freq; +}; + +enum dpp_akm { + DPP_AKM_UNKNOWN, + DPP_AKM_DPP, + DPP_AKM_PSK, + DPP_AKM_SAE, + DPP_AKM_PSK_SAE, + DPP_AKM_SAE_DPP, + DPP_AKM_PSK_SAE_DPP, +}; + +struct dpp_configuration { + u8 ssid[32]; + size_t ssid_len; + enum dpp_akm akm; + + /* For DPP configuration (connector) */ + os_time_t netaccesskey_expiry; + + /* TODO: groups */ + char *group_id; + + /* For legacy configuration */ + char *passphrase; + u8 psk[32]; + int psk_set; +}; + +struct dpp_authentication { + void *msg_ctx; + u8 peer_version; + const struct dpp_curve_params *curve; + struct dpp_bootstrap_info *peer_bi; + struct dpp_bootstrap_info *own_bi; + struct dpp_bootstrap_info *tmp_own_bi; + u8 waiting_pubkey_hash[SHA256_MAC_LEN]; + int response_pending; + enum dpp_status_error auth_resp_status; + enum dpp_status_error conf_resp_status; + u8 peer_mac_addr[ETH_ALEN]; + u8 i_nonce[DPP_MAX_NONCE_LEN]; + u8 r_nonce[DPP_MAX_NONCE_LEN]; + u8 e_nonce[DPP_MAX_NONCE_LEN]; + u8 i_capab; + u8 r_capab; + EVP_PKEY *own_protocol_key; + EVP_PKEY *peer_protocol_key; + struct wpabuf *req_msg; + struct wpabuf *resp_msg; + /* Intersection of possible frequencies for initiating DPP + * Authentication exchange */ + unsigned int freq[DPP_BOOTSTRAP_MAX_FREQ]; + unsigned int num_freq, freq_idx; + unsigned int curr_freq; + unsigned int neg_freq; + unsigned int num_freq_iters; + size_t secret_len; + u8 Mx[DPP_MAX_SHARED_SECRET_LEN]; + size_t Mx_len; + u8 Nx[DPP_MAX_SHARED_SECRET_LEN]; + size_t Nx_len; + u8 Lx[DPP_MAX_SHARED_SECRET_LEN]; + size_t Lx_len; + u8 k1[DPP_MAX_HASH_LEN]; + u8 k2[DPP_MAX_HASH_LEN]; + u8 ke[DPP_MAX_HASH_LEN]; + int initiator; + int waiting_auth_resp; + int waiting_auth_conf; + int auth_req_ack; + unsigned int auth_resp_tries; + u8 allowed_roles; + int configurator; + int remove_on_tx_status; + int connect_on_tx_status; + int waiting_conf_result; + int auth_success; + struct wpabuf *conf_req; + const struct wpabuf *conf_resp; /* owned by GAS server */ + struct dpp_configuration *conf_ap; + struct dpp_configuration *conf_sta; + struct dpp_configurator *conf; + char *connector; /* received signedConnector */ + u8 ssid[SSID_MAX_LEN]; + u8 ssid_len; + char passphrase[64]; + u8 psk[PMK_LEN]; + int psk_set; + enum dpp_akm akm; + struct wpabuf *net_access_key; + os_time_t net_access_key_expiry; + struct wpabuf *c_sign_key; +#ifdef CONFIG_TESTING_OPTIONS + char *config_obj_override; + char *discovery_override; + char *groups_override; + unsigned int ignore_netaccesskey_mismatch:1; +#endif /* CONFIG_TESTING_OPTIONS */ +}; + +struct dpp_configurator { + struct dl_list list; + unsigned int id; + int own; + EVP_PKEY *csign; + char *kid; + const struct dpp_curve_params *curve; +}; + +struct dpp_introduction { + u8 pmkid[PMKID_LEN]; + u8 pmk[PMK_LEN_MAX]; + size_t pmk_len; +}; + +#ifdef CONFIG_TESTING_OPTIONS +enum dpp_test_behavior { + DPP_TEST_DISABLED = 0, + DPP_TEST_AFTER_WRAPPED_DATA_AUTH_REQ = 1, + DPP_TEST_AFTER_WRAPPED_DATA_AUTH_RESP = 2, + DPP_TEST_AFTER_WRAPPED_DATA_AUTH_CONF = 3, + DPP_TEST_AFTER_WRAPPED_DATA_PKEX_CR_REQ = 4, + DPP_TEST_AFTER_WRAPPED_DATA_PKEX_CR_RESP = 5, + DPP_TEST_AFTER_WRAPPED_DATA_CONF_REQ = 6, + DPP_TEST_AFTER_WRAPPED_DATA_CONF_RESP = 7, + DPP_TEST_ZERO_I_CAPAB = 8, + DPP_TEST_ZERO_R_CAPAB = 9, + DPP_TEST_NO_R_BOOTSTRAP_KEY_HASH_AUTH_REQ = 10, + DPP_TEST_NO_I_BOOTSTRAP_KEY_HASH_AUTH_REQ = 11, + DPP_TEST_NO_I_PROTO_KEY_AUTH_REQ = 12, + DPP_TEST_NO_I_NONCE_AUTH_REQ = 13, + DPP_TEST_NO_I_CAPAB_AUTH_REQ = 14, + DPP_TEST_NO_WRAPPED_DATA_AUTH_REQ = 15, + DPP_TEST_NO_STATUS_AUTH_RESP = 16, + DPP_TEST_NO_R_BOOTSTRAP_KEY_HASH_AUTH_RESP = 17, + DPP_TEST_NO_I_BOOTSTRAP_KEY_HASH_AUTH_RESP = 18, + DPP_TEST_NO_R_PROTO_KEY_AUTH_RESP = 19, + DPP_TEST_NO_R_NONCE_AUTH_RESP = 20, + DPP_TEST_NO_I_NONCE_AUTH_RESP = 21, + DPP_TEST_NO_R_CAPAB_AUTH_RESP = 22, + DPP_TEST_NO_R_AUTH_AUTH_RESP = 23, + DPP_TEST_NO_WRAPPED_DATA_AUTH_RESP = 24, + DPP_TEST_NO_STATUS_AUTH_CONF = 25, + DPP_TEST_NO_R_BOOTSTRAP_KEY_HASH_AUTH_CONF = 26, + DPP_TEST_NO_I_BOOTSTRAP_KEY_HASH_AUTH_CONF = 27, + DPP_TEST_NO_I_AUTH_AUTH_CONF = 28, + DPP_TEST_NO_WRAPPED_DATA_AUTH_CONF = 29, + DPP_TEST_I_NONCE_MISMATCH_AUTH_RESP = 30, + DPP_TEST_INCOMPATIBLE_R_CAPAB_AUTH_RESP = 31, + DPP_TEST_R_AUTH_MISMATCH_AUTH_RESP = 32, + DPP_TEST_I_AUTH_MISMATCH_AUTH_CONF = 33, + DPP_TEST_NO_FINITE_CYCLIC_GROUP_PKEX_EXCHANGE_REQ = 34, + DPP_TEST_NO_ENCRYPTED_KEY_PKEX_EXCHANGE_REQ = 35, + DPP_TEST_NO_STATUS_PKEX_EXCHANGE_RESP = 36, + DPP_TEST_NO_ENCRYPTED_KEY_PKEX_EXCHANGE_RESP = 37, + DPP_TEST_NO_BOOTSTRAP_KEY_PKEX_CR_REQ = 38, + DPP_TEST_NO_I_AUTH_TAG_PKEX_CR_REQ = 39, + DPP_TEST_NO_WRAPPED_DATA_PKEX_CR_REQ = 40, + DPP_TEST_NO_BOOTSTRAP_KEY_PKEX_CR_RESP = 41, + DPP_TEST_NO_R_AUTH_TAG_PKEX_CR_RESP = 42, + DPP_TEST_NO_WRAPPED_DATA_PKEX_CR_RESP = 43, + DPP_TEST_INVALID_ENCRYPTED_KEY_PKEX_EXCHANGE_REQ = 44, + DPP_TEST_INVALID_ENCRYPTED_KEY_PKEX_EXCHANGE_RESP = 45, + DPP_TEST_INVALID_STATUS_PKEX_EXCHANGE_RESP = 46, + DPP_TEST_INVALID_BOOTSTRAP_KEY_PKEX_CR_REQ = 47, + DPP_TEST_INVALID_BOOTSTRAP_KEY_PKEX_CR_RESP = 48, + DPP_TEST_I_AUTH_TAG_MISMATCH_PKEX_CR_REQ = 49, + DPP_TEST_R_AUTH_TAG_MISMATCH_PKEX_CR_RESP = 50, + DPP_TEST_NO_E_NONCE_CONF_REQ = 51, + DPP_TEST_NO_CONFIG_ATTR_OBJ_CONF_REQ = 52, + DPP_TEST_NO_WRAPPED_DATA_CONF_REQ = 53, + DPP_TEST_NO_E_NONCE_CONF_RESP = 54, + DPP_TEST_NO_CONFIG_OBJ_CONF_RESP = 55, + DPP_TEST_NO_STATUS_CONF_RESP = 56, + DPP_TEST_NO_WRAPPED_DATA_CONF_RESP = 57, + DPP_TEST_INVALID_STATUS_CONF_RESP = 58, + DPP_TEST_E_NONCE_MISMATCH_CONF_RESP = 59, + DPP_TEST_NO_TRANSACTION_ID_PEER_DISC_REQ = 60, + DPP_TEST_NO_CONNECTOR_PEER_DISC_REQ = 61, + DPP_TEST_NO_TRANSACTION_ID_PEER_DISC_RESP = 62, + DPP_TEST_NO_STATUS_PEER_DISC_RESP = 63, + DPP_TEST_NO_CONNECTOR_PEER_DISC_RESP = 64, + DPP_TEST_AUTH_RESP_IN_PLACE_OF_CONF = 65, + DPP_TEST_INVALID_I_PROTO_KEY_AUTH_REQ = 66, + DPP_TEST_INVALID_R_PROTO_KEY_AUTH_RESP = 67, + DPP_TEST_INVALID_R_BOOTSTRAP_KEY_HASH_AUTH_REQ = 68, + DPP_TEST_INVALID_I_BOOTSTRAP_KEY_HASH_AUTH_REQ = 69, + DPP_TEST_INVALID_R_BOOTSTRAP_KEY_HASH_AUTH_RESP = 70, + DPP_TEST_INVALID_I_BOOTSTRAP_KEY_HASH_AUTH_RESP = 71, + DPP_TEST_INVALID_R_BOOTSTRAP_KEY_HASH_AUTH_CONF = 72, + DPP_TEST_INVALID_I_BOOTSTRAP_KEY_HASH_AUTH_CONF = 73, + DPP_TEST_INVALID_STATUS_AUTH_RESP = 74, + DPP_TEST_INVALID_STATUS_AUTH_CONF = 75, + DPP_TEST_INVALID_CONFIG_ATTR_OBJ_CONF_REQ = 76, + DPP_TEST_INVALID_TRANSACTION_ID_PEER_DISC_RESP = 77, + DPP_TEST_INVALID_STATUS_PEER_DISC_RESP = 78, + DPP_TEST_INVALID_CONNECTOR_PEER_DISC_RESP = 79, + DPP_TEST_INVALID_CONNECTOR_PEER_DISC_REQ = 80, + DPP_TEST_INVALID_I_NONCE_AUTH_REQ = 81, + DPP_TEST_INVALID_TRANSACTION_ID_PEER_DISC_REQ = 82, + DPP_TEST_INVALID_E_NONCE_CONF_REQ = 83, + DPP_TEST_STOP_AT_PKEX_EXCHANGE_RESP = 84, + DPP_TEST_STOP_AT_PKEX_CR_REQ = 85, + DPP_TEST_STOP_AT_PKEX_CR_RESP = 86, + DPP_TEST_STOP_AT_AUTH_REQ = 87, + DPP_TEST_STOP_AT_AUTH_RESP = 88, + DPP_TEST_STOP_AT_AUTH_CONF = 89, + DPP_TEST_STOP_AT_CONF_REQ = 90, + DPP_TEST_REJECT_CONFIG = 91, +}; + +extern enum dpp_test_behavior dpp_test; +extern u8 dpp_pkex_own_mac_override[ETH_ALEN]; +extern u8 dpp_pkex_peer_mac_override[ETH_ALEN]; +extern u8 dpp_pkex_ephemeral_key_override[600]; +extern size_t dpp_pkex_ephemeral_key_override_len; +extern u8 dpp_protocol_key_override[600]; +extern size_t dpp_protocol_key_override_len; +extern u8 dpp_nonce_override[DPP_MAX_NONCE_LEN]; +extern size_t dpp_nonce_override_len; +#endif /* CONFIG_TESTING_OPTIONS */ + +void dpp_bootstrap_info_free(struct dpp_bootstrap_info *info); +const char * dpp_bootstrap_type_txt(enum dpp_bootstrap_type type); +int dpp_bootstrap_key_hash(struct dpp_bootstrap_info *bi); +int dpp_parse_uri_chan_list(struct dpp_bootstrap_info *bi, + const char *chan_list); +int dpp_parse_uri_mac(struct dpp_bootstrap_info *bi, const char *mac); +int dpp_parse_uri_info(struct dpp_bootstrap_info *bi, const char *info); +struct dpp_bootstrap_info * dpp_parse_qr_code(const char *uri); +char * dpp_keygen(struct dpp_bootstrap_info *bi, const char *curve, + const u8 *privkey, size_t privkey_len); +struct hostapd_hw_modes; +struct dpp_authentication * dpp_auth_init(void *msg_ctx, + struct dpp_bootstrap_info *peer_bi, + struct dpp_bootstrap_info *own_bi, + u8 dpp_allowed_roles, + unsigned int neg_freq, + struct hostapd_hw_modes *own_modes, + u16 num_modes); +struct dpp_authentication * +dpp_auth_req_rx(void *msg_ctx, u8 dpp_allowed_roles, int qr_mutual, + struct dpp_bootstrap_info *peer_bi, + struct dpp_bootstrap_info *own_bi, + unsigned int freq, const u8 *hdr, const u8 *attr_start, + size_t attr_len); +struct wpabuf * +dpp_auth_resp_rx(struct dpp_authentication *auth, const u8 *hdr, + const u8 *attr_start, size_t attr_len); +struct wpabuf * dpp_build_conf_req(struct dpp_authentication *auth, + const char *json); +int dpp_auth_conf_rx(struct dpp_authentication *auth, const u8 *hdr, + const u8 *attr_start, size_t attr_len); +int dpp_notify_new_qr_code(struct dpp_authentication *auth, + struct dpp_bootstrap_info *peer_bi); +struct dpp_configuration * dpp_configuration_alloc(const char *type); +int dpp_akm_psk(enum dpp_akm akm); +int dpp_akm_sae(enum dpp_akm akm); +int dpp_akm_legacy(enum dpp_akm akm); +int dpp_akm_dpp(enum dpp_akm akm); +int dpp_akm_ver2(enum dpp_akm akm); +int dpp_configuration_valid(const struct dpp_configuration *conf); +void dpp_configuration_free(struct dpp_configuration *conf); +int dpp_set_configurator(struct dpp_global *dpp, void *msg_ctx, + struct dpp_authentication *auth, + const char *cmd); +void dpp_auth_deinit(struct dpp_authentication *auth); +struct wpabuf * +dpp_conf_req_rx(struct dpp_authentication *auth, const u8 *attr_start, + size_t attr_len); +int dpp_conf_resp_rx(struct dpp_authentication *auth, + const struct wpabuf *resp); +enum dpp_status_error dpp_conf_result_rx(struct dpp_authentication *auth, + const u8 *hdr, + const u8 *attr_start, size_t attr_len); +struct wpabuf * dpp_build_conf_result(struct dpp_authentication *auth, + enum dpp_status_error status); +struct wpabuf * dpp_alloc_msg(enum dpp_public_action_frame_type type, + size_t len); +const u8 * dpp_get_attr(const u8 *buf, size_t len, u16 req_id, u16 *ret_len); +int dpp_check_attrs(const u8 *buf, size_t len); +int dpp_key_expired(const char *timestamp, os_time_t *expiry); +const char * dpp_akm_str(enum dpp_akm akm); +int dpp_configurator_get_key(const struct dpp_configurator *conf, char *buf, + size_t buflen); +void dpp_configurator_free(struct dpp_configurator *conf); +struct dpp_configurator * +dpp_keygen_configurator(const char *curve, const u8 *privkey, + size_t privkey_len); +int dpp_configurator_own_config(struct dpp_authentication *auth, + const char *curve, int ap); +enum dpp_status_error +dpp_peer_intro(struct dpp_introduction *intro, const char *own_connector, + const u8 *net_access_key, size_t net_access_key_len, + const u8 *csign_key, size_t csign_key_len, + const u8 *peer_connector, size_t peer_connector_len, + os_time_t *expiry); +struct dpp_pkex * dpp_pkex_init(void *msg_ctx, struct dpp_bootstrap_info *bi, + const u8 *own_mac, + const char *identifier, + const char *code); +struct dpp_pkex * dpp_pkex_rx_exchange_req(void *msg_ctx, + struct dpp_bootstrap_info *bi, + const u8 *own_mac, + const u8 *peer_mac, + const char *identifier, + const char *code, + const u8 *buf, size_t len); +struct wpabuf * dpp_pkex_rx_exchange_resp(struct dpp_pkex *pkex, + const u8 *peer_mac, + const u8 *buf, size_t len); +struct wpabuf * dpp_pkex_rx_commit_reveal_req(struct dpp_pkex *pkex, + const u8 *hdr, + const u8 *buf, size_t len); +int dpp_pkex_rx_commit_reveal_resp(struct dpp_pkex *pkex, const u8 *hdr, + const u8 *buf, size_t len); +void dpp_pkex_free(struct dpp_pkex *pkex); + +char * dpp_corrupt_connector_signature(const char *connector); + + +struct dpp_pfs { + struct crypto_ecdh *ecdh; + const struct dpp_curve_params *curve; + struct wpabuf *ie; + struct wpabuf *secret; +}; + +struct dpp_pfs * dpp_pfs_init(const u8 *net_access_key, + size_t net_access_key_len); +int dpp_pfs_process(struct dpp_pfs *pfs, const u8 *peer_ie, size_t peer_ie_len); +void dpp_pfs_free(struct dpp_pfs *pfs); + +struct dpp_bootstrap_info * dpp_add_qr_code(struct dpp_global *dpp, + const char *uri); +int dpp_bootstrap_gen(struct dpp_global *dpp, const char *cmd); +struct dpp_bootstrap_info * +dpp_bootstrap_get_id(struct dpp_global *dpp, unsigned int id); +int dpp_bootstrap_remove(struct dpp_global *dpp, const char *id); +struct dpp_bootstrap_info * +dpp_pkex_finish(struct dpp_global *dpp, struct dpp_pkex *pkex, const u8 *peer, + unsigned int freq); +const char * dpp_bootstrap_get_uri(struct dpp_global *dpp, unsigned int id); +int dpp_bootstrap_info(struct dpp_global *dpp, int id, + char *reply, int reply_size); +void dpp_bootstrap_find_pair(struct dpp_global *dpp, const u8 *i_bootstrap, + const u8 *r_bootstrap, + struct dpp_bootstrap_info **own_bi, + struct dpp_bootstrap_info **peer_bi); +int dpp_configurator_add(struct dpp_global *dpp, const char *cmd); +int dpp_configurator_remove(struct dpp_global *dpp, const char *id); +int dpp_configurator_get_key_id(struct dpp_global *dpp, unsigned int id, + char *buf, size_t buflen); +struct dpp_global * dpp_global_init(void); +void dpp_global_clear(struct dpp_global *dpp); +void dpp_global_deinit(struct dpp_global *dpp); + +#endif /* CONFIG_DPP */ +#endif /* DPP_H */ diff --git a/freebsd/contrib/wpa/src/common/gas.c b/freebsd/contrib/wpa/src/common/gas.c index 1aa3c806..bddc37a6 100644 --- a/freebsd/contrib/wpa/src/common/gas.c +++ b/freebsd/contrib/wpa/src/common/gas.c @@ -77,7 +77,7 @@ gas_build_initial_resp(u8 dialog_token, u16 status_code, u16 comeback_delay, } -static struct wpabuf * +struct wpabuf * gas_build_comeback_resp(u8 dialog_token, u16 status_code, u8 frag_id, u8 more, u16 comeback_delay, size_t size) { diff --git a/freebsd/contrib/wpa/src/common/gas.h b/freebsd/contrib/wpa/src/common/gas.h index 306adc58..4c93e311 100644 --- a/freebsd/contrib/wpa/src/common/gas.h +++ b/freebsd/contrib/wpa/src/common/gas.h @@ -14,6 +14,9 @@ struct wpabuf * gas_build_initial_req(u8 dialog_token, size_t size); struct wpabuf * gas_build_comeback_req(u8 dialog_token); struct wpabuf * gas_build_initial_resp(u8 dialog_token, u16 status_code, u16 comeback_delay, size_t size); +struct wpabuf * +gas_build_comeback_resp(u8 dialog_token, u16 status_code, u8 frag_id, u8 more, + u16 comeback_delay, size_t size); struct wpabuf * gas_anqp_build_initial_req(u8 dialog_token, size_t size); struct wpabuf * gas_anqp_build_initial_resp(u8 dialog_token, u16 status_code, u16 comeback_delay, size_t size); diff --git a/freebsd/contrib/wpa/src/common/gas_server.h b/freebsd/contrib/wpa/src/common/gas_server.h new file mode 100644 index 00000000..299f529f --- /dev/null +++ b/freebsd/contrib/wpa/src/common/gas_server.h @@ -0,0 +1,44 @@ +/* + * Generic advertisement service (GAS) server + * Copyright (c) 2017, Qualcomm Atheros, Inc. + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef GAS_SERVER_H +#define GAS_SERVER_H + +#ifdef CONFIG_GAS_SERVER + +struct gas_server; + +struct gas_server * gas_server_init(void *ctx, + void (*tx)(void *ctx, int freq, + const u8 *da, + struct wpabuf *buf, + unsigned int wait_time)); +void gas_server_deinit(struct gas_server *gas); +int gas_server_register(struct gas_server *gas, + const u8 *adv_proto_id, u8 adv_proto_id_len, + struct wpabuf * + (*req_cb)(void *ctx, const u8 *sa, + const u8 *query, size_t query_len), + void (*status_cb)(void *ctx, struct wpabuf *resp, + int ok), + void *ctx); +int gas_server_rx(struct gas_server *gas, const u8 *da, const u8 *sa, + const u8 *bssid, u8 categ, const u8 *data, size_t len, + int freq); +void gas_server_tx_status(struct gas_server *gas, const u8 *dst, const u8 *data, + size_t data_len, int ack); + +#else /* CONFIG_GAS_SERVER */ + +static inline void gas_server_deinit(struct gas_server *gas) +{ +} + +#endif /* CONFIG_GAS_SERVER */ + +#endif /* GAS_SERVER_H */ diff --git a/freebsd/contrib/wpa/src/common/hw_features_common.c b/freebsd/contrib/wpa/src/common/hw_features_common.c index 81b8e695..33d0d879 100644 --- a/freebsd/contrib/wpa/src/common/hw_features_common.c +++ b/freebsd/contrib/wpa/src/common/hw_features_common.c @@ -89,13 +89,29 @@ int hw_get_chan(struct hostapd_hw_modes *mode, int freq) int allowed_ht40_channel_pair(struct hostapd_hw_modes *mode, int pri_chan, int sec_chan) { - int ok, j, first; + int ok, first; int allowed[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 140, - 149, 157, 184, 192 }; + 149, 157, 165, 184, 192 }; size_t k; + struct hostapd_channel_data *p_chan, *s_chan; + const int ht40_plus = pri_chan < sec_chan; - if (pri_chan == sec_chan || !sec_chan) - return 1; /* HT40 not used */ + p_chan = hw_get_channel_chan(mode, pri_chan, NULL); + if (!p_chan) + return 0; + + if (pri_chan == sec_chan || !sec_chan) { + if (chan_pri_allowed(p_chan)) + return 1; /* HT40 not used */ + + wpa_printf(MSG_ERROR, "Channel %d is not allowed as primary", + pri_chan); + return 0; + } + + s_chan = hw_get_channel_chan(mode, sec_chan, NULL); + if (!s_chan) + return 0; wpa_printf(MSG_DEBUG, "HT40: control channel: %d secondary channel: %d", @@ -103,16 +119,9 @@ int allowed_ht40_channel_pair(struct hostapd_hw_modes *mode, int pri_chan, /* Verify that HT40 secondary channel is an allowed 20 MHz * channel */ - ok = 0; - for (j = 0; j < mode->num_channels; j++) { - struct hostapd_channel_data *chan = &mode->channels[j]; - if (!(chan->flag & HOSTAPD_CHAN_DISABLED) && - chan->chan == sec_chan) { - ok = 1; - break; - } - } - if (!ok) { + if ((s_chan->flag & HOSTAPD_CHAN_DISABLED) || + (ht40_plus && !(p_chan->allowed_bw & HOSTAPD_CHAN_WIDTH_40P)) || + (!ht40_plus && !(p_chan->allowed_bw & HOSTAPD_CHAN_WIDTH_40M))) { wpa_printf(MSG_ERROR, "HT40 secondary channel %d not allowed", sec_chan); return 0; @@ -390,8 +399,10 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data, /* fall through */ case VHT_CHANWIDTH_80MHZ: data->bandwidth = 80; - if ((vht_oper_chwidth == 1 && center_segment1) || - (vht_oper_chwidth == 3 && !center_segment1) || + if ((vht_oper_chwidth == VHT_CHANWIDTH_80MHZ && + center_segment1) || + (vht_oper_chwidth == VHT_CHANWIDTH_80P80MHZ && + !center_segment1) || !sec_channel_offset) return -1; if (!center_segment0) { @@ -455,3 +466,157 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data, return 0; } + + +void set_disable_ht40(struct ieee80211_ht_capabilities *htcaps, + int disabled) +{ + /* Masking these out disables HT40 */ + le16 msk = host_to_le16(HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET | + HT_CAP_INFO_SHORT_GI40MHZ); + + if (disabled) + htcaps->ht_capabilities_info &= ~msk; + else + htcaps->ht_capabilities_info |= msk; +} + + +#ifdef CONFIG_IEEE80211AC + +static int _ieee80211ac_cap_check(u32 hw, u32 conf, u32 cap, + const char *name) +{ + u32 req_cap = conf & cap; + + /* + * Make sure we support all requested capabilities. + * NOTE: We assume that 'cap' represents a capability mask, + * not a discrete value. + */ + if ((hw & req_cap) != req_cap) { + wpa_printf(MSG_ERROR, + "Driver does not support configured VHT capability [%s]", + name); + return 0; + } + return 1; +} + + +static int ieee80211ac_cap_check_max(u32 hw, u32 conf, u32 mask, + unsigned int shift, + const char *name) +{ + u32 hw_max = hw & mask; + u32 conf_val = conf & mask; + + if (conf_val > hw_max) { + wpa_printf(MSG_ERROR, + "Configured VHT capability [%s] exceeds max value supported by the driver (%d > %d)", + name, conf_val >> shift, hw_max >> shift); + return 0; + } + return 1; +} + + +int ieee80211ac_cap_check(u32 hw, u32 conf) +{ +#define VHT_CAP_CHECK(cap) \ + do { \ + if (!_ieee80211ac_cap_check(hw, conf, cap, #cap)) \ + return 0; \ + } while (0) + +#define VHT_CAP_CHECK_MAX(cap) \ + do { \ + if (!ieee80211ac_cap_check_max(hw, conf, cap, cap ## _SHIFT, \ + #cap)) \ + return 0; \ + } while (0) + + VHT_CAP_CHECK_MAX(VHT_CAP_MAX_MPDU_LENGTH_MASK); + VHT_CAP_CHECK_MAX(VHT_CAP_SUPP_CHAN_WIDTH_MASK); + VHT_CAP_CHECK(VHT_CAP_RXLDPC); + VHT_CAP_CHECK(VHT_CAP_SHORT_GI_80); + VHT_CAP_CHECK(VHT_CAP_SHORT_GI_160); + VHT_CAP_CHECK(VHT_CAP_TXSTBC); + VHT_CAP_CHECK_MAX(VHT_CAP_RXSTBC_MASK); + VHT_CAP_CHECK(VHT_CAP_SU_BEAMFORMER_CAPABLE); + VHT_CAP_CHECK(VHT_CAP_SU_BEAMFORMEE_CAPABLE); + VHT_CAP_CHECK_MAX(VHT_CAP_BEAMFORMEE_STS_MAX); + VHT_CAP_CHECK_MAX(VHT_CAP_SOUNDING_DIMENSION_MAX); + VHT_CAP_CHECK(VHT_CAP_MU_BEAMFORMER_CAPABLE); + VHT_CAP_CHECK(VHT_CAP_MU_BEAMFORMEE_CAPABLE); + VHT_CAP_CHECK(VHT_CAP_VHT_TXOP_PS); + VHT_CAP_CHECK(VHT_CAP_HTC_VHT); + VHT_CAP_CHECK_MAX(VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX); + VHT_CAP_CHECK(VHT_CAP_VHT_LINK_ADAPTATION_VHT_UNSOL_MFB); + VHT_CAP_CHECK(VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB); + VHT_CAP_CHECK(VHT_CAP_RX_ANTENNA_PATTERN); + VHT_CAP_CHECK(VHT_CAP_TX_ANTENNA_PATTERN); + +#undef VHT_CAP_CHECK +#undef VHT_CAP_CHECK_MAX + + return 1; +} + +#endif /* CONFIG_IEEE80211AC */ + + +u32 num_chan_to_bw(int num_chans) +{ + switch (num_chans) { + case 2: + case 4: + case 8: + return num_chans * 20; + default: + return 20; + } +} + + +/* check if BW is applicable for channel */ +int chan_bw_allowed(const struct hostapd_channel_data *chan, u32 bw, + int ht40_plus, int pri) +{ + u32 bw_mask; + + switch (bw) { + case 20: + bw_mask = HOSTAPD_CHAN_WIDTH_20; + break; + case 40: + /* HT 40 MHz support declared only for primary channel, + * just skip 40 MHz secondary checking */ + if (pri && ht40_plus) + bw_mask = HOSTAPD_CHAN_WIDTH_40P; + else if (pri && !ht40_plus) + bw_mask = HOSTAPD_CHAN_WIDTH_40M; + else + bw_mask = 0; + break; + case 80: + bw_mask = HOSTAPD_CHAN_WIDTH_80; + break; + case 160: + bw_mask = HOSTAPD_CHAN_WIDTH_160; + break; + default: + bw_mask = 0; + break; + } + + return (chan->allowed_bw & bw_mask) == bw_mask; +} + + +/* check if channel is allowed to be used as primary */ +int chan_pri_allowed(const struct hostapd_channel_data *chan) +{ + return !(chan->flag & HOSTAPD_CHAN_DISABLED) && + (chan->allowed_bw & HOSTAPD_CHAN_WIDTH_20); +} diff --git a/freebsd/contrib/wpa/src/common/hw_features_common.h b/freebsd/contrib/wpa/src/common/hw_features_common.h index 7360b4e3..eb1f1c57 100644 --- a/freebsd/contrib/wpa/src/common/hw_features_common.h +++ b/freebsd/contrib/wpa/src/common/hw_features_common.h @@ -35,5 +35,13 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data, int vht_enabled, int sec_channel_offset, int vht_oper_chwidth, int center_segment0, int center_segment1, u32 vht_caps); +void set_disable_ht40(struct ieee80211_ht_capabilities *htcaps, + int disabled); +int ieee80211ac_cap_check(u32 hw, u32 conf); + +u32 num_chan_to_bw(int num_chans); +int chan_bw_allowed(const struct hostapd_channel_data *chan, u32 bw, + int ht40_plus, int pri); +int chan_pri_allowed(const struct hostapd_channel_data *chan); #endif /* HW_FEATURES_COMMON_H */ diff --git a/freebsd/contrib/wpa/src/common/ieee802_11_common.c b/freebsd/contrib/wpa/src/common/ieee802_11_common.c index 286fdcf8..c6fc9019 100644 --- a/freebsd/contrib/wpa/src/common/ieee802_11_common.c +++ b/freebsd/contrib/wpa/src/common/ieee802_11_common.c @@ -2,7 +2,7 @@ /* * IEEE 802.11 Common routines - * Copyright (c) 2002-2015, Jouni Malinen <j@w1.fi> + * Copyright (c) 2002-2019, Jouni Malinen <j@w1.fi> * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -13,6 +13,7 @@ #include "common.h" #include "defs.h" #include "wpa_common.h" +#include "drivers/driver.h" #include "qca-vendor.h" #include "ieee802_11_defs.h" #include "ieee802_11_common.h" @@ -122,6 +123,15 @@ static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen, elems->mbo = pos; elems->mbo_len = elen; break; + case HS20_ROAMING_CONS_SEL_OUI_TYPE: + /* Hotspot 2.0 Roaming Consortium Selection */ + elems->roaming_cons_sel = pos; + elems->roaming_cons_sel_len = elen; + break; + case MULTI_AP_OUI_TYPE: + elems->multi_ap = pos; + elems->multi_ap_len = elen; + break; default: wpa_printf(MSG_MSGDUMP, "Unknown WFA " "information element ignored " @@ -181,6 +191,108 @@ static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen, } +static int ieee802_11_parse_extension(const u8 *pos, size_t elen, + struct ieee802_11_elems *elems, + int show_errors) +{ + u8 ext_id; + + if (elen < 1) { + if (show_errors) { + wpa_printf(MSG_MSGDUMP, + "short information element (Ext)"); + } + return -1; + } + + ext_id = *pos++; + elen--; + + switch (ext_id) { + case WLAN_EID_EXT_ASSOC_DELAY_INFO: + if (elen != 1) + break; + elems->assoc_delay_info = pos; + break; + case WLAN_EID_EXT_FILS_REQ_PARAMS: + if (elen < 3) + break; + elems->fils_req_params = pos; + elems->fils_req_params_len = elen; + break; + case WLAN_EID_EXT_FILS_KEY_CONFIRM: + elems->fils_key_confirm = pos; + elems->fils_key_confirm_len = elen; + break; + case WLAN_EID_EXT_FILS_SESSION: + if (elen != FILS_SESSION_LEN) + break; + elems->fils_session = pos; + break; + case WLAN_EID_EXT_FILS_HLP_CONTAINER: + if (elen < 2 * ETH_ALEN) + break; + elems->fils_hlp = pos; + elems->fils_hlp_len = elen; + break; + case WLAN_EID_EXT_FILS_IP_ADDR_ASSIGN: + if (elen < 1) + break; + elems->fils_ip_addr_assign = pos; + elems->fils_ip_addr_assign_len = elen; + break; + case WLAN_EID_EXT_KEY_DELIVERY: + if (elen < WPA_KEY_RSC_LEN) + break; + elems->key_delivery = pos; + elems->key_delivery_len = elen; + break; + case WLAN_EID_EXT_FILS_WRAPPED_DATA: + elems->fils_wrapped_data = pos; + elems->fils_wrapped_data_len = elen; + break; + case WLAN_EID_EXT_FILS_PUBLIC_KEY: + if (elen < 1) + break; + elems->fils_pk = pos; + elems->fils_pk_len = elen; + break; + case WLAN_EID_EXT_FILS_NONCE: + if (elen != FILS_NONCE_LEN) + break; + elems->fils_nonce = pos; + break; + case WLAN_EID_EXT_OWE_DH_PARAM: + if (elen < 2) + break; + elems->owe_dh = pos; + elems->owe_dh_len = elen; + break; + case WLAN_EID_EXT_PASSWORD_IDENTIFIER: + elems->password_id = pos; + elems->password_id_len = elen; + break; + case WLAN_EID_EXT_HE_CAPABILITIES: + elems->he_capabilities = pos; + elems->he_capabilities_len = elen; + break; + case WLAN_EID_EXT_OCV_OCI: + elems->oci = pos; + elems->oci_len = elen; + break; + default: + if (show_errors) { + wpa_printf(MSG_MSGDUMP, + "IEEE 802.11 element parsing ignored unknown element extension (ext_id=%u elen=%u)", + ext_id, (unsigned int) elen); + } + return -1; + } + + return 0; +} + + /** * ieee802_11_parse_elems - Parse information elements in management frames * @start: Pointer to the start of IEs @@ -193,29 +305,17 @@ ParseRes ieee802_11_parse_elems(const u8 *start, size_t len, struct ieee802_11_elems *elems, int show_errors) { - size_t left = len; - const u8 *pos = start; + const struct element *elem; int unknown = 0; os_memset(elems, 0, sizeof(*elems)); - while (left >= 2) { - u8 id, elen; + if (!start) + return ParseOK; - id = *pos++; - elen = *pos++; - left -= 2; - - if (elen > left) { - if (show_errors) { - wpa_printf(MSG_DEBUG, "IEEE 802.11 element " - "parse failed (id=%d elen=%d " - "left=%lu)", - id, elen, (unsigned long) left); - wpa_hexdump(MSG_MSGDUMP, "IEs", start, len); - } - return ParseFailed; - } + for_each_element(elem, start, len) { + u8 id = elem->id, elen = elem->datalen; + const u8 *pos = elem->data; switch (id) { case WLAN_EID_SSID: @@ -264,6 +364,10 @@ ParseRes ieee802_11_parse_elems(const u8 *start, size_t len, elems->rsn_ie_len = elen; break; case WLAN_EID_PWR_CAPABILITY: + if (elen < 2) + break; + elems->power_capab = pos; + elems->power_capab_len = elen; break; case WLAN_EID_SUPPORTED_CHANNELS: elems->supp_channels = pos; @@ -359,8 +463,7 @@ ParseRes ieee802_11_parse_elems(const u8 *start, size_t len, elems->mic = pos; elems->mic_len = elen; /* after mic everything is encrypted, so stop. */ - left = elen; - break; + goto done; case WLAN_EID_MULTI_BAND: if (elems->mb_ies.nof_ies >= MAX_NOF_MB_IES_SUPPORTED) { wpa_printf(MSG_MSGDUMP, @@ -381,6 +484,35 @@ ParseRes ieee802_11_parse_elems(const u8 *start, size_t len, elems->rrm_enabled = pos; elems->rrm_enabled_len = elen; break; + case WLAN_EID_CAG_NUMBER: + elems->cag_number = pos; + elems->cag_number_len = elen; + break; + case WLAN_EID_AP_CSN: + if (elen < 1) + break; + elems->ap_csn = pos; + break; + case WLAN_EID_FILS_INDICATION: + if (elen < 2) + break; + elems->fils_indic = pos; + elems->fils_indic_len = elen; + break; + case WLAN_EID_DILS: + if (elen < 2) + break; + elems->dils = pos; + elems->dils_len = elen; + break; + case WLAN_EID_FRAGMENT: + /* TODO */ + break; + case WLAN_EID_EXTENSION: + if (ieee802_11_parse_extension(pos, elen, elems, + show_errors)) + unknown++; + break; default: unknown++; if (!show_errors) @@ -390,35 +522,33 @@ ParseRes ieee802_11_parse_elems(const u8 *start, size_t len, id, elen); break; } - - left -= elen; - pos += elen; } - if (left) + if (!for_each_element_completed(elem, start, len)) { + if (show_errors) { + wpa_printf(MSG_DEBUG, + "IEEE 802.11 element parse failed @%d", + (int) (start + len - (const u8 *) elem)); + wpa_hexdump(MSG_MSGDUMP, "IEs", start, len); + } return ParseFailed; + } +done: return unknown ? ParseUnknown : ParseOK; } int ieee802_11_ie_count(const u8 *ies, size_t ies_len) { + const struct element *elem; int count = 0; - const u8 *pos, *end; if (ies == NULL) return 0; - pos = ies; - end = ies + ies_len; - - while (end - pos >= 2) { - if (2 + pos[1] > end - pos) - break; + for_each_element(elem, ies, ies_len) count++; - pos += 2 + pos[1]; - } return count; } @@ -428,24 +558,17 @@ struct wpabuf * ieee802_11_vendor_ie_concat(const u8 *ies, size_t ies_len, u32 oui_type) { struct wpabuf *buf; - const u8 *end, *pos, *ie; + const struct element *elem, *found = NULL; - pos = ies; - end = ies + ies_len; - ie = NULL; - - while (end - pos > 1) { - if (2 + pos[1] > end - pos) - return NULL; - if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && - WPA_GET_BE32(&pos[2]) == oui_type) { - ie = pos; + for_each_element_id(elem, WLAN_EID_VENDOR_SPECIFIC, ies, ies_len) { + if (elem->datalen >= 4 && + WPA_GET_BE32(elem->data) == oui_type) { + found = elem; break; } - pos += 2 + pos[1]; } - if (ie == NULL) + if (!found) return NULL; /* No specified vendor IE found */ buf = wpabuf_alloc(ies_len); @@ -456,13 +579,9 @@ struct wpabuf * ieee802_11_vendor_ie_concat(const u8 *ies, size_t ies_len, * There may be multiple vendor IEs in the message, so need to * concatenate their data fields. */ - while (end - pos > 1) { - if (2 + pos[1] > end - pos) - break; - if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && - WPA_GET_BE32(&pos[2]) == oui_type) - wpabuf_put_data(buf, pos + 6, pos[1] - 4); - pos += 2 + pos[1]; + for_each_element_id(elem, WLAN_EID_VENDOR_SPECIFIC, ies, ies_len) { + if (elem->datalen >= 4 && WPA_GET_BE32(elem->data) == oui_type) + wpabuf_put_data(buf, elem->data + 4, elem->datalen - 4); } return buf; @@ -683,6 +802,25 @@ enum hostapd_hw_mode ieee80211_freq_to_channel_ext(unsigned int freq, return HOSTAPD_MODE_IEEE80211A; } + /* 5 GHz, channels 52..64 */ + if (freq >= 5260 && freq <= 5320) { + if ((freq - 5000) % 5) + return NUM_HOSTAPD_MODES; + + if (vht_opclass) + *op_class = vht_opclass; + else if (sec_channel == 1) + *op_class = 119; + else if (sec_channel == -1) + *op_class = 120; + else + *op_class = 118; + + *channel = (freq - 5000) / 5; + + return HOSTAPD_MODE_IEEE80211A; + } + /* 5 GHz, channels 149..169 */ if (freq >= 5745 && freq <= 5845) { if ((freq - 5000) % 5) @@ -746,6 +884,41 @@ enum hostapd_hw_mode ieee80211_freq_to_channel_ext(unsigned int freq, } +int ieee80211_chaninfo_to_channel(unsigned int freq, enum chan_width chanwidth, + int sec_channel, u8 *op_class, u8 *channel) +{ + int vht = CHAN_WIDTH_UNKNOWN; + + switch (chanwidth) { + case CHAN_WIDTH_UNKNOWN: + case CHAN_WIDTH_20_NOHT: + case CHAN_WIDTH_20: + case CHAN_WIDTH_40: + vht = VHT_CHANWIDTH_USE_HT; + break; + case CHAN_WIDTH_80: + vht = VHT_CHANWIDTH_80MHZ; + break; + case CHAN_WIDTH_80P80: + vht = VHT_CHANWIDTH_80P80MHZ; + break; + case CHAN_WIDTH_160: + vht = VHT_CHANWIDTH_160MHZ; + break; + } + + if (ieee80211_freq_to_channel_ext(freq, sec_channel, vht, op_class, + channel) == NUM_HOSTAPD_MODES) { + wpa_printf(MSG_WARNING, + "Cannot determine operating class and channel (freq=%u chanwidth=%d sec_channel=%d)", + freq, chanwidth, sec_channel); + return -1; + } + + return 0; +} + + static const char *const us_op_class_cc[] = { "US", "CA", NULL }; @@ -983,7 +1156,7 @@ static int ieee80211_chan_to_freq_global(u8 op_class, u8 chan) return -1; return 5000 + 5 * chan; case 129: /* center freqs 50, 114; 160 MHz */ - if (chan < 50 || chan > 114) + if (chan < 36 || chan > 128) return -1; return 5000 + 5 * chan; case 180: /* 60 GHz band, channels 1..4 */ @@ -1033,10 +1206,24 @@ int ieee80211_chan_to_freq(const char *country, u8 op_class, u8 chan) } -int ieee80211_is_dfs(int freq) +int ieee80211_is_dfs(int freq, const struct hostapd_hw_modes *modes, + u16 num_modes) { - /* TODO: this could be more accurate to better cover all domains */ - return (freq >= 5260 && freq <= 5320) || (freq >= 5500 && freq <= 5700); + int i, j; + + if (!modes || !num_modes) + return (freq >= 5260 && freq <= 5320) || + (freq >= 5500 && freq <= 5700); + + for (i = 0; i < num_modes; i++) { + for (j = 0; j < modes[i].num_channels; j++) { + if (modes[i].channels[j].freq == freq && + (modes[i].channels[j].flag & HOSTAPD_CHAN_RADAR)) + return 1; + } + } + + return 0; } @@ -1133,27 +1320,27 @@ const char * fc2str(u16 fc) int mb_ies_info_by_ies(struct mb_ies_info *info, const u8 *ies_buf, size_t ies_len) { + const struct element *elem; + os_memset(info, 0, sizeof(*info)); - while (ies_buf && ies_len >= 2 && - info->nof_ies < MAX_NOF_MB_IES_SUPPORTED) { - size_t len = 2 + ies_buf[1]; + if (!ies_buf) + return 0; - if (len > ies_len) { - wpa_hexdump(MSG_DEBUG, "Truncated IEs", - ies_buf, ies_len); - return -1; - } + for_each_element_id(elem, WLAN_EID_MULTI_BAND, ies_buf, ies_len) { + if (info->nof_ies >= MAX_NOF_MB_IES_SUPPORTED) + return 0; - if (ies_buf[0] == WLAN_EID_MULTI_BAND) { - wpa_printf(MSG_DEBUG, "MB IE of %zu bytes found", len); - info->ies[info->nof_ies].ie = ies_buf + 2; - info->ies[info->nof_ies].ie_len = ies_buf[1]; - info->nof_ies++; - } + wpa_printf(MSG_DEBUG, "MB IE of %u bytes found", + elem->datalen + 2); + info->ies[info->nof_ies].ie = elem->data; + info->ies[info->nof_ies].ie_len = elem->datalen; + info->nof_ies++; + } - ies_len -= len; - ies_buf += len; + if (!for_each_element_completed(elem, ies_buf, ies_len)) { + wpa_hexdump(MSG_DEBUG, "Truncated IEs", ies_buf, ies_len); + return -1; } return 0; @@ -1276,21 +1463,50 @@ size_t global_op_class_size = ARRAY_SIZE(global_op_class); */ const u8 * get_ie(const u8 *ies, size_t len, u8 eid) { - const u8 *end; + const struct element *elem; if (!ies) return NULL; - end = ies + len; + for_each_element_id(elem, eid, ies, len) + return &elem->id; - while (end - ies > 1) { - if (2 + ies[1] > end - ies) - break; + return NULL; +} - if (ies[0] == eid) - return ies; - ies += 2 + ies[1]; +/** + * get_ie_ext - Fetch a specified extended information element from IEs buffer + * @ies: Information elements buffer + * @len: Information elements buffer length + * @ext: Information element extension identifier (WLAN_EID_EXT_*) + * Returns: Pointer to the information element (id field) or %NULL if not found + * + * This function returns the first matching information element in the IEs + * buffer or %NULL in case the element is not found. + */ +const u8 * get_ie_ext(const u8 *ies, size_t len, u8 ext) +{ + const struct element *elem; + + if (!ies) + return NULL; + + for_each_element_extid(elem, ext, ies, len) + return &elem->id; + + return NULL; +} + + +const u8 * get_vendor_ie(const u8 *ies, size_t len, u32 vendor_type) +{ + const struct element *elem; + + for_each_element_id(elem, WLAN_EID_VENDOR_SPECIFIC, ies, len) { + if (elem->datalen >= 4 && + vendor_type == WPA_GET_BE32(elem->data)) + return &elem->id; } return NULL; @@ -1319,3 +1535,299 @@ size_t mbo_add_ie(u8 *buf, size_t len, const u8 *attr, size_t attr_len) return 6 + attr_len; } + + +size_t add_multi_ap_ie(u8 *buf, size_t len, u8 value) +{ + u8 *pos = buf; + + if (len < 9) + return 0; + + *pos++ = WLAN_EID_VENDOR_SPECIFIC; + *pos++ = 7; /* len */ + WPA_PUT_BE24(pos, OUI_WFA); + pos += 3; + *pos++ = MULTI_AP_OUI_TYPE; + *pos++ = MULTI_AP_SUB_ELEM_TYPE; + *pos++ = 1; /* len */ + *pos++ = value; + + return pos - buf; +} + + +static const struct country_op_class us_op_class[] = { + { 1, 115 }, + { 2, 118 }, + { 3, 124 }, + { 4, 121 }, + { 5, 125 }, + { 12, 81 }, + { 22, 116 }, + { 23, 119 }, + { 24, 122 }, + { 25, 126 }, + { 26, 126 }, + { 27, 117 }, + { 28, 120 }, + { 29, 123 }, + { 30, 127 }, + { 31, 127 }, + { 32, 83 }, + { 33, 84 }, + { 34, 180 }, +}; + +static const struct country_op_class eu_op_class[] = { + { 1, 115 }, + { 2, 118 }, + { 3, 121 }, + { 4, 81 }, + { 5, 116 }, + { 6, 119 }, + { 7, 122 }, + { 8, 117 }, + { 9, 120 }, + { 10, 123 }, + { 11, 83 }, + { 12, 84 }, + { 17, 125 }, + { 18, 180 }, +}; + +static const struct country_op_class jp_op_class[] = { + { 1, 115 }, + { 30, 81 }, + { 31, 82 }, + { 32, 118 }, + { 33, 118 }, + { 34, 121 }, + { 35, 121 }, + { 36, 116 }, + { 37, 119 }, + { 38, 119 }, + { 39, 122 }, + { 40, 122 }, + { 41, 117 }, + { 42, 120 }, + { 43, 120 }, + { 44, 123 }, + { 45, 123 }, + { 56, 83 }, + { 57, 84 }, + { 58, 121 }, + { 59, 180 }, +}; + +static const struct country_op_class cn_op_class[] = { + { 1, 115 }, + { 2, 118 }, + { 3, 125 }, + { 4, 116 }, + { 5, 119 }, + { 6, 126 }, + { 7, 81 }, + { 8, 83 }, + { 9, 84 }, +}; + +static u8 +global_op_class_from_country_array(u8 op_class, size_t array_size, + const struct country_op_class *country_array) +{ + size_t i; + + for (i = 0; i < array_size; i++) { + if (country_array[i].country_op_class == op_class) + return country_array[i].global_op_class; + } + + return 0; +} + + +u8 country_to_global_op_class(const char *country, u8 op_class) +{ + const struct country_op_class *country_array; + size_t size; + u8 g_op_class; + + if (country_match(us_op_class_cc, country)) { + country_array = us_op_class; + size = ARRAY_SIZE(us_op_class); + } else if (country_match(eu_op_class_cc, country)) { + country_array = eu_op_class; + size = ARRAY_SIZE(eu_op_class); + } else if (country_match(jp_op_class_cc, country)) { + country_array = jp_op_class; + size = ARRAY_SIZE(jp_op_class); + } else if (country_match(cn_op_class_cc, country)) { + country_array = cn_op_class; + size = ARRAY_SIZE(cn_op_class); + } else { + /* + * Countries that do not match any of the above countries use + * global operating classes + */ + return op_class; + } + + g_op_class = global_op_class_from_country_array(op_class, size, + country_array); + + /* + * If the given operating class did not match any of the country's + * operating classes, assume that global operating class is used. + */ + return g_op_class ? g_op_class : op_class; +} + + +const struct oper_class_map * get_oper_class(const char *country, u8 op_class) +{ + const struct oper_class_map *op; + + if (country) + op_class = country_to_global_op_class(country, op_class); + + op = &global_op_class[0]; + while (op->op_class && op->op_class != op_class) + op++; + + if (!op->op_class) + return NULL; + + return op; +} + + +int oper_class_bw_to_int(const struct oper_class_map *map) +{ + switch (map->bw) { + case BW20: + return 20; + case BW40PLUS: + case BW40MINUS: + return 40; + case BW80: + return 80; + case BW80P80: + case BW160: + return 160; + case BW2160: + return 2160; + default: + return 0; + } +} + + +int ieee802_11_parse_candidate_list(const char *pos, u8 *nei_rep, + size_t nei_rep_len) +{ + u8 *nei_pos = nei_rep; + const char *end; + + /* + * BSS Transition Candidate List Entries - Neighbor Report elements + * neighbor=<BSSID>,<BSSID Information>,<Operating Class>, + * <Channel Number>,<PHY Type>[,<hexdump of Optional Subelements>] + */ + while (pos) { + u8 *nei_start; + long int val; + char *endptr, *tmp; + + pos = os_strstr(pos, " neighbor="); + if (!pos) + break; + if (nei_pos + 15 > nei_rep + nei_rep_len) { + wpa_printf(MSG_DEBUG, + "Not enough room for additional neighbor"); + return -1; + } + pos += 10; + + nei_start = nei_pos; + *nei_pos++ = WLAN_EID_NEIGHBOR_REPORT; + nei_pos++; /* length to be filled in */ + + if (hwaddr_aton(pos, nei_pos)) { + wpa_printf(MSG_DEBUG, "Invalid BSSID"); + return -1; + } + nei_pos += ETH_ALEN; + pos += 17; + if (*pos != ',') { + wpa_printf(MSG_DEBUG, "Missing BSSID Information"); + return -1; + } + pos++; + + val = strtol(pos, &endptr, 0); + WPA_PUT_LE32(nei_pos, val); + nei_pos += 4; + if (*endptr != ',') { + wpa_printf(MSG_DEBUG, "Missing Operating Class"); + return -1; + } + pos = endptr + 1; + + *nei_pos++ = atoi(pos); /* Operating Class */ + pos = os_strchr(pos, ','); + if (pos == NULL) { + wpa_printf(MSG_DEBUG, "Missing Channel Number"); + return -1; + } + pos++; + + *nei_pos++ = atoi(pos); /* Channel Number */ + pos = os_strchr(pos, ','); + if (pos == NULL) { + wpa_printf(MSG_DEBUG, "Missing PHY Type"); + return -1; + } + pos++; + + *nei_pos++ = atoi(pos); /* PHY Type */ + end = os_strchr(pos, ' '); + tmp = os_strchr(pos, ','); + if (tmp && (!end || tmp < end)) { + /* Optional Subelements (hexdump) */ + size_t len; + + pos = tmp + 1; + end = os_strchr(pos, ' '); + if (end) + len = end - pos; + else + len = os_strlen(pos); + if (nei_pos + len / 2 > nei_rep + nei_rep_len) { + wpa_printf(MSG_DEBUG, + "Not enough room for neighbor subelements"); + return -1; + } + if (len & 0x01 || + hexstr2bin(pos, nei_pos, len / 2) < 0) { + wpa_printf(MSG_DEBUG, + "Invalid neighbor subelement info"); + return -1; + } + nei_pos += len / 2; + pos = end; + } + + nei_start[1] = nei_pos - nei_start - 2; + } + + return nei_pos - nei_rep; +} + + +int ieee802_11_ext_capab(const u8 *ie, unsigned int capab) +{ + if (!ie || ie[1] <= capab / 8) + return 0; + return !!(ie[2 + capab / 8] & BIT(capab % 8)); +} diff --git a/freebsd/contrib/wpa/src/common/ieee802_11_common.h b/freebsd/contrib/wpa/src/common/ieee802_11_common.h index 42f39096..d41bd39e 100644 --- a/freebsd/contrib/wpa/src/common/ieee802_11_common.h +++ b/freebsd/contrib/wpa/src/common/ieee802_11_common.h @@ -1,6 +1,6 @@ /* * IEEE 802.11 Common routines - * Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi> + * Copyright (c) 2002-2019, Jouni Malinen <j@w1.fi> * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -10,6 +10,15 @@ #define IEEE802_11_COMMON_H #include "defs.h" +#include "ieee802_11_defs.h" + +struct element { + u8 id; + u8 datalen; + u8 data[]; +} STRUCT_PACKED; + +struct hostapd_hw_modes; #define MAX_NOF_MB_IES_SUPPORTED 5 @@ -64,6 +73,27 @@ struct ieee802_11_elems { const u8 *pref_freq_list; const u8 *supp_op_classes; const u8 *rrm_enabled; + const u8 *cag_number; + const u8 *ap_csn; + const u8 *fils_indic; + const u8 *dils; + const u8 *assoc_delay_info; + const u8 *fils_req_params; + const u8 *fils_key_confirm; + const u8 *fils_session; + const u8 *fils_hlp; + const u8 *fils_ip_addr_assign; + const u8 *key_delivery; + const u8 *fils_wrapped_data; + const u8 *fils_pk; + const u8 *fils_nonce; + const u8 *owe_dh; + const u8 *power_capab; + const u8 *roaming_cons_sel; + const u8 *password_id; + const u8 *oci; + const u8 *multi_ap; + const u8 *he_capabilities; u8 ssid_len; u8 supp_rates_len; @@ -96,6 +126,23 @@ struct ieee802_11_elems { u8 pref_freq_list_len; u8 supp_op_classes_len; u8 rrm_enabled_len; + u8 cag_number_len; + u8 fils_indic_len; + u8 dils_len; + u8 fils_req_params_len; + u8 fils_key_confirm_len; + u8 fils_hlp_len; + u8 fils_ip_addr_assign_len; + u8 key_delivery_len; + u8 fils_wrapped_data_len; + u8 fils_pk_len; + u8 owe_dh_len; + u8 power_capab_len; + u8 roaming_cons_sel_len; + u8 password_id_len; + u8 oci_len; + u8 multi_ap_len; + u8 he_capabilities_len; struct mb_ies_info mb_ies; }; @@ -126,7 +173,10 @@ int ieee80211_chan_to_freq(const char *country, u8 op_class, u8 chan); enum hostapd_hw_mode ieee80211_freq_to_channel_ext(unsigned int freq, int sec_channel, int vht, u8 *op_class, u8 *channel); -int ieee80211_is_dfs(int freq); +int ieee80211_chaninfo_to_channel(unsigned int freq, enum chan_width chanwidth, + int sec_channel, u8 *op_class, u8 *channel); +int ieee80211_is_dfs(int freq, const struct hostapd_hw_modes *modes, + u16 num_modes); enum phy_type ieee80211_get_phy_type(int freq, int ht, int vht); int supp_rates_11b_only(struct ieee802_11_elems *elems); @@ -150,7 +200,73 @@ extern const struct oper_class_map global_op_class[]; extern size_t global_op_class_size; const u8 * get_ie(const u8 *ies, size_t len, u8 eid); +const u8 * get_ie_ext(const u8 *ies, size_t len, u8 ext); +const u8 * get_vendor_ie(const u8 *ies, size_t len, u32 vendor_type); size_t mbo_add_ie(u8 *buf, size_t len, const u8 *attr, size_t attr_len); +size_t add_multi_ap_ie(u8 *buf, size_t len, u8 value); + +struct country_op_class { + u8 country_op_class; + u8 global_op_class; +}; + +u8 country_to_global_op_class(const char *country, u8 op_class); + +const struct oper_class_map * get_oper_class(const char *country, u8 op_class); +int oper_class_bw_to_int(const struct oper_class_map *map); + +int ieee802_11_parse_candidate_list(const char *pos, u8 *nei_rep, + size_t nei_rep_len); + +int ieee802_11_ext_capab(const u8 *ie, unsigned int capab); + +/* element iteration helpers */ +#define for_each_element(_elem, _data, _datalen) \ + for (_elem = (const struct element *) (_data); \ + (const u8 *) (_data) + (_datalen) - (const u8 *) _elem >= \ + (int) sizeof(*_elem) && \ + (const u8 *) (_data) + (_datalen) - (const u8 *) _elem >= \ + (int) sizeof(*_elem) + _elem->datalen; \ + _elem = (const struct element *) (_elem->data + _elem->datalen)) + +#define for_each_element_id(element, _id, data, datalen) \ + for_each_element(element, data, datalen) \ + if (element->id == (_id)) + +#define for_each_element_extid(element, extid, _data, _datalen) \ + for_each_element(element, _data, _datalen) \ + if (element->id == WLAN_EID_EXTENSION && \ + element->datalen > 0 && \ + element->data[0] == (extid)) + +#define for_each_subelement(sub, element) \ + for_each_element(sub, (element)->data, (element)->datalen) + +#define for_each_subelement_id(sub, id, element) \ + for_each_element_id(sub, id, (element)->data, (element)->datalen) + +#define for_each_subelement_extid(sub, extid, element) \ + for_each_element_extid(sub, extid, (element)->data, (element)->datalen) + +/** + * for_each_element_completed - Determine if element parsing consumed all data + * @element: Element pointer after for_each_element() or friends + * @data: Same data pointer as passed to for_each_element() or friends + * @datalen: Same data length as passed to for_each_element() or friends + * + * This function returns 1 if all the data was parsed or considered + * while walking the elements. Only use this if your for_each_element() + * loop cannot be broken out of, otherwise it always returns 0. + * + * If some data was malformed, this returns %false since the last parsed + * element will not fill the whole remaining data. + */ +static inline int for_each_element_completed(const struct element *element, + const void *data, size_t datalen) +{ + return (const u8 *) element == (const u8 *) data + datalen; +} + #endif /* IEEE802_11_COMMON_H */ diff --git a/freebsd/contrib/wpa/src/common/ieee802_11_defs.h b/freebsd/contrib/wpa/src/common/ieee802_11_defs.h index d453aec7..adaa8931 100644 --- a/freebsd/contrib/wpa/src/common/ieee802_11_defs.h +++ b/freebsd/contrib/wpa/src/common/ieee802_11_defs.h @@ -1,6 +1,6 @@ /* * IEEE 802.11 Frame type definitions - * Copyright (c) 2002-2015, Jouni Malinen <j@w1.fi> + * Copyright (c) 2002-2019, Jouni Malinen <j@w1.fi> * Copyright (c) 2007-2008 Intel Corporation * * This software may be distributed under the terms of the BSD license. @@ -81,6 +81,9 @@ #define WLAN_AUTH_SHARED_KEY 1 #define WLAN_AUTH_FT 2 #define WLAN_AUTH_SAE 3 +#define WLAN_AUTH_FILS_SK 4 +#define WLAN_AUTH_FILS_SK_PFS 5 +#define WLAN_AUTH_FILS_PK 6 #define WLAN_AUTH_LEAP 128 #define WLAN_AUTH_CHALLENGE_LEN 128 @@ -102,7 +105,7 @@ #define WLAN_CAPABILITY_DELAYED_BLOCK_ACK BIT(14) #define WLAN_CAPABILITY_IMM_BLOCK_ACK BIT(15) -/* Status codes (IEEE 802.11-2007, 7.3.1.9, Table 7-23) */ +/* Status codes (IEEE Std 802.11-2016, 9.4.1.9, Table 9-46) */ #define WLAN_STATUS_SUCCESS 0 #define WLAN_STATUS_UNSPECIFIED_FAILURE 1 #define WLAN_STATUS_TDLS_WAKEUP_ALTERNATE 2 @@ -119,27 +122,23 @@ #define WLAN_STATUS_AUTH_TIMEOUT 16 #define WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA 17 #define WLAN_STATUS_ASSOC_DENIED_RATES 18 -/* IEEE 802.11b */ #define WLAN_STATUS_ASSOC_DENIED_NOSHORT 19 -#define WLAN_STATUS_ASSOC_DENIED_NOPBCC 20 -#define WLAN_STATUS_ASSOC_DENIED_NOAGILITY 21 -/* IEEE 802.11h */ #define WLAN_STATUS_SPEC_MGMT_REQUIRED 22 #define WLAN_STATUS_PWR_CAPABILITY_NOT_VALID 23 #define WLAN_STATUS_SUPPORTED_CHANNEL_NOT_VALID 24 -/* IEEE 802.11g */ #define WLAN_STATUS_ASSOC_DENIED_NO_SHORT_SLOT_TIME 25 -#define WLAN_STATUS_ASSOC_DENIED_NO_DSSS_OFDM 26 #define WLAN_STATUS_ASSOC_DENIED_NO_HT 27 #define WLAN_STATUS_R0KH_UNREACHABLE 28 #define WLAN_STATUS_ASSOC_DENIED_NO_PCO 29 -/* IEEE 802.11w */ #define WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY 30 #define WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION 31 #define WLAN_STATUS_UNSPECIFIED_QOS_FAILURE 32 +#define WLAN_STATUS_DENIED_INSUFFICIENT_BANDWIDTH 33 +#define WLAN_STATUS_DENIED_POOR_CHANNEL_CONDITIONS 34 +#define WLAN_STATUS_DENIED_QOS_NOT_SUPPORTED 35 #define WLAN_STATUS_REQUEST_DECLINED 37 #define WLAN_STATUS_INVALID_PARAMETERS 38 -/* IEEE 802.11i */ +#define WLAN_STATUS_REJECTED_WITH_SUGGESTED_CHANGES 39 #define WLAN_STATUS_INVALID_IE 40 #define WLAN_STATUS_GROUP_CIPHER_NOT_VALID 41 #define WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID 42 @@ -152,11 +151,13 @@ #define WLAN_STATUS_DEST_STA_NOT_PRESENT 49 #define WLAN_STATUS_DEST_STA_NOT_QOS_STA 50 #define WLAN_STATUS_ASSOC_DENIED_LISTEN_INT_TOO_LARGE 51 -/* IEEE 802.11r */ #define WLAN_STATUS_INVALID_FT_ACTION_FRAME_COUNT 52 #define WLAN_STATUS_INVALID_PMKID 53 #define WLAN_STATUS_INVALID_MDIE 54 #define WLAN_STATUS_INVALID_FTIE 55 +#define WLAN_STATUS_REQUESTED_TCLAS_NOT_SUPPORTED 56 +#define WLAN_STATUS_INSUFFICIENT_TCLAS_PROCESSING_RESOURCES 57 +#define WLAN_STATUS_TRY_ANOTHER_BSS 58 #define WLAN_STATUS_GAS_ADV_PROTO_NOT_SUPPORTED 59 #define WLAN_STATUS_NO_OUTSTANDING_GAS_REQ 60 #define WLAN_STATUS_GAS_RESP_NOT_RECEIVED 61 @@ -167,16 +168,44 @@ #define WLAN_STATUS_REQ_REFUSED_SSPN 67 #define WLAN_STATUS_REQ_REFUSED_UNAUTH_ACCESS 68 #define WLAN_STATUS_INVALID_RSNIE 72 +#define WLAN_STATUS_U_APSD_COEX_NOT_SUPPORTED 73 +#define WLAN_STATUS_U_APSD_COEX_MODE_NOT_SUPPORTED 74 +#define WLAN_STATUS_BAD_INTERVAL_WITH_U_APSD_COEX 75 #define WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ 76 #define WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED 77 +#define WLAN_STATUS_CANNOT_FIND_ALT_TBTT 78 #define WLAN_STATUS_TRANSMISSION_FAILURE 79 +#define WLAN_STATUS_REQ_TCLAS_NOT_SUPPORTED 80 +#define WLAN_STATUS_TCLAS_RESOURCES_EXCHAUSTED 81 #define WLAN_STATUS_REJECTED_WITH_SUGGESTED_BSS_TRANSITION 82 +#define WLAN_STATUS_REJECT_WITH_SCHEDULE 83 +#define WLAN_STATUS_REJECT_NO_WAKEUP_SPECIFIED 84 +#define WLAN_STATUS_SUCCESS_POWER_SAVE_MODE 85 #define WLAN_STATUS_PENDING_ADMITTING_FST_SESSION 86 +#define WLAN_STATUS_PERFORMING_FST_NOW 87 +#define WLAN_STATUS_PENDING_GAP_IN_BA_WINDOW 88 +#define WLAN_STATUS_REJECT_U_PID_SETTING 89 +#define WLAN_STATUS_REFUSED_EXTERNAL_REASON 92 +#define WLAN_STATUS_REFUSED_AP_OUT_OF_MEMORY 93 +#define WLAN_STATUS_REJECTED_EMERGENCY_SERVICE_NOT_SUPPORTED 94 #define WLAN_STATUS_QUERY_RESP_OUTSTANDING 95 +#define WLAN_STATUS_REJECT_DSE_BAND 96 +#define WLAN_STATUS_TCLAS_PROCESSING_TERMINATED 97 +#define WLAN_STATUS_TS_SCHEDULE_CONFLICT 98 #define WLAN_STATUS_DENIED_WITH_SUGGESTED_BAND_AND_CHANNEL 99 +#define WLAN_STATUS_MCCAOP_RESERVATION_CONFLICT 100 +#define WLAN_STATUS_MAF_LIMIT_EXCEEDED 101 +#define WLAN_STATUS_MCCA_TRACK_LIMIT_EXCEEDED 102 +#define WLAN_STATUS_DENIED_DUE_TO_SPECTRUM_MANAGEMENT 103 #define WLAN_STATUS_ASSOC_DENIED_NO_VHT 104 - -/* Reason codes (IEEE 802.11-2007, 7.3.1.7, Table 7-22) */ +#define WLAN_STATUS_ENABLEMENT_DENIED 105 +#define WLAN_STATUS_RESTRICTION_FROM_AUTHORIZED_GDB 106 +#define WLAN_STATUS_AUTHORIZATION_DEENABLED 107 +#define WLAN_STATUS_FILS_AUTHENTICATION_FAILURE 112 +#define WLAN_STATUS_UNKNOWN_AUTHENTICATION_SERVER 113 +#define WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER 123 + +/* Reason codes (IEEE Std 802.11-2016, 9.4.1.7, Table 9-45) */ #define WLAN_REASON_UNSPECIFIED 1 #define WLAN_REASON_PREV_AUTH_NOT_VALID 2 #define WLAN_REASON_DEAUTH_LEAVING 3 @@ -186,10 +215,9 @@ #define WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA 7 #define WLAN_REASON_DISASSOC_STA_HAS_LEFT 8 #define WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH 9 -/* IEEE 802.11h */ #define WLAN_REASON_PWR_CAPABILITY_NOT_VALID 10 #define WLAN_REASON_SUPPORTED_CHANNEL_NOT_VALID 11 -/* IEEE 802.11i */ +#define WLAN_REASON_BSS_TRANSITION_DISASSOC 12 #define WLAN_REASON_INVALID_IE 13 #define WLAN_REASON_MICHAEL_MIC_FAILURE 14 #define WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT 15 @@ -204,9 +232,26 @@ #define WLAN_REASON_CIPHER_SUITE_REJECTED 24 #define WLAN_REASON_TDLS_TEARDOWN_UNREACHABLE 25 #define WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED 26 -/* IEEE 802.11e */ +#define WLAN_REASON_SSP_REQUESTED_DISASSOC 27 +#define WLAN_REASON_NO_SSP_ROAMING_AGREEMENT 28 +#define WLAN_REASON_BAD_CIPHER_OR_AKM 29 +#define WLAN_REASON_NOT_AUTHORIZED_THIS_LOCATION 30 +#define WLAN_REASON_SERVICE_CHANGE_PRECLUDES_TS 31 +#define WLAN_REASON_UNSPECIFIED_QOS_REASON 32 +#define WLAN_REASON_NOT_ENOUGH_BANDWIDTH 33 #define WLAN_REASON_DISASSOC_LOW_ACK 34 -/* IEEE 802.11s */ +#define WLAN_REASON_EXCEEDED_TXOP 35 +#define WLAN_REASON_STA_LEAVING 36 +#define WLAN_REASON_END_TS_BA_DLS 37 +#define WLAN_REASON_UNKNOWN_TS_BA 38 +#define WLAN_REASON_TIMEOUT 39 +#define WLAN_REASON_PEERKEY_MISMATCH 45 +#define WLAN_REASON_AUTHORIZED_ACCESS_LIMIT_REACHED 46 +#define WLAN_REASON_EXTERNAL_SERVICE_REQUIREMENTS 47 +#define WLAN_REASON_INVALID_FT_ACTION_FRAME_COUNT 48 +#define WLAN_REASON_INVALID_PMKID 49 +#define WLAN_REASON_INVALID_MDE 50 +#define WLAN_REASON_INVALID_FTE 51 #define WLAN_REASON_MESH_PEERING_CANCELLED 52 #define WLAN_REASON_MESH_MAX_PEERS 53 #define WLAN_REASON_MESH_CONFIG_POLICY_VIOLATION 54 @@ -216,20 +261,29 @@ #define WLAN_REASON_MESH_INVALID_GTK 58 #define WLAN_REASON_MESH_INCONSISTENT_PARAMS 59 #define WLAN_REASON_MESH_INVALID_SECURITY_CAP 60 +#define WLAN_REASON_MESH_PATH_ERROR_NO_PROXY_INFO 61 +#define WLAN_REASON_MESH_PATH_ERROR_NO_FORWARDING_INFO 62 +#define WLAN_REASON_MESH_PATH_ERROR_DEST_UNREACHABLE 63 +#define WLAN_REASON_MAC_ADDRESS_ALREADY_EXISTS_IN_MBSS 64 +#define WLAN_REASON_MESH_CHANNEL_SWITCH_REGULATORY_REQ 65 +#define WLAN_REASON_MESH_CHANNEL_SWITCH_UNSPECIFIED 66 -/* Information Element IDs */ +/* Information Element IDs (IEEE Std 802.11-2016, 9.4.2.1, Table 9-77) */ #define WLAN_EID_SSID 0 #define WLAN_EID_SUPP_RATES 1 -#define WLAN_EID_FH_PARAMS 2 #define WLAN_EID_DS_PARAMS 3 #define WLAN_EID_CF_PARAMS 4 #define WLAN_EID_TIM 5 #define WLAN_EID_IBSS_PARAMS 6 #define WLAN_EID_COUNTRY 7 +#define WLAN_EID_REQUEST 10 #define WLAN_EID_BSS_LOAD 11 +#define WLAN_EID_EDCA_PARAM_SET 12 +#define WLAN_EID_TSPEC 13 +#define WLAN_EID_TCLAS 14 +#define WLAN_EID_SCHEDULE 15 #define WLAN_EID_CHALLENGE 16 -/* EIDs defined by IEEE 802.11h - START */ #define WLAN_EID_PWR_CONSTRAINT 32 #define WLAN_EID_PWR_CAPABILITY 33 #define WLAN_EID_TPC_REQUEST 34 @@ -238,50 +292,139 @@ #define WLAN_EID_CHANNEL_SWITCH 37 #define WLAN_EID_MEASURE_REQUEST 38 #define WLAN_EID_MEASURE_REPORT 39 -#define WLAN_EID_QUITE 40 +#define WLAN_EID_QUIET 40 #define WLAN_EID_IBSS_DFS 41 -/* EIDs defined by IEEE 802.11h - END */ #define WLAN_EID_ERP_INFO 42 +#define WLAN_EID_TS_DELAY 43 +#define WLAN_EID_TCLAS_PROCESSING 44 #define WLAN_EID_HT_CAP 45 #define WLAN_EID_QOS 46 #define WLAN_EID_RSN 48 #define WLAN_EID_EXT_SUPP_RATES 50 +#define WLAN_EID_AP_CHANNEL_REPORT 51 #define WLAN_EID_NEIGHBOR_REPORT 52 +#define WLAN_EID_RCPI 53 #define WLAN_EID_MOBILITY_DOMAIN 54 #define WLAN_EID_FAST_BSS_TRANSITION 55 #define WLAN_EID_TIMEOUT_INTERVAL 56 #define WLAN_EID_RIC_DATA 57 +#define WLAN_EID_DSE_REGISTERED_LOCATION 58 #define WLAN_EID_SUPPORTED_OPERATING_CLASSES 59 #define WLAN_EID_EXT_CHANSWITCH_ANN 60 #define WLAN_EID_HT_OPERATION 61 #define WLAN_EID_SECONDARY_CHANNEL_OFFSET 62 -#define WLAN_EID_WAPI 68 +#define WLAN_EID_BSS_AVERAGE_ACCESS_DELAY 63 +#define WLAN_EID_ANTENNA 64 +#define WLAN_EID_RSNI 65 +#define WLAN_EID_MEASUREMENT_PILOT_TRANSMISSION 66 +#define WLAN_EID_BSS_AVAILABLE_ADM_CAPA 67 +#define WLAN_EID_BSS_AC_ACCESS_DELAY 68 /* note: also used by WAPI */ #define WLAN_EID_TIME_ADVERTISEMENT 69 #define WLAN_EID_RRM_ENABLED_CAPABILITIES 70 +#define WLAN_EID_MULTIPLE_BSSID 71 #define WLAN_EID_20_40_BSS_COEXISTENCE 72 #define WLAN_EID_20_40_BSS_INTOLERANT 73 #define WLAN_EID_OVERLAPPING_BSS_SCAN_PARAMS 74 +#define WLAN_EID_RIC_DESCRIPTOR 75 #define WLAN_EID_MMIE 76 +#define WLAN_EID_EVENT_REQUEST 78 +#define WLAN_EID_EVENT_REPORT 79 +#define WLAN_EID_DIAGNOSTIC_REQUEST 80 +#define WLAN_EID_DIAGNOSTIC_REPORT 81 +#define WLAN_EID_LOCATION_PARAMETERS 82 +#define WLAN_EID_NONTRANSMITTED_BSSID_CAPA 83 #define WLAN_EID_SSID_LIST 84 +#define WLAN_EID_MULTIPLE_BSSID_INDEX 85 +#define WLAN_EID_FMS_DESCRIPTOR 86 +#define WLAN_EID_FMS_REQUEST 87 +#define WLAN_EID_FMS_RESPONSE 88 +#define WLAN_EID_QOS_TRAFFIC_CAPABILITY 89 #define WLAN_EID_BSS_MAX_IDLE_PERIOD 90 #define WLAN_EID_TFS_REQ 91 #define WLAN_EID_TFS_RESP 92 #define WLAN_EID_WNMSLEEP 93 +#define WLAN_EID_TIM_BROADCAST_REQUEST 94 +#define WLAN_EID_TIM_BROADCAST_RESPONSE 95 +#define WLAN_EID_COLLOCATED_INTERFERENCE_REPORT 96 +#define WLAN_EID_CHANNEL_USAGE 97 #define WLAN_EID_TIME_ZONE 98 +#define WLAN_EID_DMS_REQUEST 99 +#define WLAN_EID_DMS_RESPONSE 100 #define WLAN_EID_LINK_ID 101 +#define WLAN_EID_WAKEUP_SCHEDULE 102 +#define WLAN_EID_CHANNEL_SWITCH_TIMING 104 +#define WLAN_EID_PTI_CONTROL 105 +#define WLAN_EID_TPU_BUFFER_STATUS 106 #define WLAN_EID_INTERWORKING 107 #define WLAN_EID_ADV_PROTO 108 +#define WLAN_EID_EXPEDITED_BANDWIDTH_REQ 109 #define WLAN_EID_QOS_MAP_SET 110 #define WLAN_EID_ROAMING_CONSORTIUM 111 +#define WLAN_EID_EMERGENCY_ALERT_ID 112 #define WLAN_EID_MESH_CONFIG 113 #define WLAN_EID_MESH_ID 114 +#define WLAN_EID_MESH_LINK_METRIC_REPORT 115 +#define WLAN_EID_CONGESTION_NOTIFICATION 116 #define WLAN_EID_PEER_MGMT 117 +#define WLAN_EID_MESH_CHANNEL_SWITCH_PARAMETERS 118 +#define WLAN_EID_MESH_AWAKE_WINDOW 119 +#define WLAN_EID_BEACON_TIMING 120 +#define WLAN_EID_MCCAOP_SETUP_REQUEST 121 +#define WLAN_EID_MCCAOP_SETUP_REPLY 122 +#define WLAN_EID_MCCAOP_ADVERTISEMENT 123 +#define WLAN_EID_MCCAOP_TEARDOWN 124 +#define WLAN_EID_GANN 125 +#define WLAN_EID_RANN 126 #define WLAN_EID_EXT_CAPAB 127 +#define WLAN_EID_PREQ 130 +#define WLAN_EID_PREP 131 +#define WLAN_EID_PERR 132 +#define WLAN_EID_PXU 137 +#define WLAN_EID_PXUC 138 #define WLAN_EID_AMPE 139 #define WLAN_EID_MIC 140 +#define WLAN_EID_DESTINATION_URI 141 +#define WLAN_EID_U_APSD_COEX 142 +#define WLAN_EID_DMG_WAKEUP_SCHEDULE 143 +#define WLAN_EID_EXTENDED_SCHEDULE 144 +#define WLAN_EID_STA_AVAILABILITY 145 +#define WLAN_EID_DMG_TSPEC 146 +#define WLAN_EID_NEXT_DMG_ATI 147 +#define WLAN_EID_DMG_CAPABILITIES 148 +#define WLAN_EID_DMG_OPERATION 151 +#define WLAN_EID_DMG_BSS_PARAMETER_CHANGE 152 +#define WLAN_EID_DMG_BEAM_REFINEMENT 153 +#define WLAN_EID_CHANNEL_MEASUREMENT_FEEDBACK 154 #define WLAN_EID_CCKM 156 +#define WLAN_EID_AWAKE_WINDOW 157 #define WLAN_EID_MULTI_BAND 158 +#define WLAN_EID_ADDBA_EXTENSION 159 +#define WLAN_EID_NEXTPCP_LIST 160 +#define WLAN_EID_PCP_HANDOVER 161 +#define WLAN_EID_DMG_LINK_MARGIN 162 +#define WLAN_EID_SWITCHING_STREAM 163 #define WLAN_EID_SESSION_TRANSITION 164 +#define WLAN_EID_DYNAMIC_TONE_PAIRING_REPORT 165 +#define WLAN_EID_CLUSTER_REPORT 166 +#define WLAN_EID_REPLAY_CAPABILITIES 167 +#define WLAN_EID_RELAY_TRANSFER_PARAM_SET 168 +#define WLAN_EID_BEAMLINK_MAINTENANCE 169 +#define WLAN_EID_MULTIPLE_MAC_SUBLAYERS 170 +#define WLAN_EID_U_PID 171 +#define WLAN_EID_DMG_LINK_ADAPTATION_ACK 172 +#define WLAN_EID_MCCAOP_ADVERTISEMENT_OVERVIEW 174 +#define WLAN_EID_QUIET_PERIOD_REQUEST 175 +#define WLAN_EID_QUIET_PERIOD_RESPONSE 177 +#define WLAN_EID_QMF_POLICY 181 +#define WLAN_EID_ECAPC_POLICY 182 +#define WLAN_EID_CLUSTER_TIME_OFFSET 183 +#define WLAN_EID_INTRA_ACCESS_CATEGORY_PRIORITY 184 +#define WLAN_EID_SCS_DESCRIPTOR 185 +#define WLAN_EID_QLOAD_REPORT 186 +#define WLAN_EID_HCCA_TXOP_UPDATE_COUNT 187 +#define WLAN_EID_HIGHER_LAYER_STREAM_ID 188 +#define WLAN_EID_GCR_GROUP_ADDRESS 189 +#define WLAN_EID_ANTENNA_SECTOR_ID_PATTERN 190 #define WLAN_EID_VHT_CAP 191 #define WLAN_EID_VHT_OPERATION 192 #define WLAN_EID_VHT_EXTENDED_BSS_LOAD 193 @@ -291,10 +434,124 @@ #define WLAN_EID_VHT_AID 197 #define WLAN_EID_VHT_QUIET_CHANNEL 198 #define WLAN_EID_VHT_OPERATING_MODE_NOTIFICATION 199 +#define WLAN_EID_UPSIM 200 +#define WLAN_EID_REDUCED_NEIGHBOR_REPORT 201 +#define WLAN_EID_TVHT_OPERATION 202 +#define WLAN_EID_DEVICE_LOCATION 204 +#define WLAN_EID_WHITE_SPACE_MAP 205 +#define WLAN_EID_FTM_PARAMETERS 206 #define WLAN_EID_VENDOR_SPECIFIC 221 - - -/* Action frame categories (IEEE 802.11-2007, 7.3.1.11, Table 7-24) */ +#define WLAN_EID_CAG_NUMBER 237 +#define WLAN_EID_AP_CSN 239 +#define WLAN_EID_FILS_INDICATION 240 +#define WLAN_EID_DILS 241 +#define WLAN_EID_FRAGMENT 242 +#define WLAN_EID_EXTENSION 255 + +/* Element ID Extension (EID 255) values */ +#define WLAN_EID_EXT_ASSOC_DELAY_INFO 1 +#define WLAN_EID_EXT_FILS_REQ_PARAMS 2 +#define WLAN_EID_EXT_FILS_KEY_CONFIRM 3 +#define WLAN_EID_EXT_FILS_SESSION 4 +#define WLAN_EID_EXT_FILS_HLP_CONTAINER 5 +#define WLAN_EID_EXT_FILS_IP_ADDR_ASSIGN 6 +#define WLAN_EID_EXT_KEY_DELIVERY 7 +#define WLAN_EID_EXT_FILS_WRAPPED_DATA 8 +#define WLAN_EID_EXT_FTM_SYNC_INFO 9 +#define WLAN_EID_EXT_EXTENDED_REQUEST 10 +#define WLAN_EID_EXT_ESTIMATED_SERVICE_PARAMS 11 +#define WLAN_EID_EXT_FILS_PUBLIC_KEY 12 +#define WLAN_EID_EXT_FILS_NONCE 13 +#define WLAN_EID_EXT_FUTURE_CHANNEL_GUIDANCE 14 +#define WLAN_EID_EXT_OWE_DH_PARAM 32 +#define WLAN_EID_EXT_PASSWORD_IDENTIFIER 33 +#define WLAN_EID_EXT_HE_CAPABILITIES 35 +#define WLAN_EID_EXT_HE_OPERATION 36 +#define WLAN_EID_EXT_HE_MU_EDCA_PARAMS 38 +#define WLAN_EID_EXT_OCV_OCI 54 + +/* Extended Capabilities field */ +#define WLAN_EXT_CAPAB_20_40_COEX 0 +#define WLAN_EXT_CAPAB_GLK 1 +#define WLAN_EXT_CAPAB_EXT_CHAN_SWITCH 2 +#define WLAN_EXT_CAPAB_GLK_GCR 3 +#define WLAN_EXT_CAPAB_PSMP 4 +/* 5 - Reserved */ +#define WLAN_EXT_CAPAB_S_PSMP 6 +#define WLAN_EXT_CAPAB_EVENT 7 +#define WLAN_EXT_CAPAB_DIAGNOSTICS 8 +#define WLAN_EXT_CAPAB_MULTICAST_DIAGNOSTICS 9 +#define WLAN_EXT_CAPAB_LOCATION_TRACKING 10 +#define WLAN_EXT_CAPAB_FMS 11 +#define WLAN_EXT_CAPAB_PROXY_ARP 12 +#define WLAN_EXT_CAPAB_COLL_INTERF_REP 13 +#define WLAN_EXT_CAPAB_CIVIC_LOCATION 14 +#define WLAN_EXT_CAPAB_GEOSPATIAL_LOCATION 15 +#define WLAN_EXT_CAPAB_TFS 16 +#define WLAN_EXT_CAPAB_WNM_SLEEP_MODE 17 +#define WLAN_EXT_CAPAB_TIM_BROADCAST 18 +#define WLAN_EXT_CAPAB_BSS_TRANSITION 19 +#define WLAN_EXT_CAPAB_QOS_TRAFFIC 20 +#define WLAN_EXT_CAPAB_AC_STA_COUNT 21 +#define WLAN_EXT_CAPAB_MULTIPLE_BSSID 22 +#define WLAN_EXT_CAPAB_TIMING_MEASUREMENT 23 +#define WLAN_EXT_CAPAB_CHANNEL_USAGE 24 +#define WLAN_EXT_CAPAB_SSID_LIST 25 +#define WLAN_EXT_CAPAB_DMS 26 +#define WLAN_EXT_CAPAB_UTF_TSF_OFFSET 27 +#define WLAN_EXT_CAPAB_TPU_BUFFER_STA 28 +#define WLAN_EXT_CAPAB_TDLS_PEER_PSM 29 +#define WLAN_EXT_CAPAB_TDLS_CHANNEL_SWITCH 30 +#define WLAN_EXT_CAPAB_INTERWORKING 31 +#define WLAN_EXT_CAPAB_QOS_MAP 32 +#define WLAN_EXT_CAPAB_EBR 33 +#define WLAN_EXT_CAPAB_SSPN_INTERFACE 34 +/* 35 - Reserved */ +#define WLAN_EXT_CAPAB_MSGCF 36 +#define WLAN_EXT_CAPAB_TDLS 37 +#define WLAN_EXT_CAPAB_TDLS_PROHIBITED 38 +#define WLAN_EXT_CAPAB_TDLS_CHANNEL_SWITCH_PROHIBITED 39 +#define WLAN_EXT_CAPAB_REJECT_UNADMITTED_FRAME 40 +#define WLAN_EXT_CAPAB_ +/* 41-43 - Service Interval Granularity */ +#define WLAN_EXT_CAPAB_IDENTIFIER_LOCATION 44 +#define WLAN_EXT_CAPAB_U_APSD_COEX 45 +#define WLAN_EXT_CAPAB_WNM_NOTIFCATION 46 +#define WLAN_EXT_CAPAB_QAB 47 +#define WLAN_EXT_CAPAB_UTF_8_SSID 48 +#define WLAN_EXT_CAPAB_QMF 49 +#define WLAN_EXT_CAPAB_QMF_RECONFIG 50 +#define WLAN_EXT_CAPAB_ROBUST_AV_STREAMING 51 +#define WLAN_EXT_CAPAB_ADVANCED_GCR 52 +#define WLAN_EXT_CAPAB_MESH_GCR 53 +#define WLAN_EXT_CAPAB_SCS 54 +#define WLAN_EXT_CAPAB_QLOAD_REPORT 55 +#define WLAN_EXT_CAPAB_ALT_EDCA 56 +#define WLAN_EXT_CAPAB_UNPROT_TXOP_NEG 57 +#define WLAN_EXT_CAPAB_PROT_TXOP_NEG 58 +/* 59 - Reserved */ +#define WLAN_EXT_CAPAB_PROT_QLOAD_REPORT 60 +#define WLAN_EXT_CAPAB_TDLS_WIDER_BW 61 +#define WLAN_EXT_CAPAB_OPMODE_NOTIF 62 +#define WLAN_EXT_CAPAB_ +/* 63-64 - Max Number of MSDUs In A-MSDU */ +#define WLAN_EXT_CAPAB_CHANNEL_SCHEDULE_MGMT 65 +#define WLAN_EXT_CAPAB_GEODB_INBAND_ENABLING_SIGNAL 66 +#define WLAN_EXT_CAPAB_NETWORK_CHANNEL_CTRL 67 +#define WLAN_EXT_CAPAB_WHITE_SPACE_MAP 68 +#define WLAN_EXT_CAPAB_CHANNEL_AVAIL_QUERY 69 +#define WLAN_EXT_CAPAB_FTM_RESPONDER 70 +#define WLAN_EXT_CAPAB_FTM_INITIATOR 71 +#define WLAN_EXT_CAPAB_FILS 72 +#define WLAN_EXT_CAPAB_EXT_SPECTRUM_MGMT 73 +#define WLAN_EXT_CAPAB_FUTURE_CHANNEL_GUIDANCE 74 +#define WLAN_EXT_CAPAB_PAD 75 +/* 76-79 - Reserved */ +#define WLAN_EXT_CAPAB_COMPLETE_NON_TX_BSSID_PROFILE 80 +#define WLAN_EXT_CAPAB_SAE_PW_ID 81 +#define WLAN_EXT_CAPAB_SAE_PW_ID_EXCLUSIVELY 82 + +/* Action frame categories (IEEE Std 802.11-2016, 9.4.1.11, Table 9-76) */ #define WLAN_ACTION_SPECTRUM_MGMT 0 #define WLAN_ACTION_QOS 1 #define WLAN_ACTION_DLS 2 @@ -308,21 +565,59 @@ #define WLAN_ACTION_WNM 10 #define WLAN_ACTION_UNPROTECTED_WNM 11 #define WLAN_ACTION_TDLS 12 +#define WLAN_ACTION_MESH 13 +#define WLAN_ACTION_MULTIHOP 14 #define WLAN_ACTION_SELF_PROTECTED 15 +#define WLAN_ACTION_DMG 16 #define WLAN_ACTION_WMM 17 /* WMM Specification 1.1 */ #define WLAN_ACTION_FST 18 +#define WLAN_ACTION_ROBUST_AV_STREAMING 19 +#define WLAN_ACTION_UNPROTECTED_DMG 20 +#define WLAN_ACTION_VHT 21 +#define WLAN_ACTION_FILS 26 +#define WLAN_ACTION_VENDOR_SPECIFIC_PROTECTED 126 #define WLAN_ACTION_VENDOR_SPECIFIC 127 +/* Note: 128-255 used to report errors by setting category | 0x80 */ -/* Public action codes */ +/* Public action codes (IEEE Std 802.11-2016, 9.6.8.1, Table 9-307) */ #define WLAN_PA_20_40_BSS_COEX 0 +#define WLAN_PA_DSE_ENABLEMENT 1 +#define WLAN_PA_DSE_DEENABLEMENT 2 +#define WLAN_PA_DSE_REG_LOCATION_ANNOUNCE 3 +#define WLAN_PA_EXT_CHANNEL_SWITCH_ANNOUNCE 4 +#define WLAN_PA_DSE_MEASUREMENT_REQ 5 +#define WLAN_PA_DSE_MEASUREMENT_RESP 6 +#define WLAN_PA_MEASUREMENT_PILOT 7 +#define WLAN_PA_DSE_POWER_CONSTRAINT 8 #define WLAN_PA_VENDOR_SPECIFIC 9 #define WLAN_PA_GAS_INITIAL_REQ 10 #define WLAN_PA_GAS_INITIAL_RESP 11 #define WLAN_PA_GAS_COMEBACK_REQ 12 #define WLAN_PA_GAS_COMEBACK_RESP 13 #define WLAN_TDLS_DISCOVERY_RESPONSE 14 - -/* Protected Dual of Public Action frames */ +#define WLAN_PA_LOCATION_TRACK_NOTIFICATION 15 +#define WLAN_PA_QAB_REQUEST_FRAME 16 +#define WLAN_PA_QAB_RESPONSE_FRAME 17 +#define WLAN_PA_QMF_POLICY 18 +#define WLAN_PA_QMF_POLICY_CHANGE 19 +#define WLAN_PA_QLOAD_REQUEST 20 +#define WLAN_PA_QLOAD_REPORT 21 +#define WLAN_PA_HCCA_TXOP_ADVERTISEMENT 22 +#define WLAN_PA_HCCA_TXOP_RESPONSE 23 +#define WLAN_PA_PUBLIC_KEY 24 +#define WLAN_PA_CHANNEL_AVAILABILITY_QUERY 25 +#define WLAN_PA_CHANNEL_SCHEDULE_MANAGEMENT 26 +#define WLAN_PA_CONTACT_VERIFICATION_SIGNAL 27 +#define WLAN_PA_GDD_ENABLEMENT_REQ 28 +#define WLAN_PA_GDD_ENABLEMENT_RESP 29 +#define WLAN_PA_NETWORK_CHANNEL_CONTROL 30 +#define WLAN_PA_WHITE_SPACE_MAP_ANNOUNCEMENT 31 +#define WLAN_PA_FTM_REQUEST 32 +#define WLAN_PA_FTM 33 +#define WLAN_PA_FILS_DISCOVERY 34 + +/* Protected Dual of Public Action frames (IEEE Std 802.11-2016, 9.6.11, + * Table 9-332) */ #define WLAN_PROT_DSE_ENABLEMENT 1 #define WLAN_PROT_DSE_DEENABLEMENT 2 #define WLAN_PROT_EXT_CSA 4 @@ -334,6 +629,21 @@ #define WLAN_PROT_GAS_INITIAL_RESP 11 #define WLAN_PROT_GAS_COMEBACK_REQ 12 #define WLAN_PROT_GAS_COMEBACK_RESP 13 +#define WLAN_PROT_QAB_REQUEST_FRAME 16 +#define WLAN_PROT_QAB_RESPONSE_FRAME 17 +#define WLAN_PROT_QMF_POLICY 18 +#define WLAN_PROT_QMF_POLICY_CHANGE 19 +#define WLAN_PROT_QLOAD_REQUEST 20 +#define WLAN_PROT_QLOAD_REPORT 21 +#define WLAN_PROT_HCCA_TXOP_ADVERTISEMENT 22 +#define WLAN_PROT_HCCA_TXOP_RESPONSE 23 +#define WLAN_PROT_CHANNEL_AVAILABILITY_QUERY 25 +#define WLAN_PROT_CHANNEL_SCHEDULE_MANAGEMENT 26 +#define WLAN_PROT_CONTACT_VERIFICATION_SIGNAL 27 +#define WLAN_PROT_GDD_ENABLEMENT_REQ 28 +#define WLAN_PROT_GDD_ENABLEMENT_RESP 29 +#define WLAN_PROT_NETWORK_CHANNEL_CONTROL 30 +#define WLAN_PROT_WHITE_SPACE_MAP_ANNOUNCEMENT 31 /* SA Query Action frame (IEEE 802.11w/D8.0, 7.4.9) */ #define WLAN_SA_QUERY_REQUEST 0 @@ -362,10 +672,14 @@ #define WLAN_RRM_NEIGHBOR_REPORT_REQUEST 4 #define WLAN_RRM_NEIGHBOR_REPORT_RESPONSE 5 -/* Radio Measurement capabilities (from RRM Capabilities IE) */ +/* Radio Measurement capabilities (from RM Enabled Capabilities element) + * IEEE Std 802.11-2016, 9.4.2.45, Table 9-157 */ /* byte 1 (out of 5) */ #define WLAN_RRM_CAPS_LINK_MEASUREMENT BIT(0) #define WLAN_RRM_CAPS_NEIGHBOR_REPORT BIT(1) +#define WLAN_RRM_CAPS_BEACON_REPORT_PASSIVE BIT(4) +#define WLAN_RRM_CAPS_BEACON_REPORT_ACTIVE BIT(5) +#define WLAN_RRM_CAPS_BEACON_REPORT_TABLE BIT(6) /* byte 2 (out of 5) */ #define WLAN_RRM_CAPS_LCI_MEASUREMENT BIT(4) /* byte 5 (out of 5) */ @@ -398,16 +712,18 @@ #define INTERWORKING_ANT_TEST 6 #define INTERWORKING_ANT_WILDCARD 15 -/* Advertisement Protocol ID definitions (IEEE Std 802.11u-2011) */ +/* Advertisement Protocol ID definitions (IEEE Std 802.11-2016, Table 9-215) */ enum adv_proto_id { ACCESS_NETWORK_QUERY_PROTOCOL = 0, MIH_INFO_SERVICE = 1, MIH_CMD_AND_EVENT_DISCOVERY = 2, EMERGENCY_ALERT_SYSTEM = 3, + REGISTERED_LOCATION_QUERY_PROTO = 4, ADV_PROTO_VENDOR_SPECIFIC = 221 }; -/* Access Network Query Protocol info ID definitions (IEEE Std 802.11u-2011) */ +/* Access Network Query Protocol info ID definitions (IEEE Std 802.11-2016, + * Table 9-271; P802.11ai) */ enum anqp_info_id { ANQP_QUERY_LIST = 256, ANQP_CAPABILITY_LIST = 257, @@ -426,9 +742,14 @@ enum anqp_info_id { ANQP_TDLS_CAPABILITY = 270, ANQP_EMERGENCY_NAI = 271, ANQP_NEIGHBOR_REPORT = 272, + ANQP_QUERY_AP_LIST = 273, + ANQP_AP_LIST_RESPONSE = 274, + ANQP_FILS_REALM_INFO = 275, + ANQP_CAG = 276, ANQP_VENUE_URL = 277, ANQP_ADVICE_OF_CHARGE = 278, ANQP_LOCAL_CONTENT = 279, + ANQP_NETWORK_AUTH_TYPE_TIMESTAMP = 280, ANQP_VENDOR_SPECIFIC = 56797 }; @@ -505,6 +826,11 @@ enum lci_req_subelem { LCI_REQ_SUBELEM_MAX_AGE = 4, }; +#define FILS_NONCE_LEN 16 +#define FILS_SESSION_LEN 8 +#define FILS_CACHE_ID_LEN 2 +#define FILS_MAX_KEY_AUTH_LEN 48 + #ifdef _MSC_VER #pragma pack(push, 1) #endif /* _MSC_VER */ @@ -621,10 +947,12 @@ struct ieee80211_mgmt { struct { u8 action; u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN]; + u8 variable[]; /* OCI element */ } STRUCT_PACKED sa_query_req; struct { u8 action; /* */ u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN]; + u8 variable[]; /* OCI element */ } STRUCT_PACKED sa_query_resp; struct { u8 action; @@ -678,6 +1006,16 @@ struct ieee80211_mgmt { u8 variable[]; } STRUCT_PACKED bss_tm_query; struct { + u8 action; /* 11 */ + u8 dialog_token; + u8 req_info; + } STRUCT_PACKED coloc_intf_req; + struct { + u8 action; /* 12 */ + u8 dialog_token; + u8 variable[]; + } STRUCT_PACKED coloc_intf_report; + struct { u8 action; /* 15 */ u8 variable[]; } STRUCT_PACKED slf_prot_action; @@ -887,6 +1225,7 @@ struct ieee80211_ampe_ie { #define VHT_CAP_SUPP_CHAN_WIDTH_160MHZ ((u32) BIT(2)) #define VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ ((u32) BIT(3)) #define VHT_CAP_SUPP_CHAN_WIDTH_MASK ((u32) BIT(2) | BIT(3)) +#define VHT_CAP_SUPP_CHAN_WIDTH_MASK_SHIFT 2 #define VHT_CAP_RXLDPC ((u32) BIT(4)) #define VHT_CAP_SHORT_GI_80 ((u32) BIT(5)) #define VHT_CAP_SHORT_GI_160 ((u32) BIT(6)) @@ -953,6 +1292,15 @@ struct ieee80211_ampe_ie { #define OSEN_IE_VENDOR_TYPE 0x506f9a12 #define MBO_IE_VENDOR_TYPE 0x506f9a16 #define MBO_OUI_TYPE 22 +#define OWE_IE_VENDOR_TYPE 0x506f9a1c +#define OWE_OUI_TYPE 28 +#define MULTI_AP_OUI_TYPE 0x1B + +#define MULTI_AP_SUB_ELEM_TYPE 0x06 +#define MULTI_AP_TEAR_DOWN BIT(4) +#define MULTI_AP_FRONTHAUL_BSS BIT(5) +#define MULTI_AP_BACKHAUL_BSS BIT(6) +#define MULTI_AP_BACKHAUL_STA BIT(7) #define WMM_OUI_TYPE 2 #define WMM_OUI_SUBTYPE_INFORMATION_ELEMENT 0 @@ -1072,6 +1420,7 @@ enum wmm_ac { #define HS20_INDICATION_OUI_TYPE 16 #define HS20_ANQP_OUI_TYPE 17 #define HS20_OSEN_OUI_TYPE 18 +#define HS20_ROAMING_CONS_SEL_OUI_TYPE 29 #define HS20_STYPE_QUERY_LIST 1 #define HS20_STYPE_CAPABILITY_LIST 2 #define HS20_STYPE_OPERATOR_FRIENDLY_NAME 3 @@ -1082,21 +1431,29 @@ enum wmm_ac { #define HS20_STYPE_OSU_PROVIDERS_LIST 8 #define HS20_STYPE_ICON_REQUEST 10 #define HS20_STYPE_ICON_BINARY_FILE 11 +#define HS20_STYPE_OPERATOR_ICON_METADATA 12 +#define HS20_STYPE_OSU_PROVIDERS_NAI_LIST 13 #define HS20_DGAF_DISABLED 0x01 #define HS20_PPS_MO_ID_PRESENT 0x02 #define HS20_ANQP_DOMAIN_ID_PRESENT 0x04 -#define HS20_VERSION 0x10 /* Release 2 */ +#ifndef HS20_VERSION +#define HS20_VERSION 0x20 /* Release 3 */ +#endif /* HS20_VERSION */ /* WNM-Notification WFA vendors specific subtypes */ #define HS20_WNM_SUB_REM_NEEDED 0 #define HS20_WNM_DEAUTH_IMMINENT_NOTICE 1 +#define WFA_WNM_NOTIF_SUBELEM_NON_PREF_CHAN_REPORT 2 +#define WFA_WNM_NOTIF_SUBELEM_CELL_DATA_CAPA 3 +#define HS20_WNM_T_C_ACCEPTANCE 4 #define HS20_DEAUTH_REASON_CODE_BSS 0 #define HS20_DEAUTH_REASON_CODE_ESS 1 /* MBO v0.0_r19, 4.2: MBO Attributes */ /* Table 4-5: MBO Attributes */ +/* OCE v0.0.10, Table 4-3: OCE Attributes */ enum mbo_attr_id { MBO_ATTR_ID_AP_CAPA_IND = 1, MBO_ATTR_ID_NON_PREF_CHAN_REPORT = 2, @@ -1106,6 +1463,10 @@ enum mbo_attr_id { MBO_ATTR_ID_TRANSITION_REASON = 6, MBO_ATTR_ID_TRANSITION_REJECT_REASON = 7, MBO_ATTR_ID_ASSOC_RETRY_DELAY = 8, + OCE_ATTR_ID_CAPA_IND = 101, + OCE_ATTR_ID_RSSI_BASED_ASSOC_REJECT = 102, + OCE_ATTR_ID_REDUCED_WAN_METRICS = 103, + OCE_ATTR_ID_RNR_COMPLETENESS = 104, }; /* MBO v0.0_r19, 4.2.1: MBO AP Capability Indication Attribute */ @@ -1174,15 +1535,17 @@ enum mbo_transition_reject_reason { MBO_TRANSITION_REJECT_REASON_SERVICES = 6, }; -/* MBO v0.0_r19, 4.4: WNM-Notification vendor subelements */ -enum wfa_wnm_notif_subelem_id { - WFA_WNM_NOTIF_SUBELEM_NON_PREF_CHAN_REPORT = 2, - WFA_WNM_NOTIF_SUBELEM_CELL_DATA_CAPA = 3, -}; - -/* MBO v0.0_r25, 4.3: MBO ANQP-elements */ +/* MBO v0.0_r27, 4.3: MBO ANQP-elements */ #define MBO_ANQP_OUI_TYPE 0x12 -#define MBO_ANQP_SUBTYPE_CELL_CONN_PREF 1 +#define MBO_ANQP_SUBTYPE_QUERY_LIST 1 +#define MBO_ANQP_SUBTYPE_CELL_CONN_PREF 2 +#define MAX_MBO_ANQP_SUBTYPE MBO_ANQP_SUBTYPE_CELL_CONN_PREF + +/* OCE v0.0.10, 4.2.1: OCE Capability Indication Attribute */ +#define OCE_RELEASE 1 +#define OCE_RELEASE_MASK (BIT(0) | BIT(1) | BIT(2)) +#define OCE_IS_STA_CFON BIT(3) +#define OCE_IS_NON_OCE_AP_PRESENT BIT(4) /* Wi-Fi Direct (P2P) */ @@ -1331,7 +1694,9 @@ enum wifi_display_subelem { WFD_SUBELEM_COUPLED_SINK = 6, WFD_SUBELEM_EXT_CAPAB = 7, WFD_SUBELEM_LOCAL_IP_ADDRESS = 8, - WFD_SUBELEM_SESSION_INFO = 9 + WFD_SUBELEM_SESSION_INFO = 9, + WFD_SUBELEM_MAC_INFO = 10, + WFD_SUBELEM_R2_DEVICE_INFO = 11, }; /* 802.11s */ @@ -1363,41 +1728,6 @@ enum plink_action_field { #define VENDOR_HT_CAPAB_OUI_TYPE 0x33 /* 00-90-4c:0x33 */ -/* cipher suite selectors */ -#define WLAN_CIPHER_SUITE_USE_GROUP 0x000FAC00 -#define WLAN_CIPHER_SUITE_WEP40 0x000FAC01 -#define WLAN_CIPHER_SUITE_TKIP 0x000FAC02 -/* reserved: 0x000FAC03 */ -#define WLAN_CIPHER_SUITE_CCMP 0x000FAC04 -#define WLAN_CIPHER_SUITE_WEP104 0x000FAC05 -#define WLAN_CIPHER_SUITE_AES_CMAC 0x000FAC06 -#define WLAN_CIPHER_SUITE_NO_GROUP_ADDR 0x000FAC07 -#define WLAN_CIPHER_SUITE_GCMP 0x000FAC08 -#define WLAN_CIPHER_SUITE_GCMP_256 0x000FAC09 -#define WLAN_CIPHER_SUITE_CCMP_256 0x000FAC0A -#define WLAN_CIPHER_SUITE_BIP_GMAC_128 0x000FAC0B -#define WLAN_CIPHER_SUITE_BIP_GMAC_256 0x000FAC0C -#define WLAN_CIPHER_SUITE_BIP_CMAC_256 0x000FAC0D - -#define WLAN_CIPHER_SUITE_SMS4 0x00147201 - -#define WLAN_CIPHER_SUITE_CKIP 0x00409600 -#define WLAN_CIPHER_SUITE_CKIP_CMIC 0x00409601 -#define WLAN_CIPHER_SUITE_CMIC 0x00409602 -#define WLAN_CIPHER_SUITE_KRK 0x004096FF /* for nl80211 use only */ - -/* AKM suite selectors */ -#define WLAN_AKM_SUITE_8021X 0x000FAC01 -#define WLAN_AKM_SUITE_PSK 0x000FAC02 -#define WLAN_AKM_SUITE_FT_8021X 0x000FAC03 -#define WLAN_AKM_SUITE_FT_PSK 0x000FAC04 -#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05 -#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06 -#define WLAN_AKM_SUITE_8021X_SUITE_B 0x000FAC11 -#define WLAN_AKM_SUITE_8021X_SUITE_B_192 0x000FAC12 -#define WLAN_AKM_SUITE_CCKM 0x00409600 -#define WLAN_AKM_SUITE_OSEN 0x506f9a01 - /* IEEE 802.11v - WNM Action field values */ enum wnm_action { @@ -1559,6 +1889,117 @@ struct rrm_link_measurement_report { u8 variable[0]; } STRUCT_PACKED; +/* IEEE Std 802.11-2016, 9.4.2.21 - Measurement Request element */ +struct rrm_measurement_request_element { + u8 eid; /* Element ID */ + u8 len; /* Length */ + u8 token; /* Measurement Token */ + u8 mode; /* Measurement Request Mode */ + u8 type; /* Measurement Type */ + u8 variable[0]; /* Measurement Request */ +} STRUCT_PACKED; + +/* IEEE Std 802.11-2016, Figure 9-148 - Measurement Request Mode field */ +#define MEASUREMENT_REQUEST_MODE_PARALLEL BIT(0) +#define MEASUREMENT_REQUEST_MODE_ENABLE BIT(1) +#define MEASUREMENT_REQUEST_MODE_REQUEST BIT(2) +#define MEASUREMENT_REQUEST_MODE_REPORT BIT(3) +#define MEASUREMENT_REQUEST_MODE_DURATION_MANDATORY BIT(4) + +/* IEEE Std 802.11-2016, 9.4.2.21.7 - Beacon request */ +struct rrm_measurement_beacon_request { + u8 oper_class; /* Operating Class */ + u8 channel; /* Channel Number */ + le16 rand_interval; /* Randomization Interval (in TUs) */ + le16 duration; /* Measurement Duration (in TUs) */ + u8 mode; /* Measurement Mode */ + u8 bssid[ETH_ALEN]; /* BSSID */ + u8 variable[0]; /* Optional Subelements */ +} STRUCT_PACKED; + +/* + * IEEE Std 802.11-2016, Table 9-87 - Measurement Mode definitions for Beacon + * request + */ +enum beacon_report_mode { + BEACON_REPORT_MODE_PASSIVE = 0, + BEACON_REPORT_MODE_ACTIVE = 1, + BEACON_REPORT_MODE_TABLE = 2, +}; + +/* IEEE Std 802.11-2016, Table 9-88 - Beacon Request subelement IDs */ +/* IEEE P802.11-REVmd/D2.0, Table 9-106 - Optional subelement IDs for + * Beacon request */ +#define WLAN_BEACON_REQUEST_SUBELEM_SSID 0 +#define WLAN_BEACON_REQUEST_SUBELEM_INFO 1 /* Beacon Reporting */ +#define WLAN_BEACON_REQUEST_SUBELEM_DETAIL 2 /* Reporting Detail */ +#define WLAN_BEACON_REQUEST_SUBELEM_REQUEST 10 +#define WLAN_BEACON_REQUEST_SUBELEM_AP_CHANNEL 51 /* AP Channel Report */ +#define WLAN_BEACON_REQUEST_SUBELEM_LAST_INDICATION 164 +#define WLAN_BEACON_REQUEST_SUBELEM_VENDOR 221 + +/* + * IEEE Std 802.11-2016, Table 9-90 - Reporting Detail values + */ +enum beacon_report_detail { + /* No fixed-length fields or elements */ + BEACON_REPORT_DETAIL_NONE = 0, + /* All fixed-length fields and any requested elements in the Request + * element if present */ + BEACON_REPORT_DETAIL_REQUESTED_ONLY = 1, + /* All fixed-length fields and elements (default, used when Reporting + * Detail subelement is not included in a Beacon request) */ + BEACON_REPORT_DETAIL_ALL_FIELDS_AND_ELEMENTS = 2, +}; + +/* IEEE Std 802.11-2016, 9.4.2.22 - Measurement Report element */ +struct rrm_measurement_report_element { + u8 eid; /* Element ID */ + u8 len; /* Length */ + u8 token; /* Measurement Token */ + u8 mode; /* Measurement Report Mode */ + u8 type; /* Measurement Type */ + u8 variable[0]; /* Measurement Report */ +} STRUCT_PACKED; + +/* IEEE Std 802.11-2016, Figure 9-192 - Measurement Report Mode field */ +#define MEASUREMENT_REPORT_MODE_ACCEPT 0 +#define MEASUREMENT_REPORT_MODE_REJECT_LATE BIT(0) +#define MEASUREMENT_REPORT_MODE_REJECT_INCAPABLE BIT(1) +#define MEASUREMENT_REPORT_MODE_REJECT_REFUSED BIT(2) + +/* IEEE Std 802.11-2016, 9.4.2.22.7 - Beacon report */ +struct rrm_measurement_beacon_report { + u8 op_class; /* Operating Class */ + u8 channel; /* Channel Number */ + le64 start_time; /* Actual Measurement Start Time + * (in TSF of the BSS requesting the measurement) */ + le16 duration; /* in TUs */ + u8 report_info; /* Reported Frame Information */ + u8 rcpi; /* RCPI */ + u8 rsni; /* RSNI */ + u8 bssid[ETH_ALEN]; /* BSSID */ + u8 antenna_id; /* Antenna ID */ + le32 parent_tsf; /* Parent TSF */ + u8 variable[0]; /* Optional Subelements */ +} STRUCT_PACKED; + +/* IEEE Std 802.11-2016, Table 9-112 - Beacon report Subelement IDs */ +/* IEEE P802.11-REVmd/D2.0, Table 9-130 - Optional subelement IDs for + * Beacon report */ +#define WLAN_BEACON_REPORT_SUBELEM_FRAME_BODY 1 +#define WLAN_BEACON_REPORT_SUBELEM_FRAME_BODY_FRAGMENT_ID 2 +#define WLAN_BEACON_REPORT_SUBELEM_LAST_INDICATION 164 +#define WLAN_BEACON_REPORT_SUBELEM_VENDOR 221 + +/* IEEE P802.11-REVmd/D2.0, Table 9-232 - Data field format of the + * Reported Frame Body Fragment ID subelement */ +#define REPORTED_FRAME_BODY_SUBELEM_LEN 4 +#define REPORTED_FRAME_BODY_MORE_FRAGMENTS BIT(7) + +/* IEEE P802.11-REVmd/D2.0, 9.4.2.21.7 - Beacon report */ +#define BEACON_REPORT_LAST_INDICATION_SUBELEM_LEN 3 + /* IEEE Std 802.11ad-2012 - Multi-band element */ struct multi_band_ie { u8 eid; /* WLAN_EID_MULTI_BAND */ @@ -1660,4 +2101,83 @@ enum nr_chan_width { NR_CHAN_WIDTH_80P80 = 4, }; +struct ieee80211_he_capabilities { + u8 he_mac_capab_info[6]; + u8 he_phy_capab_info[11]; + u8 he_txrx_mcs_support[12]; /* TODO: 4, 8, or 12 octets */ + /* PPE Thresholds (optional) */ +} STRUCT_PACKED; + +struct ieee80211_he_operation { + u32 he_oper_params; /* HE Operation Parameters[3] and + * BSS Color Information[1] */ + u8 he_mcs_nss_set[2]; + u8 vht_op_info_chwidth; + u8 vht_op_info_chan_center_freq_seg0_idx; + u8 vht_op_info_chan_center_freq_seg1_idx; + /* Followed by conditional MaxBSSID Indicator subfield (u8) */ +} STRUCT_PACKED; + +/* HE Capabilities Information defines */ +#define HE_PHYCAP_SU_BEAMFORMER_CAPAB_IDX 3 +#define HE_PHYCAP_SU_BEAMFORMER_CAPAB ((u8) BIT(7)) +#define HE_PHYCAP_SU_BEAMFORMEE_CAPAB_IDX 4 +#define HE_PHYCAP_SU_BEAMFORMEE_CAPAB ((u8) BIT(0)) +#define HE_PHYCAP_MU_BEAMFORMER_CAPAB_IDX 4 +#define HE_PHYCAP_MU_BEAMFORMER_CAPAB ((u8) BIT(1)) + +/* HE Operation defines */ +/* HE Operation Parameters and BSS Color Information fields */ +#define HE_OPERATION_BSS_COLOR_MASK ((u32) (BIT(0) | BIT(1) | \ + BIT(2) | BIT(3) | \ + BIT(4) | BIT(5))) +#define HE_OPERATION_PARTIAL_BSS_COLOR ((u32) BIT(6)) +#define HE_OPERATION_BSS_COLOR_DISABLED ((u32) BIT(7)) +#define HE_OPERATION_DFLT_PE_DURATION_MASK ((u32) (BIT(8) | BIT(9) | \ + BIT(10))) +#define HE_OPERATION_DFLT_PE_DURATION_OFFSET 8 +#define HE_OPERATION_TWT_REQUIRED ((u32) BIT(11)) +#define HE_OPERATION_RTS_THRESHOLD_MASK ((u32) (BIT(12) | BIT(13) | \ + BIT(14) | BIT(15) | \ + BIT(16) | BIT(17) | \ + BIT(18) | BIT(19) | \ + BIT(20) | BIT(21))) +#define HE_OPERATION_RTS_THRESHOLD_OFFSET 12 + +struct ieee80211_he_mu_edca_parameter_set { + u8 he_qos_info; + u8 he_mu_ac_be_param[3]; + u8 he_mu_ac_bk_param[3]; + u8 he_mu_ac_vi_param[3]; + u8 he_mu_ac_vo_param[3]; +} STRUCT_PACKED; + +/* HE MU AC parameter record field format */ +/* ACI/AIFSN */ +#define HE_MU_AC_PARAM_ACI_IDX 0 +#define HE_MU_AC_PARAM_AIFSN ((u8) (BIT(0) | BIT(1) | BIT(2) | BIT(3))) +#define HE_MU_AC_PARAM_ACM ((u8) BIT(4)) +#define HE_MU_AC_PARAM_ACI ((u8) (BIT(5) | BIT(6))) +/* B7: Reserved */ + +/* ECWmin/ECWmax */ +#define HE_MU_AC_PARAM_ECW_IDX 1 +#define HE_MU_AC_PARAM_ECWMIN ((u8) (BIT(0) | BIT(1) | BIT(2) | BIT(3))) +#define HE_MU_AC_PARAM_ECWMAX ((u8) (BIT(4) | BIT(5) | BIT(6) | BIT(7))) + +/* MU EDCA Timer */ +#define HE_MU_AC_PARAM_TIMER_IDX 2 + +/* HE QoS Info field */ +#define HE_QOS_INFO_EDCA_PARAM_SET_COUNT ((u8) (BIT(0) | BIT(1) | \ + BIT(2) | BIT(3))) +#define HE_QOS_INFO_Q_ACK ((u8) (BIT(4))) +#define HE_QOS_INFO_QUEUE_REQUEST ((u8) (BIT(5))) +#define HE_QOS_INFO_TXOP_REQUEST ((u8) (BIT(6))) +/* B7: Reserved if sent by an AP; More Data Ack if sent by a non-AP STA */ +#define HE_QOS_INFO_MORE_DATA_ACK ((u8) (BIT(7))) + +/* DPP Public Action frame identifiers - OUI_WFA */ +#define DPP_OUI_TYPE 0x1A + #endif /* IEEE802_11_DEFS_H */ diff --git a/freebsd/contrib/wpa/src/common/ieee802_1x_defs.h b/freebsd/contrib/wpa/src/common/ieee802_1x_defs.h new file mode 100644 index 00000000..e7acff10 --- /dev/null +++ b/freebsd/contrib/wpa/src/common/ieee802_1x_defs.h @@ -0,0 +1,86 @@ +/* + * IEEE Std 802.1X-2010 definitions + * Copyright (c) 2013-2014, Qualcomm Atheros, Inc. + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef IEEE802_1X_DEFS_H +#define IEEE802_1X_DEFS_H + +#define CS_ID_LEN 8 +#define CS_ID_GCM_AES_128 0x0080020001000001ULL +#define CS_NAME_GCM_AES_128 "GCM-AES-128" +#define CS_ID_GCM_AES_256 0x0080c20001000002ULL +#define CS_NAME_GCM_AES_256 "GCM-AES-256" + +enum macsec_policy { + /** + * Should secure sessions. + * This accepts key server's advice to determine whether to secure the + * session or not. + */ + SHOULD_SECURE, + + /** + * Disabled MACsec - do not secure sessions. + */ + DO_NOT_SECURE, + + /** + * Should secure sessions, and try to use encryption. + * Like @SHOULD_SECURE, this follows the key server's decision. + */ + SHOULD_ENCRYPT, +}; + + +/* IEEE Std 802.1X-2010 - Table 11-6 - MACsec Capability */ +enum macsec_cap { + /** + * MACsec is not implemented + */ + MACSEC_CAP_NOT_IMPLEMENTED, + + /** + * 'Integrity without confidentiality' + */ + MACSEC_CAP_INTEGRITY, + + /** + * 'Integrity without confidentiality' and + * 'Integrity and confidentiality' with a confidentiality offset of 0 + */ + MACSEC_CAP_INTEG_AND_CONF, + + /** + * 'Integrity without confidentiality' and + * 'Integrity and confidentiality' with a confidentiality offset of 0, + * 30, 50 + */ + MACSEC_CAP_INTEG_AND_CONF_0_30_50, +}; + +enum validate_frames { + Disabled, + Checked, + Strict, +}; + +/* IEEE Std 802.1X-2010 - Table 11-6 - Confidentiality Offset */ +enum confidentiality_offset { + CONFIDENTIALITY_NONE = 0, + CONFIDENTIALITY_OFFSET_0 = 1, + CONFIDENTIALITY_OFFSET_30 = 2, + CONFIDENTIALITY_OFFSET_50 = 3, +}; + +/* IEEE Std 802.1X-2010 - Table 9-2 */ +#define DEFAULT_PRIO_INFRA_PORT 0x10 +#define DEFAULT_PRIO_PRIMRAY_AP 0x30 +#define DEFAULT_PRIO_SECONDARY_AP 0x50 +#define DEFAULT_PRIO_GROUP_CA_MEMBER 0x70 +#define DEFAULT_PRIO_NOT_KEY_SERVER 0xFF + +#endif /* IEEE802_1X_DEFS_H */ diff --git a/freebsd/contrib/wpa/src/common/ocv.h b/freebsd/contrib/wpa/src/common/ocv.h new file mode 100644 index 00000000..6379d9d0 --- /dev/null +++ b/freebsd/contrib/wpa/src/common/ocv.h @@ -0,0 +1,40 @@ +/* + * Operating Channel Validation (OCV) + * Copyright (c) 2018, Mathy Vanhoef + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef OCV_H +#define OCV_H + +struct wpa_channel_info; + +struct oci_info { + /* Values in the OCI element */ + u8 op_class; + u8 channel; + u8 seg1_idx; + + /* Derived values for easier verification */ + int freq; + int sec_channel; + int chanwidth; +}; + +#define OCV_OCI_LEN 3 +#define OCV_OCI_EXTENDED_LEN (3 + OCV_OCI_LEN) +#define OCV_OCI_KDE_LEN (2 + RSN_SELECTOR_LEN + OCV_OCI_LEN) + +extern char ocv_errorstr[256]; + +int ocv_derive_all_parameters(struct oci_info *oci); +int ocv_insert_oci(struct wpa_channel_info *ci, u8 **argpos); +int ocv_insert_oci_kde(struct wpa_channel_info *ci, u8 **argpos); +int ocv_insert_extended_oci(struct wpa_channel_info *ci, u8 *pos); +int ocv_verify_tx_params(const u8 *oci_ie, size_t oci_ie_len, + struct wpa_channel_info *ci, int tx_chanwidth, + int tx_seg1_idx); + +#endif /* OCV_H */ diff --git a/freebsd/contrib/wpa/src/common/qca-vendor.h b/freebsd/contrib/wpa/src/common/qca-vendor.h index adaec890..c34a3bc1 100644 --- a/freebsd/contrib/wpa/src/common/qca-vendor.h +++ b/freebsd/contrib/wpa/src/common/qca-vendor.h @@ -1,6 +1,7 @@ /* * Qualcomm Atheros OUI and vendor specific assignments - * Copyright (c) 2014-2015, Qualcomm Atheros, Inc. + * Copyright (c) 2014-2017, Qualcomm Atheros, Inc. + * Copyright (c) 2018, The Linux Foundation * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -41,15 +42,22 @@ enum qca_radiotap_vendor_ids { * * @QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY: Recommendation of frequency * ranges to avoid to reduce issues due to interference or internal - * co-existence information in the driver. The event data structure is - * defined in struct qca_avoid_freq_list. + * co-existence information in the driver. These frequencies aim to + * minimize the traffic but not to totally avoid the traffic. That said + * for a P2P use case, these frequencies are allowed for the P2P + * discovery/negotiation but avoid the group to get formed on these + * frequencies. The event data structure is defined in + * struct qca_avoid_freq_list. * * @QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY: Command to check driver support * for DFS offloading. * * @QCA_NL80211_VENDOR_SUBCMD_NAN: NAN command/event which is used to pass * NAN Request/Response and NAN Indication messages. These messages are - * interpreted between the framework and the firmware component. + * interpreted between the framework and the firmware component. While + * sending the command from userspace to the driver, payload is not + * encapsulated inside any attribute. Attribute QCA_WLAN_VENDOR_ATTR_NAN + * is used when receiving vendor events in userspace from the driver. * * @QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY: Set key operation that can be * used to configure PMK to the driver even when not connected. This can @@ -90,6 +98,75 @@ enum qca_radiotap_vendor_ids { * which supports DFS offloading, to indicate a radar pattern has been * detected. The channel is now unusable. * + * @QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET: Get the feature bitmap + * based on enum wifi_logger_supported_features. Attributes defined in + * enum qca_wlan_vendor_attr_get_logger_features. + * + * @QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA: Get the ring data from a particular + * logger ring, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID is passed as the + * attribute for this command. Attributes defined in + * enum qca_wlan_vendor_attr_wifi_logger_start. + * + * @QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES: Get the supported TDLS + * capabilities of the driver, parameters includes the attributes defined + * in enum qca_wlan_vendor_attr_tdls_get_capabilities. + * + * @QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS: Vendor command used to offload + * sending of certain periodic IP packet to firmware, attributes defined in + * enum qca_wlan_vendor_attr_offloaded_packets. + * + * @QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI: Command used to configure RSSI + * monitoring, defines min and max RSSI which are configured for RSSI + * monitoring. Also used to notify the RSSI breach and provides the BSSID + * and RSSI value that was breached. Attributes defined in + * enum qca_wlan_vendor_attr_rssi_monitoring. + * + * @QCA_NL80211_VENDOR_SUBCMD_NDP: Command used for performing various NAN + * Data Path (NDP) related operations, attributes defined in + * enum qca_wlan_vendor_attr_ndp_params. + * + * @QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD: Command used to enable/disable + * Neighbour Discovery offload, attributes defined in + * enum qca_wlan_vendor_attr_nd_offload. + * + * @QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER: Used to set/get the various + * configuration parameter for BPF packet filter, attributes defined in + * enum qca_wlan_vendor_attr_packet_filter. + * + * @QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE: Gets the driver-firmware + * maximum supported size, attributes defined in + * enum qca_wlan_vendor_drv_info. + * + * @QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS: Command to get various + * data about wake reasons and datapath IP statistics, attributes defined + * in enum qca_wlan_vendor_attr_wake_stats. + * + * @QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG: Command used to set configuration + * for IEEE 802.11 communicating outside the context of a basic service + * set, called OCB command. Uses the attributes defines in + * enum qca_wlan_vendor_attr_ocb_set_config. + * + * @QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME: Command used to set OCB + * UTC time. Use the attributes defines in + * enum qca_wlan_vendor_attr_ocb_set_utc_time. + * + * @QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT: Command used to start + * sending OCB timing advert frames. Uses the attributes defines in + * enum qca_wlan_vendor_attr_ocb_start_timing_advert. + * + * @QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT: Command used to stop + * OCB timing advert. Uses the attributes defines in + * enum qca_wlan_vendor_attr_ocb_stop_timing_advert. + * + * @QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER: Command used to get TSF + * timer value. Uses the attributes defines in + * enum qca_wlan_vendor_attr_ocb_get_tsf_resp. + * + * @QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES: Command/event to update the + * link properties of the respective interface. As an event, is used + * to notify the connected station's status. The attributes for this + * command are defined in enum qca_wlan_vendor_attr_link_properties. + * * @QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START: Command used to * start the P2P Listen offload function in device and pass the listen * channel, period, interval, count, device types, and vendor specific @@ -164,8 +241,11 @@ enum qca_radiotap_vendor_ids { * * @QCA_NL80211_VENDOR_SUBCMD_AOA_MEAS: Perform a standalone AOA (angle of * arrival) measurement with a single peer. Specify peer MAC address in - * QCA_WLAN_VENDOR_ATTR_MAC_ADDR and measurement type in - * QCA_WLAN_VENDOR_ATTR_AOA_TYPE. Measurement result is reported in + * QCA_WLAN_VENDOR_ATTR_MAC_ADDR and optionally frequency (MHz) in + * QCA_WLAN_VENDOR_ATTR_FREQ (if not specified, locate peer in kernel + * scan results cache and use the frequency from there). + * Also specify measurement type in QCA_WLAN_VENDOR_ATTR_AOA_TYPE. + * Measurement result is reported in * QCA_NL80211_VENDOR_SUBCMD_AOA_MEAS_RESULT event. * * @QCA_NL80211_VENDOR_SUBCMD_AOA_ABORT_MEAS: Abort an AOA measurement. Specify @@ -185,6 +265,265 @@ enum qca_radiotap_vendor_ids { * * @QCA_NL80211_VENDOR_SUBCMD_GET_CHAIN_RSSI: Get antenna RSSI value for a * specific chain. + * + * @QCA_NL80211_VENDOR_SUBCMD_DMG_RF_GET_SECTOR_CFG: Get low level + * configuration for a DMG RF sector. Specify sector index in + * QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_INDEX, sector type in + * QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_TYPE and RF modules + * to return sector information for in + * QCA_WLAN_VENDOR_ATTR_DMG_RF_MODULE_MASK. Returns sector configuration + * in QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_CFG. Also return the + * exact time where information was captured in + * QCA_WLAN_VENDOR_ATTR_TSF. + * + * @QCA_NL80211_VENDOR_SUBCMD_DMG_RF_SET_SECTOR_CFG: Set low level + * configuration for a DMG RF sector. Specify sector index in + * QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_INDEX, sector type in + * QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_TYPE and sector configuration + * for one or more DMG RF modules in + * QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_CFG. + * + * @QCA_NL80211_VENDOR_SUBCMD_DMG_RF_GET_SELECTED_SECTOR: Get selected + * DMG RF sector for a station. This is the sector that the HW + * will use to communicate with the station. Specify the MAC address + * of associated station/AP/PCP in QCA_WLAN_VENDOR_ATTR_MAC_ADDR (not + * needed for unassociated station). Specify sector type to return in + * QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_TYPE. Returns the selected + * sector index in QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_INDEX. + * Also return the exact time where the information was captured + * in QCA_WLAN_VENDOR_ATTR_TSF. + * + * @QCA_NL80211_VENDOR_SUBCMD_DMG_RF_SET_SELECTED_SECTOR: Set the + * selected DMG RF sector for a station. This is the sector that + * the HW will use to communicate with the station. + * Specify the MAC address of associated station/AP/PCP in + * QCA_WLAN_VENDOR_ATTR_MAC_ADDR, the sector type to select in + * QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_TYPE and the sector index + * in QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_INDEX. + * The selected sector will be locked such that it will not be + * modified like it normally does (for example when station + * moves around). To unlock the selected sector for a station + * pass the special value 0xFFFF in the sector index. To unlock + * all connected stations also pass a broadcast MAC address. + * + * @QCA_NL80211_VENDOR_SUBCMD_CONFIGURE_TDLS: Configure the TDLS behavior + * in the host driver. The different TDLS configurations are defined + * by the attributes in enum qca_wlan_vendor_attr_tdls_configuration. + * + * @QCA_NL80211_VENDOR_SUBCMD_GET_HE_CAPABILITIES: Query device IEEE 802.11ax HE + * capabilities. The response uses the attributes defined in + * enum qca_wlan_vendor_attr_get_he_capabilities. + * + * @QCA_NL80211_VENDOR_SUBCMD_ABORT_SCAN: Abort an ongoing vendor scan that was + * started with QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN. This command + * carries the scan cookie of the corresponding scan request. The scan + * cookie is represented by QCA_WLAN_VENDOR_ATTR_SCAN_COOKIE. + * + * @QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS: Set the Specific + * Absorption Rate (SAR) power limits. A critical regulation for + * FCC compliance, OEMs require methods to set SAR limits on TX + * power of WLAN/WWAN. enum qca_vendor_attr_sar_limits + * attributes are used with this command. + * + * @QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS: This command/event is used by the + * host driver for offloading the implementation of Auto Channel Selection + * (ACS) to an external user space entity. This interface is used as the + * event from the host driver to the user space entity and also as the + * request from the user space entity to the host driver. The event from + * the host driver is used by the user space entity as an indication to + * start the ACS functionality. The attributes used by this event are + * represented by the enum qca_wlan_vendor_attr_external_acs_event. + * User space entity uses the same interface to inform the host driver with + * selected channels after the ACS operation using the attributes defined + * by enum qca_wlan_vendor_attr_external_acs_channels. + * + * @QCA_NL80211_VENDOR_SUBCMD_CHIP_PWRSAVE_FAILURE: Vendor event carrying the + * requisite information leading to a power save failure. The information + * carried as part of this event is represented by the + * enum qca_attr_chip_power_save_failure attributes. + * + * @QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_SET: Start/Stop the NUD statistics + * collection. Uses attributes defined in enum qca_attr_nud_stats_set. + * + * @QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET: Get the NUD statistics. These + * statistics are represented by the enum qca_attr_nud_stats_get + * attributes. + * + * @QCA_NL80211_VENDOR_SUBCMD_FETCH_BSS_TRANSITION_STATUS: Sub-command to fetch + * the BSS transition status, whether accept or reject, for a list of + * candidate BSSIDs provided by the userspace. This uses the vendor + * attributes QCA_WLAN_VENDOR_ATTR_BTM_MBO_TRANSITION_REASON and + * QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO. The userspace shall specify + * the attributes QCA_WLAN_VENDOR_ATTR_BTM_MBO_TRANSITION_REASON and an + * array of QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_BSSID nested in + * QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO in the request. In the response + * the driver shall specify array of + * QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_BSSID and + * QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_STATUS pairs nested in + * QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO. + * + * @QCA_NL80211_VENDOR_SUBCMD_SET_TRACE_LEVEL: Set the trace level for a + * specific QCA module. The trace levels are represented by + * enum qca_attr_trace_level attributes. + * + * @QCA_NL80211_VENDOR_SUBCMD_BRP_SET_ANT_LIMIT: Set the Beam Refinement + * Protocol antenna limit in different modes. See enum + * qca_wlan_vendor_attr_brp_ant_limit_mode. + * + * @QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_START: Start spectral scan. The scan + * parameters are specified by enum qca_wlan_vendor_attr_spectral_scan. + * This returns a cookie (%QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_COOKIE) + * identifying the operation in success case. + * + * @QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_STOP: Stop spectral scan. This uses + * a cookie (%QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_COOKIE) from + * @QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_START to identify the scan to + * be stopped. + * + * @QCA_NL80211_VENDOR_SUBCMD_ACTIVE_TOS: Set the active Type Of Service on the + * specific interface. This can be used to modify some of the low level + * scan parameters (off channel dwell time, home channel time) in the + * driver/firmware. These parameters are maintained within the host driver. + * This command is valid only when the interface is in the connected state. + * These scan parameters shall be reset by the driver/firmware once + * disconnected. The attributes used with this command are defined in + * enum qca_wlan_vendor_attr_active_tos. + * + * @QCA_NL80211_VENDOR_SUBCMD_HANG: Event indicating to the user space that the + * driver has detected an internal failure. This event carries the + * information indicating the reason that triggered this detection. The + * attributes for this command are defined in + * enum qca_wlan_vendor_attr_hang. + * + * @QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_GET_CONFIG: Get the current values + * of spectral parameters used. The spectral scan parameters are specified + * by enum qca_wlan_vendor_attr_spectral_scan. + * + * @QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_GET_DIAG_STATS: Get the debug stats + * for spectral scan functionality. The debug stats are specified by + * enum qca_wlan_vendor_attr_spectral_diag_stats. + * + * @QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_GET_CAP_INFO: Get spectral + * scan system capabilities. The capabilities are specified + * by enum qca_wlan_vendor_attr_spectral_cap. + * + * @QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_GET_STATUS: Get the current + * status of spectral scan. The status values are specified + * by enum qca_wlan_vendor_attr_spectral_scan_status. + * + * @QCA_NL80211_VENDOR_SUBCMD_PEER_FLUSH_PENDING: Sub-command to flush + * peer pending packets. Specify the peer MAC address in + * QCA_WLAN_VENDOR_ATTR_PEER_ADDR and the access category of the packets + * in QCA_WLAN_VENDOR_ATTR_AC. The attributes are listed + * in enum qca_wlan_vendor_attr_flush_pending. + * + * @QCA_NL80211_VENDOR_SUBCMD_GET_RROP_INFO: Get vendor specific Representative + * RF Operating Parameter (RROP) information. The attributes for this + * information are defined in enum qca_wlan_vendor_attr_rrop_info. This is + * intended for use by external Auto Channel Selection applications. + * + * @QCA_NL80211_VENDOR_SUBCMD_GET_SAR_LIMITS: Get the Specific Absorption Rate + * (SAR) power limits. This is a companion to the command + * @QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS and is used to retrieve the + * settings currently in use. The attributes returned by this command are + * defined by enum qca_vendor_attr_sar_limits. + * + * @QCA_NL80211_VENDOR_SUBCMD_WLAN_MAC_INFO: Provides the current behavior of + * the WLAN hardware MAC. Also, provides the WLAN netdev interface + * information attached to the respective MAC. + * This works both as a query (user space asks the current mode) or event + * interface (driver advertising the current mode to the user space). + * Driver does not trigger this event for temporary hardware mode changes. + * Mode changes w.r.t Wi-Fi connection update (VIZ creation / deletion, + * channel change, etc.) are updated with this event. Attributes for this + * interface are defined in enum qca_wlan_vendor_attr_mac. + * + * @QCA_NL80211_VENDOR_SUBCMD_SET_QDEPTH_THRESH: Set MSDU queue depth threshold + * per peer per TID. Attributes for this command are define in + * enum qca_wlan_set_qdepth_thresh_attr. + * @QCA_NL80211_VENDOR_SUBCMD_THERMAL_CMD: Provides the thermal shutdown action + * guide for WLAN driver. Request to suspend of driver and FW if the + * temperature is higher than the suspend threshold; resume action is + * requested to driver if the temperature is lower than the resume + * threshold. In user poll mode, request temperature data by user. For test + * purpose, getting thermal shutdown configuration parameters is needed. + * Attributes for this interface are defined in + * enum qca_wlan_vendor_attr_thermal_cmd. + * @QCA_NL80211_VENDOR_SUBCMD_THERMAL_EVENT: Thermal events reported from + * driver. Thermal temperature and indication of resume completion are + * reported as thermal events. The attributes for this command are defined + * in enum qca_wlan_vendor_attr_thermal_event. + * + * @QCA_NL80211_VENDOR_SUBCMD_WIFI_TEST_CONFIGURATION: Sub command to set WiFi + * test configuration. Attributes for this command are defined in + * enum qca_wlan_vendor_attr_wifi_test_config. + * + * @QCA_NL80211_VENDOR_SUBCMD_BSS_FILTER: This command is used to configure an + * RX filter to receive frames from stations that are active on the + * operating channel, but not associated with the local device (e.g., STAs + * associated with other APs). Filtering is done based on a list of BSSIDs + * and STA MAC addresses added by the user. This command is also used to + * fetch the statistics of unassociated stations. The attributes used with + * this command are defined in enum qca_wlan_vendor_attr_bss_filter. + * + * @QCA_NL80211_VENDOR_SUBCMD_NAN_EXT: An extendable version of NAN vendor + * command. The earlier command for NAN, QCA_NL80211_VENDOR_SUBCMD_NAN, + * carried a payload which was a binary blob of data. The command was not + * extendable to send more information. The newer version carries the + * legacy blob encapsulated within an attribute and can be extended with + * additional vendor attributes that can enhance the NAN command interface. + * @QCA_NL80211_VENDOR_SUBCMD_ROAM_SCAN_EVENT: Event to indicate scan triggered + * or stopped within driver/firmware in order to initiate roaming. The + * attributes used with this event are defined in enum + * qca_wlan_vendor_attr_roam_scan. Some drivers may not send these events + * in few cases, e.g., if the host processor is sleeping when this event + * is generated in firmware. + * + * @QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG: This command is used to + * configure parameters per peer to capture Channel Frequency Response + * (CFR) and enable Periodic CFR capture. The attributes for this command + * are defined in enum qca_wlan_vendor_peer_cfr_capture_attr. + * + * @QCA_NL80211_VENDOR_SUBCMD_THROUGHPUT_CHANGE_EVENT: Event to indicate changes + * in throughput dynamically. The driver estimates the throughput based on + * number of packets being transmitted/received per second and indicates + * the changes in throughput to user space. Userspace tools can use this + * information to configure kernel's TCP parameters in order to achieve + * peak throughput. Optionally, the driver will also send guidance on + * modifications to kernel's TCP parameters which can be referred by + * userspace tools. The attributes used with this event are defined in enum + * qca_wlan_vendor_attr_throughput_change. + * + * @QCA_NL80211_VENDOR_SUBCMD_COEX_CONFIG: This command is used to set + * priorities among different types of traffic during coex scenarios. + * Current supported prioritization is among WLAN/BT/ZIGBEE with different + * profiles mentioned in enum qca_coex_config_profiles. The associated + * attributes used with this command are defined in enum + * qca_vendor_attr_coex_config. + * + * Based on the config provided, FW will boost the weight and prioritize + * the traffic for that subsystem (WLAN/BT/Zigbee). + * + * @QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_AKMS: This command is used to query + * the supported AKM suite selectorss from the driver. It returns the list + * of supported AKMs in the attribute NL80211_ATTR_AKM_SUITES. + * @QCA_NL80211_VENDOR_SUBCMD_GET_FW_STATE: This command is used to get firmware + * state from the driver. It returns the firmware state in the attribute + * QCA_WLAN_VENDOR_ATTR_FW_STATE. + * @QCA_NL80211_VENDOR_SUBCMD_PEER_STATS_CACHE_FLUSH: This vendor subcommand + * is used by the driver to flush per-peer cached statistics to user space + * application. This interface is used as an event from the driver to + * user space application. Attributes for this event are specified in + * enum qca_wlan_vendor_attr_peer_stats_cache_params. + * QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_DATA attribute is expected to be + * sent in the event. + * @QCA_NL80211_VENDOR_SUBCMD_MPTA_HELPER_CONFIG: This sub command is used to + * improve the success rate of Zigbee joining network. + * Due to PTA master limitation, Zigbee joining network success rate is + * low while WLAN is working. The WLAN driver needs to configure some + * parameters including Zigbee state and specific WLAN periods to enhance + * PTA master. All these parameters are delivered by the attributes + * defined in enum qca_mpta_helper_vendor_attr. */ enum qca_nl80211_vendor_subcmds { QCA_NL80211_VENDOR_SUBCMD_UNSPEC = 0, @@ -194,7 +533,7 @@ enum qca_nl80211_vendor_subcmds { QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY = 10, QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY = 11, QCA_NL80211_VENDOR_SUBCMD_NAN = 12, - QCA_NL80211_VENDOR_SUBMCD_STATS_EXT = 13, + QCA_NL80211_VENDOR_SUBCMD_STATS_EXT = 13, QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET = 14, QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET = 15, QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR = 16, @@ -236,11 +575,33 @@ enum qca_nl80211_vendor_subcmds { QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED = 58, QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED = 59, QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED = 60, - /* 61-73 - reserved for QCA */ + QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO = 61, + QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START = 62, + QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP = 63, + QCA_NL80211_VENDOR_SUBCMD_ROAM = 64, + QCA_NL80211_VENDOR_SUBCMD_GSCAN_SET_SSID_HOTLIST = 65, + QCA_NL80211_VENDOR_SUBCMD_GSCAN_RESET_SSID_HOTLIST = 66, + QCA_NL80211_VENDOR_SUBCMD_GSCAN_HOTLIST_SSID_FOUND = 67, + QCA_NL80211_VENDOR_SUBCMD_GSCAN_HOTLIST_SSID_LOST = 68, + QCA_NL80211_VENDOR_SUBCMD_PNO_SET_LIST = 69, + QCA_NL80211_VENDOR_SUBCMD_PNO_SET_PASSPOINT_LIST = 70, + QCA_NL80211_VENDOR_SUBCMD_PNO_RESET_PASSPOINT_LIST = 71, + QCA_NL80211_VENDOR_SUBCMD_PNO_NETWORK_FOUND = 72, + QCA_NL80211_VENDOR_SUBCMD_PNO_PASSPOINT_NETWORK_FOUND = 73, /* Wi-Fi configuration subcommands */ QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION = 74, QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_CONFIGURATION = 75, - /* 76-90 - reserved for QCA */ + QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET = 76, + QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA = 77, + QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES = 78, + QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS = 79, + QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI = 80, + QCA_NL80211_VENDOR_SUBCMD_NDP = 81, + QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD = 82, + QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER = 83, + QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE = 84, + QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS = 85, + /* 86-90 - reserved for QCA */ QCA_NL80211_VENDOR_SUBCMD_DATA_OFFLOAD = 91, QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG = 92, QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME = 93, @@ -285,21 +646,70 @@ enum qca_nl80211_vendor_subcmds { QCA_NL80211_VENDOR_SUBCMD_AOA_MEAS_RESULT = 136, QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST = 137, QCA_NL80211_VENDOR_SUBCMD_GET_CHAIN_RSSI = 138, + /* DMG low level RF sector operations */ + QCA_NL80211_VENDOR_SUBCMD_DMG_RF_GET_SECTOR_CFG = 139, + QCA_NL80211_VENDOR_SUBCMD_DMG_RF_SET_SECTOR_CFG = 140, + QCA_NL80211_VENDOR_SUBCMD_DMG_RF_GET_SELECTED_SECTOR = 141, + QCA_NL80211_VENDOR_SUBCMD_DMG_RF_SET_SELECTED_SECTOR = 142, + QCA_NL80211_VENDOR_SUBCMD_CONFIGURE_TDLS = 143, + QCA_NL80211_VENDOR_SUBCMD_GET_HE_CAPABILITIES = 144, + QCA_NL80211_VENDOR_SUBCMD_ABORT_SCAN = 145, + QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS = 146, + QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS = 147, + QCA_NL80211_VENDOR_SUBCMD_CHIP_PWRSAVE_FAILURE = 148, + QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_SET = 149, + QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET = 150, + QCA_NL80211_VENDOR_SUBCMD_FETCH_BSS_TRANSITION_STATUS = 151, + QCA_NL80211_VENDOR_SUBCMD_SET_TRACE_LEVEL = 152, + QCA_NL80211_VENDOR_SUBCMD_BRP_SET_ANT_LIMIT = 153, + QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_START = 154, + QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_STOP = 155, + QCA_NL80211_VENDOR_SUBCMD_ACTIVE_TOS = 156, + QCA_NL80211_VENDOR_SUBCMD_HANG = 157, + QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_GET_CONFIG = 158, + QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_GET_DIAG_STATS = 159, + QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_GET_CAP_INFO = 160, + QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_GET_STATUS = 161, + /* Flush peer pending data */ + QCA_NL80211_VENDOR_SUBCMD_PEER_FLUSH_PENDING = 162, + QCA_NL80211_VENDOR_SUBCMD_GET_RROP_INFO = 163, + QCA_NL80211_VENDOR_SUBCMD_GET_SAR_LIMITS = 164, + QCA_NL80211_VENDOR_SUBCMD_WLAN_MAC_INFO = 165, + QCA_NL80211_VENDOR_SUBCMD_SET_QDEPTH_THRESH = 166, + /* Thermal shutdown commands to protect wifi chip */ + QCA_NL80211_VENDOR_SUBCMD_THERMAL_CMD = 167, + QCA_NL80211_VENDOR_SUBCMD_THERMAL_EVENT = 168, + /* Wi-Fi test configuration subcommand */ + QCA_NL80211_VENDOR_SUBCMD_WIFI_TEST_CONFIGURATION = 169, + /* Frame filter operations for other BSSs/unassociated STAs */ + QCA_NL80211_VENDOR_SUBCMD_BSS_FILTER = 170, + QCA_NL80211_VENDOR_SUBCMD_NAN_EXT = 171, + QCA_NL80211_VENDOR_SUBCMD_ROAM_SCAN_EVENT = 172, + QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG = 173, + QCA_NL80211_VENDOR_SUBCMD_THROUGHPUT_CHANGE_EVENT = 174, + QCA_NL80211_VENDOR_SUBCMD_COEX_CONFIG = 175, + QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_AKMS = 176, + QCA_NL80211_VENDOR_SUBCMD_GET_FW_STATE = 177, + QCA_NL80211_VENDOR_SUBCMD_PEER_STATS_CACHE_FLUSH = 178, + QCA_NL80211_VENDOR_SUBCMD_MPTA_HELPER_CONFIG = 179, }; - enum qca_wlan_vendor_attr { QCA_WLAN_VENDOR_ATTR_INVALID = 0, /* used by QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY */ QCA_WLAN_VENDOR_ATTR_DFS = 1, - /* used by QCA_NL80211_VENDOR_SUBCMD_NAN */ + /* Used only when driver sends vendor events to the userspace under the + * command QCA_NL80211_VENDOR_SUBCMD_NAN. Not used when userspace sends + * commands to the driver. + */ QCA_WLAN_VENDOR_ATTR_NAN = 2, /* used by QCA_NL80211_VENDOR_SUBCMD_STATS_EXT */ QCA_WLAN_VENDOR_ATTR_STATS_EXT = 3, /* used by QCA_NL80211_VENDOR_SUBCMD_STATS_EXT */ QCA_WLAN_VENDOR_ATTR_IFINDEX = 4, /* used by QCA_NL80211_VENDOR_SUBCMD_ROAMING, u32 with values defined - * by enum qca_roaming_policy. */ + * by enum qca_roaming_policy. + */ QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY = 5, QCA_WLAN_VENDOR_ATTR_MAC_ADDR = 6, /* used by QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES */ @@ -387,22 +797,147 @@ enum qca_wlan_vendor_attr { QCA_WLAN_VENDOR_ATTR_AOA_MEAS_RESULT = 25, /* Used in QCA_NL80211_VENDOR_SUBCMD_GET_CHAIN_RSSI command * to specify the chain number (unsigned 32 bit value) to inquire - * the corresponding antenna RSSI value */ + * the corresponding antenna RSSI value + */ QCA_WLAN_VENDOR_ATTR_CHAIN_INDEX = 26, /* Used in QCA_NL80211_VENDOR_SUBCMD_GET_CHAIN_RSSI command - * to report the specific antenna RSSI value (unsigned 32 bit value) */ + * to report the specific antenna RSSI value (unsigned 32 bit value) + */ QCA_WLAN_VENDOR_ATTR_CHAIN_RSSI = 27, + /* Frequency in MHz, various uses. Unsigned 32 bit value */ + QCA_WLAN_VENDOR_ATTR_FREQ = 28, + /* TSF timer value, unsigned 64 bit value. + * May be returned by various commands. + */ + QCA_WLAN_VENDOR_ATTR_TSF = 29, + /* DMG RF sector index, unsigned 16 bit number. Valid values are + * 0..127 for sector indices or 65535 as special value used to + * unlock sector selection in + * QCA_NL80211_VENDOR_SUBCMD_DMG_RF_SET_SELECTED_SECTOR. + */ + QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_INDEX = 30, + /* DMG RF sector type, unsigned 8 bit value. One of the values + * in enum qca_wlan_vendor_attr_dmg_rf_sector_type. + */ + QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_TYPE = 31, + /* Bitmask of DMG RF modules for which information is requested. Each + * bit corresponds to an RF module with the same index as the bit + * number. Unsigned 32 bit number but only low 8 bits can be set since + * all DMG chips currently have up to 8 RF modules. + */ + QCA_WLAN_VENDOR_ATTR_DMG_RF_MODULE_MASK = 32, + /* Array of nested attributes where each entry is DMG RF sector + * configuration for a single RF module. + * Attributes for each entry are taken from enum + * qca_wlan_vendor_attr_dmg_rf_sector_cfg. + * Specified in QCA_NL80211_VENDOR_SUBCMD_DMG_RF_SET_SECTOR_CFG + * and returned by QCA_NL80211_VENDOR_SUBCMD_DMG_RF_GET_SECTOR_CFG. + */ + QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_CFG = 33, + /* Used in QCA_NL80211_VENDOR_SUBCMD_STATS_EXT command + * to report frame aggregation statistics to userspace. + */ + QCA_WLAN_VENDOR_ATTR_RX_AGGREGATION_STATS_HOLES_NUM = 34, + QCA_WLAN_VENDOR_ATTR_RX_AGGREGATION_STATS_HOLES_INFO = 35, + /* Unsigned 8-bit value representing MBO transition reason code as + * provided by the AP used by subcommand + * QCA_NL80211_VENDOR_SUBCMD_FETCH_BSS_TRANSITION_STATUS. This is + * specified by the userspace in the request to the driver. + */ + QCA_WLAN_VENDOR_ATTR_BTM_MBO_TRANSITION_REASON = 36, + /* Array of nested attributes, BSSID and status code, used by subcommand + * QCA_NL80211_VENDOR_SUBCMD_FETCH_BSS_TRANSITION_STATUS, where each + * entry is taken from enum qca_wlan_vendor_attr_btm_candidate_info. + * The userspace space specifies the list/array of candidate BSSIDs in + * the order of preference in the request. The driver specifies the + * status code, for each BSSID in the list, in the response. The + * acceptable candidates are listed in the order preferred by the + * driver. + */ + QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO = 37, + /* Used in QCA_NL80211_VENDOR_SUBCMD_BRP_SET_ANT_LIMIT command + * See enum qca_wlan_vendor_attr_brp_ant_limit_mode. + */ + QCA_WLAN_VENDOR_ATTR_BRP_ANT_LIMIT_MODE = 38, + /* Used in QCA_NL80211_VENDOR_SUBCMD_BRP_SET_ANT_LIMIT command + * to define the number of antennas to use for BRP. + * different purpose in each ANT_LIMIT_MODE: + * DISABLE - ignored + * EFFECTIVE - upper limit to number of antennas to be used + * FORCE - exact number of antennas to be used + * unsigned 8 bit value + */ + QCA_WLAN_VENDOR_ATTR_BRP_ANT_NUM_LIMIT = 39, + /* Used in QCA_NL80211_VENDOR_SUBCMD_GET_CHAIN_RSSI command + * to report the corresponding antenna index to the chain RSSI value + */ + QCA_WLAN_VENDOR_ATTR_ANTENNA_INFO = 40, + /* Used in QCA_NL80211_VENDOR_SUBCMD_GET_CHAIN_RSSI command to report + * the specific antenna EVM value (unsigned 32 bit value). With a + * determinate group of antennas, the driver specifies the EVM value + * for each antenna ID, and application extract them in user space. + */ + QCA_WLAN_VENDOR_ATTR_CHAIN_EVM = 41, + /* + * Used in QCA_NL80211_VENDOR_SUBCMD_GET_FW_STATE command to report + * wlan firmware current state. FW state is an unsigned 8 bit value, + * one of the values in enum qca_wlan_vendor_attr_fw_state. + */ + QCA_WLAN_VENDOR_ATTR_FW_STATE = 42, + /* keep last */ QCA_WLAN_VENDOR_ATTR_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_MAX = QCA_WLAN_VENDOR_ATTR_AFTER_LAST - 1, }; - enum qca_roaming_policy { QCA_ROAMING_NOT_ALLOWED, QCA_ROAMING_ALLOWED_WITHIN_ESS, }; +/** + * enum qca_roam_reason - Represents the reason codes for roaming. Used by + * QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REASON. + * + * @QCA_ROAM_REASON_UNKNOWN: Any reason that do not classify under the below + * reasons. + * + * @QCA_ROAM_REASON_PER: Roam triggered when packet error rates (PER) breached + * the configured threshold. + * + * @QCA_ROAM_REASON_BEACON_MISS: Roam triggered due to the continuous configured + * beacon misses from the then connected AP. + * + * @QCA_ROAM_REASON_POOR_RSSI: Roam triggered due to the poor RSSI reported + * by the connected AP. + * + * @QCA_ROAM_REASON_BETTER_RSSI: Roam triggered for finding a BSS with a better + * RSSI than the connected BSS. Here the RSSI of the current BSS is not poor. + * + * @QCA_ROAM_REASON_CONGESTION: Roam triggered considering the connected channel + * or environment being very noisy or congested. + * + * @QCA_ROAM_REASON_EXPLICIT_REQUEST: Roam triggered due to an explicit request + * from the user (user space). + * + * @QCA_ROAM_REASON_BTM: Roam triggered due to BTM Request frame received from + * the connected AP. + * + * @QCA_ROAM_REASON_BSS_LOAD: Roam triggered due to the channel utilization + * breaching out the configured threshold. + */ +enum qca_roam_reason { + QCA_ROAM_REASON_UNKNOWN, + QCA_ROAM_REASON_PER, + QCA_ROAM_REASON_BEACON_MISS, + QCA_ROAM_REASON_POOR_RSSI, + QCA_ROAM_REASON_BETTER_RSSI, + QCA_ROAM_REASON_CONGESTION, + QCA_ROAM_REASON_USER_TRIGGER, + QCA_ROAM_REASON_BTM, + QCA_ROAM_REASON_BSS_LOAD, +}; + enum qca_wlan_vendor_attr_roam_auth { QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_INVALID = 0, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID, @@ -413,6 +948,43 @@ enum qca_wlan_vendor_attr_roam_auth { QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS, + /* Indicates the status of re-association requested by user space for + * the BSSID specified by QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID. + * Type u16. + * Represents the status code from AP. Use + * %WLAN_STATUS_UNSPECIFIED_FAILURE if the device cannot give you the + * real status code for failures. + */ + QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_STATUS, + /* This attribute indicates that the old association was maintained when + * a re-association is requested by user space and that re-association + * attempt fails (i.e., cannot connect to the requested BSS, but can + * remain associated with the BSS with which the association was in + * place when being requested to roam). Used along with + * WLAN_VENDOR_ATTR_ROAM_AUTH_STATUS to indicate the current + * re-association status. Type flag. + * This attribute is applicable only for re-association failure cases. + */ + QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RETAIN_CONNECTION, + /* This attribute specifies the PMK if one was newly generated during + * FILS roaming. This is added to the PMKSA cache and is used in + * subsequent connections with PMKSA caching. + */ + QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PMK = 11, + /* This attribute specifies the PMKID used/generated for the current + * FILS roam. This is used in subsequent connections with PMKSA caching. + */ + QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PMKID = 12, + /* A 16-bit unsigned value specifying the next sequence number to use + * in ERP message in the currently associated realm. This is used in + * doing subsequent ERP based connections in the same realm. + */ + QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_FILS_ERP_NEXT_SEQ_NUM = 13, + /* A 16-bit unsigned value representing the reasons for the roaming. + * Defined by enum qca_roam_reason. + */ + QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REASON = 14, + /* keep last */ QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_MAX = @@ -493,13 +1065,25 @@ enum qca_wlan_vendor_acs_hw_mode { * @QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY: Device supports automatic * band selection based on channel selection results. * @QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS: Device supports - * simultaneous off-channel operations. + * simultaneous off-channel operations. * @QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD: Device supports P2P * Listen offload; a mechanism where the station's firmware takes care of * responding to incoming Probe Request frames received from other P2P * Devices whilst in Listen state, rather than having the user space * wpa_supplicant do it. Information from received P2P requests are * forwarded from firmware to host whenever the host processor wakes up. + * @QCA_WLAN_VENDOR_FEATURE_OCE_STA: Device supports all OCE non-AP STA + * specific features. + * @QCA_WLAN_VENDOR_FEATURE_OCE_AP: Device supports all OCE AP specific + * features. + * @QCA_WLAN_VENDOR_FEATURE_OCE_STA_CFON: Device supports OCE STA-CFON + * specific features only. If a Device sets this bit but not the + * %QCA_WLAN_VENDOR_FEATURE_OCE_AP, the userspace shall assume that + * this Device may not support all OCE AP functionalities but can support + * only OCE STA-CFON functionalities. + * @QCA_WLAN_VENDOR_FEATURE_SELF_MANAGED_REGULATORY: Device supports self + * managed regulatory. + * @QCA_WLAN_VENDOR_FEATURE_TWT: Device supports TWT (Target Wake Time). * @NUM_QCA_WLAN_VENDOR_FEATURES: Number of assigned feature bits */ enum qca_wlan_vendor_features { @@ -507,6 +1091,11 @@ enum qca_wlan_vendor_features { QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY = 1, QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS = 2, QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD = 3, + QCA_WLAN_VENDOR_FEATURE_OCE_STA = 4, + QCA_WLAN_VENDOR_FEATURE_OCE_AP = 5, + QCA_WLAN_VENDOR_FEATURE_OCE_STA_CFON = 6, + QCA_WLAN_VENDOR_FEATURE_SELF_MANAGED_REGULATORY = 7, + QCA_WLAN_VENDOR_FEATURE_TWT = 8, NUM_QCA_WLAN_VENDOR_FEATURES /* keep last */ }; @@ -532,6 +1121,112 @@ enum qca_wlan_vendor_attr_data_offload_ind { QCA_WLAN_VENDOR_ATTR_DATA_OFFLOAD_IND_AFTER_LAST - 1 }; +/** + * enum qca_wlan_vendor_attr_ocb_set_config - Vendor subcmd attributes to set + * OCB config + * + * @QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_CHANNEL_COUNT: Number of channels in the + * configuration + * @QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_SCHEDULE_SIZE: Size of the schedule + * @QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_CHANNEL_ARRAY: Array of channels + * @QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_SCHEDULE_ARRAY: Array of channels to be + * scheduled + * @QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_NDL_CHANNEL_ARRAY: Array of NDL channel + * information + * @QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_NDL_ACTIVE_STATE_ARRAY: Array of NDL + * active state configuration + * @QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_FLAGS: Configuration flags such as + * OCB_CONFIG_FLAG_80211_FRAME_MODE + * @QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_DEF_TX_PARAM: Default TX parameters to + * use in the case that a packet is sent without a TX control header + * @QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_TA_MAX_DURATION: Max duration after the + * last TA received that the local time set by TA is synchronous to other + * communicating OCB STAs. + */ +enum qca_wlan_vendor_attr_ocb_set_config { + QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_CHANNEL_COUNT = 1, + QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_SCHEDULE_SIZE = 2, + QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_CHANNEL_ARRAY = 3, + QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_SCHEDULE_ARRAY = 4, + QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_NDL_CHANNEL_ARRAY = 5, + QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_NDL_ACTIVE_STATE_ARRAY = 6, + QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_FLAGS = 7, + QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_DEF_TX_PARAM = 8, + QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_TA_MAX_DURATION = 9, + QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_MAX = + QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_AFTER_LAST - 1 +}; + +/** + * enum qca_wlan_vendor_attr_ocb_set_utc_time - Vendor subcmd attributes to set + * UTC time + * + * @QCA_WLAN_VENDOR_ATTR_OCB_SET_UTC_TIME_VALUE: The UTC time as an array of + * 10 bytes + * @QCA_WLAN_VENDOR_ATTR_OCB_SET_UTC_TIME_ERROR: The time error as an array of + * 5 bytes + */ +enum qca_wlan_vendor_attr_ocb_set_utc_time { + QCA_WLAN_VENDOR_ATTR_OCB_SET_UTC_TIME_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_OCB_SET_UTC_TIME_VALUE = 1, + QCA_WLAN_VENDOR_ATTR_OCB_SET_UTC_TIME_ERROR = 2, + QCA_WLAN_VENDOR_ATTR_OCB_SET_UTC_TIME_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_OCB_SET_UTC_TIME_MAX = + QCA_WLAN_VENDOR_ATTR_OCB_SET_UTC_TIME_AFTER_LAST - 1 +}; + +/** + * enum qca_wlan_vendor_attr_ocb_start_timing_advert - Vendor subcmd attributes + * to start sending timing advert frames + * + * @QCA_WLAN_VENDOR_ATTR_OCB_START_TIMING_ADVERT_CHANNEL_FREQ: Cannel frequency + * on which to send the frames + * @QCA_WLAN_VENDOR_ATTR_OCB_START_TIMING_ADVERT_REPEAT_RATE: Number of times + * the frame is sent in 5 seconds + */ +enum qca_wlan_vendor_attr_ocb_start_timing_advert { + QCA_WLAN_VENDOR_ATTR_OCB_START_TIMING_ADVERT_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_OCB_START_TIMING_ADVERT_CHANNEL_FREQ = 1, + QCA_WLAN_VENDOR_ATTR_OCB_START_TIMING_ADVERT_REPEAT_RATE = 2, + QCA_WLAN_VENDOR_ATTR_OCB_START_TIMING_ADVERT_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_OCB_START_TIMING_ADVERT_MAX = + QCA_WLAN_VENDOR_ATTR_OCB_START_TIMING_ADVERT_AFTER_LAST - 1 +}; + +/** + * enum qca_wlan_vendor_attr_ocb_stop_timing_advert - Vendor subcmd attributes + * to stop timing advert + * + * @QCA_WLAN_VENDOR_ATTR_OCB_STOP_TIMING_ADVERT_CHANNEL_FREQ: The channel + * frequency on which to stop the timing advert + */ +enum qca_wlan_vendor_attr_ocb_stop_timing_advert { + QCA_WLAN_VENDOR_ATTR_OCB_STOP_TIMING_ADVERT_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_OCB_STOP_TIMING_ADVERT_CHANNEL_FREQ = 1, + QCA_WLAN_VENDOR_ATTR_OCB_STOP_TIMING_ADVERT_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_OCB_STOP_TIMING_ADVERT_MAX = + QCA_WLAN_VENDOR_ATTR_OCB_STOP_TIMING_ADVERT_AFTER_LAST - 1 +}; + +/** + * enum qca_wlan_vendor_attr_ocb_get_tsf_response - Vendor subcmd attributes to + * get TSF timer value + * + * @QCA_WLAN_VENDOR_ATTR_OCB_GET_TSF_RESP_TIMER_HIGH: Higher 32 bits of the + * timer + * @QCA_WLAN_VENDOR_ATTR_OCB_GET_TSF_RESP_TIMER_LOW: Lower 32 bits of the timer + */ +enum qca_wlan_vendor_attr_ocb_get_tsf_resp { + QCA_WLAN_VENDOR_ATTR_OCB_GET_TSF_RESP_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_OCB_GET_TSF_RESP_TIMER_HIGH = 1, + QCA_WLAN_VENDOR_ATTR_OCB_GET_TSF_RESP_TIMER_LOW = 2, + QCA_WLAN_VENDOR_ATTR_OCB_GET_TSF_RESP_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_OCB_GET_TSF_RESP_MAX = + QCA_WLAN_VENDOR_ATTR_OCB_GET_TSF_RESP_AFTER_LAST - 1 +}; + enum qca_vendor_attr_get_preferred_freq_list { QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_INVALID, /* A 32-unsigned value; the interface type/mode for which the preferred @@ -544,6 +1239,12 @@ enum qca_vendor_attr_get_preferred_freq_list { * from kernel space to user space. */ QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST, + /* An array of nested values as per enum qca_wlan_vendor_attr_pcl + * attribute. Each element contains frequency (MHz), weight, and flag + * bit mask indicating how the frequency should be used in P2P + * negotiation; sent from kernel space to user space. + */ + QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_WEIGHED_PCL, /* keep last */ QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX = @@ -679,11 +1380,39 @@ enum qca_vendor_attr_wisa_cmd { * vendor specific element is defined by the latest P802.11ax draft. * Please note that the draft is still work in progress and this element * payload is subject to change. + * + * @QCA_VENDOR_ELEM_RAPS: RAPS element (OFDMA-based Random Access Parameter Set + * element). + * This element can be used for pre-standard publication testing of HE + * before P802.11ax draft assigns the element ID extension. The payload of + * this vendor specific element is defined by the latest P802.11ax draft + * (not including the Element ID Extension field). Please note that the + * draft is still work in progress and this element payload is subject to + * change. + * + * @QCA_VENDOR_ELEM_MU_EDCA_PARAMS: MU EDCA Parameter Set element. + * This element can be used for pre-standard publication testing of HE + * before P802.11ax draft assigns the element ID extension. The payload of + * this vendor specific element is defined by the latest P802.11ax draft + * (not including the Element ID Extension field). Please note that the + * draft is still work in progress and this element payload is subject to + * change. + * + * @QCA_VENDOR_ELEM_BSS_COLOR_CHANGE: BSS Color Change Announcement element. + * This element can be used for pre-standard publication testing of HE + * before P802.11ax draft assigns the element ID extension. The payload of + * this vendor specific element is defined by the latest P802.11ax draft + * (not including the Element ID Extension field). Please note that the + * draft is still work in progress and this element payload is subject to + * change. */ enum qca_vendor_element_id { QCA_VENDOR_ELEM_P2P_PREF_CHAN_LIST = 0, QCA_VENDOR_ELEM_HE_CAPAB = 1, QCA_VENDOR_ELEM_HE_OPER = 2, + QCA_VENDOR_ELEM_RAPS = 3, + QCA_VENDOR_ELEM_MU_EDCA_PARAMS = 4, + QCA_VENDOR_ELEM_BSS_COLOR_CHANGE = 5, }; /** @@ -696,29 +1425,32 @@ enum qca_vendor_element_id { * @QCA_WLAN_VENDOR_ATTR_SCAN_SUPP_RATES: Nested array attribute of supported * rates to be included * @QCA_WLAN_VENDOR_ATTR_SCAN_TX_NO_CCK_RATE: flag used to send probe requests - * at non CCK rate in 2GHz band + * at non CCK rate in 2GHz band * @QCA_WLAN_VENDOR_ATTR_SCAN_FLAGS: Unsigned 32-bit scan flags * @QCA_WLAN_VENDOR_ATTR_SCAN_COOKIE: Unsigned 64-bit cookie provided by the - * driver for the specific scan request + * driver for the specific scan request * @QCA_WLAN_VENDOR_ATTR_SCAN_STATUS: Unsigned 8-bit status of the scan - * request decoded as in enum scan_status + * request decoded as in enum scan_status * @QCA_WLAN_VENDOR_ATTR_SCAN_MAC: 6-byte MAC address to use when randomisation - * scan flag is set + * scan flag is set * @QCA_WLAN_VENDOR_ATTR_SCAN_MAC_MASK: 6-byte MAC address mask to be used with - * randomisation + * randomisation + * @QCA_WLAN_VENDOR_ATTR_SCAN_BSSID: 6-byte MAC address representing the + * specific BSSID to scan for. */ enum qca_wlan_vendor_attr_scan { QCA_WLAN_VENDOR_ATTR_SCAN_INVALID_PARAM = 0, - QCA_WLAN_VENDOR_ATTR_SCAN_IE, - QCA_WLAN_VENDOR_ATTR_SCAN_FREQUENCIES, - QCA_WLAN_VENDOR_ATTR_SCAN_SSIDS, - QCA_WLAN_VENDOR_ATTR_SCAN_SUPP_RATES, - QCA_WLAN_VENDOR_ATTR_SCAN_TX_NO_CCK_RATE, - QCA_WLAN_VENDOR_ATTR_SCAN_FLAGS, - QCA_WLAN_VENDOR_ATTR_SCAN_COOKIE, - QCA_WLAN_VENDOR_ATTR_SCAN_STATUS, - QCA_WLAN_VENDOR_ATTR_SCAN_MAC, - QCA_WLAN_VENDOR_ATTR_SCAN_MAC_MASK, + QCA_WLAN_VENDOR_ATTR_SCAN_IE = 1, + QCA_WLAN_VENDOR_ATTR_SCAN_FREQUENCIES = 2, + QCA_WLAN_VENDOR_ATTR_SCAN_SSIDS = 3, + QCA_WLAN_VENDOR_ATTR_SCAN_SUPP_RATES = 4, + QCA_WLAN_VENDOR_ATTR_SCAN_TX_NO_CCK_RATE = 5, + QCA_WLAN_VENDOR_ATTR_SCAN_FLAGS = 6, + QCA_WLAN_VENDOR_ATTR_SCAN_COOKIE = 7, + QCA_WLAN_VENDOR_ATTR_SCAN_STATUS = 8, + QCA_WLAN_VENDOR_ATTR_SCAN_MAC = 9, + QCA_WLAN_VENDOR_ATTR_SCAN_MAC_MASK = 10, + QCA_WLAN_VENDOR_ATTR_SCAN_BSSID = 11, QCA_WLAN_VENDOR_ATTR_SCAN_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_SCAN_MAX = QCA_WLAN_VENDOR_ATTR_SCAN_AFTER_LAST - 1 @@ -726,10 +1458,10 @@ enum qca_wlan_vendor_attr_scan { /** * enum scan_status - Specifies the valid values the vendor scan attribute - * QCA_WLAN_VENDOR_ATTR_SCAN_STATUS can take + * QCA_WLAN_VENDOR_ATTR_SCAN_STATUS can take * * @VENDOR_SCAN_STATUS_NEW_RESULTS: implies the vendor scan is successful with - * new scan results + * new scan results * @VENDOR_SCAN_STATUS_ABORTED: implies the vendor scan was aborted in-between */ enum scan_status { @@ -776,7 +1508,8 @@ enum qca_vendor_attr_txpower_scale { enum qca_vendor_attr_txpower_decr_db { QCA_WLAN_VENDOR_ATTR_TXPOWER_DECR_DB_INVALID, /* 8-bit unsigned value to indicate the reduction of TX power in dB for - * a virtual interface. */ + * a virtual interface. + */ QCA_WLAN_VENDOR_ATTR_TXPOWER_DECR_DB, /* keep last */ QCA_WLAN_VENDOR_ATTR_TXPOWER_DECR_DB_AFTER_LAST, @@ -826,29 +1559,37 @@ enum qca_wlan_vendor_attr_config { */ QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND = 7, /* 8-bit unsigned value to configure the maximum TX MPDU for - * aggregation. */ + * aggregation. + */ QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION = 8, /* 8-bit unsigned value to configure the maximum RX MPDU for - * aggregation. */ + * aggregation. + */ QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION = 9, /* 8-bit unsigned value to configure the Non aggregrate/11g sw - * retry threshold (0 disable, 31 max). */ + * retry threshold (0 disable, 31 max). + */ QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY = 10, /* 8-bit unsigned value to configure the aggregrate sw - * retry threshold (0 disable, 31 max). */ + * retry threshold (0 disable, 31 max). + */ QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY = 11, /* 8-bit unsigned value to configure the MGMT frame - * retry threshold (0 disable, 31 max). */ + * retry threshold (0 disable, 31 max). + */ QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY = 12, /* 8-bit unsigned value to configure the CTRL frame - * retry threshold (0 disable, 31 max). */ + * retry threshold (0 disable, 31 max). + */ QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY = 13, /* 8-bit unsigned value to configure the propagation delay for - * 2G/5G band (0~63, units in us) */ + * 2G/5G band (0~63, units in us) + */ QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY = 14, /* Unsigned 32-bit value to configure the number of unicast TX fail * packet count. The peer is disconnected once this threshold is - * reached. */ + * reached. + */ QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT = 15, /* Attribute used to set scan default IEs to the driver. * @@ -859,7 +1600,8 @@ enum qca_wlan_vendor_attr_config { * merged with the IEs received along with scan request coming to the * driver. If a particular IE is present in the scan default IEs but not * present in the scan request, then that IE should be added to the IEs - * sent in the Probe Request frames for that scan request. */ + * sent in the Probe Request frames for that scan request. + */ QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES = 16, /* Unsigned 32-bit attribute for generic commands */ QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_COMMAND = 17, @@ -868,42 +1610,183 @@ enum qca_wlan_vendor_attr_config { /* Unsigned 32-bit data attribute for generic command response */ QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_DATA = 19, /* Unsigned 32-bit length attribute for - * QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_DATA */ + * QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_DATA + */ QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_LENGTH = 20, /* Unsigned 32-bit flags attribute for - * QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_DATA */ + * QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_DATA + */ QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_FLAGS = 21, /* Unsigned 32-bit, defining the access policy. * See enum qca_access_policy. Used with - * QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST. */ + * QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST. + */ QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY = 22, /* Sets the list of full set of IEs for which a specific access policy * has to be applied. Used along with * QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY to control the access. - * Zero length payload can be used to clear this access constraint. */ + * Zero length payload can be used to clear this access constraint. + */ QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST = 23, /* Unsigned 32-bit, specifies the interface index (netdev) for which the * corresponding configurations are applied. If the interface index is * not specified, the configurations are attributed to the respective - * wiphy. */ + * wiphy. + */ QCA_WLAN_VENDOR_ATTR_CONFIG_IFINDEX = 24, /* 8-bit unsigned value to trigger QPower: 1-Enable, 0-Disable */ QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER = 25, /* 8-bit unsigned value to configure the driver and below layers to * ignore the assoc disallowed set by APs while connecting - * 1-Ignore, 0-Don't ignore */ + * 1-Ignore, 0-Don't ignore + */ QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED = 26, /* 32-bit unsigned value to trigger antenna diversity features: - * 1-Enable, 0-Disable */ + * 1-Enable, 0-Disable + */ QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_ENA = 27, /* 32-bit unsigned value to configure specific chain antenna */ QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_CHAIN = 28, /* 32-bit unsigned value to trigger cycle selftest - * 1-Enable, 0-Disable */ + * 1-Enable, 0-Disable + */ QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST = 29, /* 32-bit unsigned to configure the cycle time of selftest - * the unit is micro-second */ + * the unit is micro-second + */ QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST_INTVL = 30, + /* 32-bit unsigned value to set reorder timeout for AC_VO */ + QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_VOICE = 31, + /* 32-bit unsigned value to set reorder timeout for AC_VI */ + QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_VIDEO = 32, + /* 32-bit unsigned value to set reorder timeout for AC_BE */ + QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_BESTEFFORT = 33, + /* 32-bit unsigned value to set reorder timeout for AC_BK */ + QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_BACKGROUND = 34, + /* 6-byte MAC address to point out the specific peer */ + QCA_WLAN_VENDOR_ATTR_CONFIG_RX_BLOCKSIZE_PEER_MAC = 35, + /* 32-bit unsigned value to set window size for specific peer */ + QCA_WLAN_VENDOR_ATTR_CONFIG_RX_BLOCKSIZE_WINLIMIT = 36, + /* 8-bit unsigned value to set the beacon miss threshold in 2.4 GHz */ + QCA_WLAN_VENDOR_ATTR_CONFIG_BEACON_MISS_THRESHOLD_24 = 37, + /* 8-bit unsigned value to set the beacon miss threshold in 5 GHz */ + QCA_WLAN_VENDOR_ATTR_CONFIG_BEACON_MISS_THRESHOLD_5 = 38, + /* 32-bit unsigned value to configure 5 or 10 MHz channel width for + * station device while in disconnect state. The attribute use the + * value of enum nl80211_chan_width: NL80211_CHAN_WIDTH_5 means 5 MHz, + * NL80211_CHAN_WIDTH_10 means 10 MHz. If set, the device work in 5 or + * 10 MHz channel width, the station will not connect to a BSS using 20 + * MHz or higher bandwidth. Set to NL80211_CHAN_WIDTH_20_NOHT to + * clear this constraint. + */ + QCA_WLAN_VENDOR_ATTR_CONFIG_SUB20_CHAN_WIDTH = 39, + /* 32-bit unsigned value to configure the propagation absolute delay + * for 2G/5G band (units in us) + */ + QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_ABS_DELAY = 40, + /* 32-bit unsigned value to set probe period */ + QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_PROBE_PERIOD = 41, + /* 32-bit unsigned value to set stay period */ + QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_STAY_PERIOD = 42, + /* 32-bit unsigned value to set snr diff */ + QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SNR_DIFF = 43, + /* 32-bit unsigned value to set probe dwell time */ + QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_PROBE_DWELL_TIME = 44, + /* 32-bit unsigned value to set mgmt snr weight */ + QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_MGMT_SNR_WEIGHT = 45, + /* 32-bit unsigned value to set data snr weight */ + QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_DATA_SNR_WEIGHT = 46, + /* 32-bit unsigned value to set ack snr weight */ + QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_ACK_SNR_WEIGHT = 47, + /* 32-bit unsigned value to configure the listen interval. + * This is in units of beacon intervals. This configuration alters + * the negotiated listen interval with the AP during the connection. + * It is highly recommended to configure a value less than or equal to + * the one negotiated during the association. Configuring any greater + * value can have adverse effects (frame loss, AP disassociating STA, + * etc.). + */ + QCA_WLAN_VENDOR_ATTR_CONFIG_LISTEN_INTERVAL = 48, + /* + * 8 bit unsigned value that is set on an AP/GO virtual interface to + * disable operations that would cause the AP/GO to leave its operating + * channel. + * + * This will restrict the scans to the AP/GO operating channel and the + * channels of the other band, if DBS is supported.A STA/CLI interface + * brought up after this setting is enabled, will be restricted to + * connecting to devices only on the AP/GO interface's operating channel + * or on the other band in DBS case. P2P supported channel list is + * modified, to only include AP interface's operating-channel and the + * channels of the other band if DBS is supported. + * + * These restrictions are only applicable as long as the AP/GO interface + * is alive. If the AP/GO interface is brought down then this + * setting/restriction is forgotten. + * + * If this variable is set on an AP/GO interface while a multi-channel + * concurrent session is active, it has no effect on the operation of + * the current interfaces, other than restricting the scan to the AP/GO + * operating channel and the other band channels if DBS is supported. + * However, if the STA is brought down and restarted then the new STA + * connection will either be formed on the AP/GO channel or on the + * other band in a DBS case. This is because of the scan being + * restricted on these channels as mentioned above. + * + * 1-Restrict / 0-Don't restrict offchannel operations. + */ + QCA_WLAN_VENDOR_ATTR_CONFIG_RESTRICT_OFFCHANNEL = 49, + /* + * 8 bit unsigned value to enable/disable LRO (Large Receive Offload) + * on an interface. + * 1 - Enable, 0 - Disable. + */ + QCA_WLAN_VENDOR_ATTR_CONFIG_LRO = 50, + + /* + * 8 bit unsigned value to globally enable/disable scan + * 1 - Enable, 0 - Disable. + */ + QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_ENABLE = 51, + + /* 8-bit unsigned value to set the total beacon miss count + * This parameter will set the total beacon miss count. + */ + QCA_WLAN_VENDOR_ATTR_CONFIG_TOTAL_BEACON_MISS_COUNT = 52, + + /* Unsigned 32-bit value to configure the number of continuous + * Beacon Miss which shall be used by the firmware to penalize + * the RSSI for BTC. + */ + QCA_WLAN_VENDOR_ATTR_CONFIG_PENALIZE_AFTER_NCONS_BEACON_MISS_BTC = 53, + + /* 8-bit unsigned value to configure the driver and below layers to + * enable/disable all FILS features. + * 0-enable, 1-disable + */ + QCA_WLAN_VENDOR_ATTR_CONFIG_DISABLE_FILS = 54, + + /* 16-bit unsigned value to configure the level of WLAN latency + * module. See enum qca_wlan_vendor_attr_config_latency_level. + */ + QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL = 55, + + /* 8-bit unsigned value indicating the driver to use the RSNE as-is from + * the connect interface. Exclusively used for the scenarios where the + * device is used as a test bed device with special functionality and + * not recommended for production. This helps driver to not validate the + * RSNE passed from user space and thus allow arbitrary IE data to be + * used for testing purposes. + * 1-enable, 0-disable. + * Applications set/reset this configuration. If not reset, this + * parameter remains in use until the driver is unloaded. + */ + QCA_WLAN_VENDOR_ATTR_CONFIG_RSN_IE = 56, + + /* 8-bit unsigned value to trigger green Tx power saving. + * 1-Enable, 0-Disable + */ + QCA_WLAN_VENDOR_ATTR_CONFIG_GTX = 57, /* keep last */ QCA_WLAN_VENDOR_ATTR_CONFIG_AFTER_LAST, @@ -937,7 +1820,8 @@ enum qca_wlan_vendor_attr_sap_config { enum qca_wlan_vendor_attr_sap_conditional_chan_switch { QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_INVALID = 0, /* Priority based frequency list (an array of u32 values in host byte - * order) */ + * order) + */ QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST = 1, /* Status of the conditional switch (u32). * 0: Success, Non-zero: Failure @@ -972,6 +1856,36 @@ enum qca_wlan_gpio_attr { }; /** + * qca_wlan_set_qdepth_thresh_attr - Parameters for setting + * MSDUQ depth threshold per peer per tid in the target + * + * Associated Vendor Command: + * QCA_NL80211_VENDOR_SUBCMD_SET_QDEPTH_THRESH + */ +enum qca_wlan_set_qdepth_thresh_attr { + QCA_WLAN_VENDOR_ATTR_QDEPTH_THRESH_INVALID = 0, + /* 6-byte MAC address */ + QCA_WLAN_VENDOR_ATTR_QDEPTH_THRESH_MAC_ADDR, + /* Unsigned 32-bit attribute for holding the TID */ + QCA_WLAN_VENDOR_ATTR_QDEPTH_THRESH_TID, + /* Unsigned 32-bit attribute for holding the update mask + * bit 0 - Update high priority msdu qdepth threshold + * bit 1 - Update low priority msdu qdepth threshold + * bit 2 - Update UDP msdu qdepth threshold + * bit 3 - Update Non UDP msdu qdepth threshold + * rest of bits are reserved + */ + QCA_WLAN_VENDOR_ATTR_QDEPTH_THRESH_UPDATE_MASK, + /* Unsigned 32-bit attribute for holding the threshold value */ + QCA_WLAN_VENDOR_ATTR_QDEPTH_THRESH_VALUE, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_QDEPTH_THRESH_LAST, + QCA_WLAN_VENDOR_ATTR_QDEPTH_THRESH_MAX = + QCA_WLAN_VENDOR_ATTR_QDEPTH_THRESH_LAST - 1, +}; + +/** * enum qca_wlan_vendor_attr_get_hw_capability - Wi-Fi hardware capability */ enum qca_wlan_vendor_attr_get_hw_capability { @@ -1143,6 +2057,12 @@ enum qca_wlan_vendor_attr_get_hw_capability { * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_ANT_NF: per antenna NF value * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_IFACE_RSSI_BEACON: RSSI of beacon * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_IFACE_SNR_BEACON: SNR of beacon + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_REPORT_TIME: u64 + * Absolute timestamp from 1970/1/1, unit in ms. After receiving the + * message, user layer APP could call gettimeofday to get another + * timestamp and calculate transfer delay for the message. + * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_MEASUREMENT_TIME: u32 + * Real period for this measurement, unit in us. */ enum qca_wlan_vendor_attr_ll_stats_ext { QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_INVALID = 0, @@ -1236,6 +2156,9 @@ enum qca_wlan_vendor_attr_ll_stats_ext { QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_IFACE_RSSI_BEACON, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_IFACE_SNR_BEACON, + QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_REPORT_TIME, + QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_MEASUREMENT_TIME, + QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_LAST, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_MAX = QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_LAST - 1 @@ -1289,7 +2212,7 @@ enum qca_wlan_vendor_attr_loc_capa { * @QCA_WLAN_VENDOR_ATTR_LOC_CAPA_FLAG_FTM_INITIATOR: Set if driver * can run FTM sessions. QCA_NL80211_VENDOR_SUBCMD_FTM_START_SESSION * will be supported if set. -* @QCA_WLAN_VENDOR_ATTR_LOC_CAPA_FLAG_ASAP: Set if FTM responder + * @QCA_WLAN_VENDOR_ATTR_LOC_CAPA_FLAG_ASAP: Set if FTM responder * supports immediate (ASAP) response. * @QCA_WLAN_VENDOR_ATTR_LOC_CAPA_FLAG_AOA: Set if driver supports standalone * AOA measurement using QCA_NL80211_VENDOR_SUBCMD_AOA_MEAS. @@ -1320,6 +2243,10 @@ enum qca_wlan_vendor_attr_loc_capa_flags { * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_AOA_BURST_PERIOD: Request AOA * measurement every <value> bursts. If 0 or not specified, * AOA measurements will be disabled for this peer. + * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_FREQ: Frequency in MHz where + * the measurement frames are exchanged. Optional; if not + * specified, try to locate the peer in the kernel scan + * results cache and use frequency from there. */ enum qca_wlan_vendor_attr_ftm_peer_info { QCA_WLAN_VENDOR_ATTR_FTM_PEER_INVALID, @@ -1328,6 +2255,7 @@ enum qca_wlan_vendor_attr_ftm_peer_info { QCA_WLAN_VENDOR_ATTR_FTM_PEER_MEAS_PARAMS, QCA_WLAN_VENDOR_ATTR_FTM_PEER_SECURE_TOKEN_ID, QCA_WLAN_VENDOR_ATTR_FTM_PEER_AOA_BURST_PERIOD, + QCA_WLAN_VENDOR_ATTR_FTM_PEER_FREQ, /* keep last */ QCA_WLAN_VENDOR_ATTR_FTM_PEER_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_FTM_PEER_MAX = @@ -1587,4 +2515,4198 @@ enum qca_wlan_vendor_attr_encryption_test { QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_AFTER_LAST - 1 }; +/** + * enum qca_wlan_vendor_attr_dmg_rf_sector_type - Type of + * sector for DMG RF sector operations. + * + * @QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_TYPE_RX: RX sector + * @QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_TYPE_TX: TX sector + */ +enum qca_wlan_vendor_attr_dmg_rf_sector_type { + QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_TYPE_RX, + QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_TYPE_TX, + QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_TYPE_MAX +}; + +/** + * enum qca_wlan_vendor_attr_fw_state - State of firmware + * + * @QCA_WLAN_VENDOR_ATTR_FW_STATE_ERROR: FW is in bad state + * @QCA_WLAN_VENDOR_ATTR_FW_STATE_ACTIVE: FW is active + */ +enum qca_wlan_vendor_attr_fw_state { + QCA_WLAN_VENDOR_ATTR_FW_STATE_ERROR, + QCA_WLAN_VENDOR_ATTR_FW_STATE_ACTIVE, + QCA_WLAN_VENDOR_ATTR_FW_STATE_MAX +}; + +/** + * BRP antenna limit mode + * + * @QCA_WLAN_VENDOR_ATTR_BRP_ANT_LIMIT_MODE_DISABLE: Disable BRP force + * antenna limit, BRP will be performed as usual. + * @QCA_WLAN_VENDOR_ATTR_BRP_ANT_LIMIT_MODE_EFFECTIVE: Define maximal + * antennas limit. the hardware may use less antennas than the + * maximum limit. + * @QCA_WLAN_VENDOR_ATTR_BRP_ANT_LIMIT_MODE_FORCE: The hardware will + * use exactly the specified number of antennas for BRP. + */ +enum qca_wlan_vendor_attr_brp_ant_limit_mode { + QCA_WLAN_VENDOR_ATTR_BRP_ANT_LIMIT_MODE_DISABLE, + QCA_WLAN_VENDOR_ATTR_BRP_ANT_LIMIT_MODE_EFFECTIVE, + QCA_WLAN_VENDOR_ATTR_BRP_ANT_LIMIT_MODE_FORCE, + QCA_WLAN_VENDOR_ATTR_BRP_ANT_LIMIT_MODE_MAX +}; + +/** + * enum qca_wlan_vendor_attr_dmg_rf_sector_cfg - Attributes for + * DMG RF sector configuration for a single RF module. + * The values are defined in a compact way which closely matches + * the way it is stored in HW registers. + * The configuration provides values for 32 antennas and 8 distribution + * amplifiers, and together describes the characteristics of the RF + * sector - such as a beam in some direction with some gain. + * + * @QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_CFG_MODULE_INDEX: Index + * of RF module for this configuration. + * @QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_CFG_ETYPE0: Bit 0 of edge + * amplifier gain index. Unsigned 32 bit number containing + * bits for all 32 antennas. + * @QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_CFG_ETYPE1: Bit 1 of edge + * amplifier gain index. Unsigned 32 bit number containing + * bits for all 32 antennas. + * @QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_CFG_ETYPE2: Bit 2 of edge + * amplifier gain index. Unsigned 32 bit number containing + * bits for all 32 antennas. + * @QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_CFG_PSH_HI: Phase values + * for first 16 antennas, 2 bits per antenna. + * @QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_CFG_PSH_LO: Phase values + * for last 16 antennas, 2 bits per antenna. + * @QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_CFG_DTYPE_X16: Contains + * DTYPE values (3 bits) for each distribution amplifier, followed + * by X16 switch bits for each distribution amplifier. There are + * total of 8 distribution amplifiers. + */ +enum qca_wlan_vendor_attr_dmg_rf_sector_cfg { + QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_CFG_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_CFG_MODULE_INDEX = 1, + QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_CFG_ETYPE0 = 2, + QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_CFG_ETYPE1 = 3, + QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_CFG_ETYPE2 = 4, + QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_CFG_PSH_HI = 5, + QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_CFG_PSH_LO = 6, + QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_CFG_DTYPE_X16 = 7, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_CFG_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_CFG_MAX = + QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_CFG_AFTER_LAST - 1 +}; + +enum qca_wlan_vendor_attr_ll_stats_set { + QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_INVALID = 0, + /* Unsigned 32-bit value */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_CONFIG_MPDU_SIZE_THRESHOLD = 1, + QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_CONFIG_AGGRESSIVE_STATS_GATHERING = 2, + /* keep last */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_MAX = + QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_AFTER_LAST - 1, +}; + +enum qca_wlan_vendor_attr_ll_stats_clr { + QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_INVALID = 0, + /* Unsigned 32bit bitmap for clearing statistics + * All radio statistics 0x00000001 + * cca_busy_time (within radio statistics) 0x00000002 + * All channel stats (within radio statistics) 0x00000004 + * All scan statistics (within radio statistics) 0x00000008 + * All interface statistics 0x00000010 + * All tx rate statistics (within interface statistics) 0x00000020 + * All ac statistics (with in interface statistics) 0x00000040 + * All contention (min, max, avg) statistics (within ac statisctics) + * 0x00000080. + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_REQ_MASK = 1, + /* Unsigned 8 bit value: Request to stop statistics collection */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_REQ = 2, + + /* Unsigned 32 bit bitmap: Response from the driver + * for the cleared statistics + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_RSP_MASK = 3, + /* Unsigned 8 bit value: Response from driver/firmware + * for the stop request + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_RSP = 4, + /* keep last */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_MAX = + QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_AFTER_LAST - 1, +}; + +enum qca_wlan_vendor_attr_ll_stats_get { + QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_INVALID = 0, + /* Unsigned 32 bit value provided by the caller issuing the GET stats + * command. When reporting the stats results, the driver uses the same + * value to indicate which GET request the results correspond to. + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_ID = 1, + /* Unsigned 32 bit value - bit mask to identify what statistics are + * requested for retrieval. + * Radio Statistics 0x00000001 + * Interface Statistics 0x00000020 + * All Peer Statistics 0x00000040 + * Peer Statistics 0x00000080 + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_MASK = 2, + /* keep last */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_MAX = + QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_AFTER_LAST - 1, +}; + +enum qca_wlan_vendor_attr_ll_stats_results { + QCA_WLAN_VENDOR_ATTR_LL_STATS_INVALID = 0, + /* Unsigned 32bit value. Used by the driver; must match the request id + * provided with the QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET command. + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_RESULTS_REQ_ID = 1, + + /* Unsigned 32 bit value */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_BEACON_RX = 2, + /* Unsigned 32 bit value */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_MGMT_RX = 3, + /* Unsigned 32 bit value */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_MGMT_ACTION_RX = 4, + /* Unsigned 32 bit value */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_MGMT_ACTION_TX = 5, + /* Signed 32 bit value */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RSSI_MGMT = 6, + /* Signed 32 bit value */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RSSI_DATA = 7, + /* Signed 32 bit value */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RSSI_ACK = 8, + + /* Attributes of type QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_* are + * nested within the interface stats. + */ + + /* Interface mode, e.g., STA, SOFTAP, IBSS, etc. + * Type = enum wifi_interface_mode. + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_MODE = 9, + /* Interface MAC address. An array of 6 Unsigned int8 */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_MAC_ADDR = 10, + /* Type = enum wifi_connection_state, e.g., DISCONNECTED, + * AUTHENTICATING, etc. valid for STA, CLI only. + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_STATE = 11, + /* Type = enum wifi_roam_state. Roaming state, e.g., IDLE or ACTIVE + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_ROAMING = 12, + /* Unsigned 32 bit value. WIFI_CAPABILITY_XXX */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_CAPABILITIES = 13, + /* NULL terminated SSID. An array of 33 Unsigned 8bit values */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_SSID = 14, + /* BSSID. An array of 6 unsigned 8 bit values */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_BSSID = 15, + /* Country string advertised by AP. An array of 3 unsigned 8 bit + * values. + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_AP_COUNTRY_STR = 16, + /* Country string for this association. An array of 3 unsigned 8 bit + * values. + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_COUNTRY_STR = 17, + + /* Attributes of type QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_* could + * be nested within the interface stats. + */ + + /* Type = enum wifi_traffic_ac, e.g., V0, VI, BE and BK */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_AC = 18, + /* Unsigned int 32 value corresponding to respective AC */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_TX_MPDU = 19, + /* Unsigned int 32 value corresponding to respective AC */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RX_MPDU = 20, + /* Unsigned int 32 value corresponding to respective AC */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_TX_MCAST = 21, + /* Unsigned int 32 value corresponding to respective AC */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RX_MCAST = 22, + /* Unsigned int 32 value corresponding to respective AC */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RX_AMPDU = 23, + /* Unsigned int 32 value corresponding to respective AC */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_TX_AMPDU = 24, + /* Unsigned int 32 value corresponding to respective AC */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_MPDU_LOST = 25, + /* Unsigned int 32 value corresponding to respective AC */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RETRIES = 26, + /* Unsigned int 32 value corresponding to respective AC */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RETRIES_SHORT = 27, + /* Unsigned int 32 values corresponding to respective AC */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RETRIES_LONG = 28, + /* Unsigned int 32 values corresponding to respective AC */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_TIME_MIN = 29, + /* Unsigned int 32 values corresponding to respective AC */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_TIME_MAX = 30, + /* Unsigned int 32 values corresponding to respective AC */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_TIME_AVG = 31, + /* Unsigned int 32 values corresponding to respective AC */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_NUM_SAMPLES = 32, + /* Unsigned 32 bit value. Number of peers */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_NUM_PEERS = 33, + + /* Attributes of type QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_* are + * nested within the interface stats. + */ + + /* Type = enum wifi_peer_type. Peer type, e.g., STA, AP, P2P GO etc. */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_TYPE = 34, + /* MAC addr corresponding to respective peer. An array of 6 unsigned + * 8 bit values. + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_MAC_ADDRESS = 35, + /* Unsigned int 32 bit value representing capabilities corresponding + * to respective peer. + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_CAPABILITIES = 36, + /* Unsigned 32 bit value. Number of rates */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_NUM_RATES = 37, + + /* Attributes of type QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_* + * are nested within the rate stat. + */ + + /* Wi-Fi Rate - separate attributes defined for individual fields */ + + /* Unsigned int 8 bit value; 0: OFDM, 1:CCK, 2:HT 3:VHT 4..7 reserved */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_PREAMBLE = 38, + /* Unsigned int 8 bit value; 0:1x1, 1:2x2, 3:3x3, 4:4x4 */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_NSS = 39, + /* Unsigned int 8 bit value; 0:20 MHz, 1:40 MHz, 2:80 MHz, 3:160 MHz */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_BW = 40, + /* Unsigned int 8 bit value; OFDM/CCK rate code would be as per IEEE Std + * in the units of 0.5 Mbps HT/VHT it would be MCS index + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_MCS_INDEX = 41, + + /* Unsigned 32 bit value. Bit rate in units of 100 kbps */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_BIT_RATE = 42, + + /* Attributes of type QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_STAT_* could be + * nested within the peer info stats. + */ + + /* Unsigned int 32 bit value. Number of successfully transmitted data + * packets, i.e., with ACK received corresponding to the respective + * rate. + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_TX_MPDU = 43, + /* Unsigned int 32 bit value. Number of received data packets + * corresponding to the respective rate. + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RX_MPDU = 44, + /* Unsigned int 32 bit value. Number of data packet losses, i.e., no ACK + * received corresponding to the respective rate. + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_MPDU_LOST = 45, + /* Unsigned int 32 bit value. Total number of data packet retries for + * the respective rate. + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RETRIES = 46, + /* Unsigned int 32 bit value. Total number of short data packet retries + * for the respective rate. + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RETRIES_SHORT = 47, + /* Unsigned int 32 bit value. Total number of long data packet retries + * for the respective rate. + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RETRIES_LONG = 48, + + QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ID = 49, + /* Unsigned 32 bit value. Total number of msecs the radio is awake + * accruing over time. + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME = 50, + /* Unsigned 32 bit value. Total number of msecs the radio is + * transmitting accruing over time. + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_TX_TIME = 51, + /* Unsigned 32 bit value. Total number of msecs the radio is in active + * receive accruing over time. + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_RX_TIME = 52, + /* Unsigned 32 bit value. Total number of msecs the radio is awake due + * to all scan accruing over time. + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_SCAN = 53, + /* Unsigned 32 bit value. Total number of msecs the radio is awake due + * to NAN accruing over time. + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_NBD = 54, + /* Unsigned 32 bit value. Total number of msecs the radio is awake due + * to GSCAN accruing over time. + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_GSCAN = 55, + /* Unsigned 32 bit value. Total number of msecs the radio is awake due + * to roam scan accruing over time. + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_ROAM_SCAN = 56, + /* Unsigned 32 bit value. Total number of msecs the radio is awake due + * to PNO scan accruing over time. + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_PNO_SCAN = 57, + /* Unsigned 32 bit value. Total number of msecs the radio is awake due + * to Hotspot 2.0 scans and GAS exchange accruing over time. + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_HS20 = 58, + /* Unsigned 32 bit value. Number of channels. */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_NUM_CHANNELS = 59, + + /* Attributes of type QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_* could + * be nested within the channel stats. + */ + + /* Type = enum wifi_channel_width. Channel width, e.g., 20, 40, 80 */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_WIDTH = 60, + /* Unsigned 32 bit value. Primary 20 MHz channel. */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_CENTER_FREQ = 61, + /* Unsigned 32 bit value. Center frequency (MHz) first segment. */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_CENTER_FREQ0 = 62, + /* Unsigned 32 bit value. Center frequency (MHz) second segment. */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_CENTER_FREQ1 = 63, + + /* Attributes of type QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_* could be + * nested within the radio stats. + */ + + /* Unsigned int 32 bit value representing total number of msecs the + * radio is awake on that channel accruing over time, corresponding to + * the respective channel. + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_ON_TIME = 64, + /* Unsigned int 32 bit value representing total number of msecs the CCA + * register is busy accruing over time corresponding to the respective + * channel. + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_CCA_BUSY_TIME = 65, + + QCA_WLAN_VENDOR_ATTR_LL_STATS_NUM_RADIOS = 66, + + /* Signifies the nested list of channel attributes + * QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_* + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_CH_INFO = 67, + + /* Signifies the nested list of peer info attributes + * QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_* + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO = 68, + + /* Signifies the nested list of rate info attributes + * QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_* + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_RATE_INFO = 69, + + /* Signifies the nested list of wmm info attributes + * QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_* + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_INFO = 70, + + /* Unsigned 8 bit value. Used by the driver; if set to 1, it indicates + * that more stats, e.g., peers or radio, are to follow in the next + * QCA_NL80211_VENDOR_SUBCMD_LL_STATS_*_RESULTS event. + * Otherwise, it is set to 0. + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_RESULTS_MORE_DATA = 71, + + /* Unsigned 64 bit value */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_AVERAGE_TSF_OFFSET = 72, + + /* Unsigned 32 bit value */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_LEAKY_AP_DETECTED = 73, + + /* Unsigned 32 bit value */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_LEAKY_AP_AVG_NUM_FRAMES_LEAKED = 74, + + /* Unsigned 32 bit value */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_LEAKY_AP_GUARD_TIME = 75, + + /* Unsigned 32 bit value */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_TYPE = 76, + + /* Unsigned 32 bit value */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_NUM_TX_LEVELS = 77, + + /* Number of msecs the radio spent in transmitting for each power level + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_TX_TIME_PER_LEVEL = 78, + + /* Unsigned 32 bit value */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RTS_SUCC_CNT = 79, + /* Unsigned 32 bit value */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RTS_FAIL_CNT = 80, + /* Unsigned 32 bit value */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_PPDU_SUCC_CNT = 81, + /* Unsigned 32 bit value */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_PPDU_FAIL_CNT = 82, + + /* Unsigned int 32 value. + * Pending MSDUs corresponding to respective AC. + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_PENDING_MSDU = 83, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX = + QCA_WLAN_VENDOR_ATTR_LL_STATS_AFTER_LAST - 1, +}; + +enum qca_wlan_vendor_attr_ll_stats_type { + QCA_NL80211_VENDOR_SUBCMD_LL_STATS_TYPE_INVALID = 0, + QCA_NL80211_VENDOR_SUBCMD_LL_STATS_TYPE_RADIO = 1, + QCA_NL80211_VENDOR_SUBCMD_LL_STATS_TYPE_IFACE = 2, + QCA_NL80211_VENDOR_SUBCMD_LL_STATS_TYPE_PEERS = 3, + + /* keep last */ + QCA_NL80211_VENDOR_SUBCMD_LL_STATS_TYPE_AFTER_LAST, + QCA_NL80211_VENDOR_SUBCMD_LL_STATS_TYPE_MAX = + QCA_NL80211_VENDOR_SUBCMD_LL_STATS_TYPE_AFTER_LAST - 1, +}; + +/** + * enum qca_wlan_vendor_attr_tdls_configuration - Attributes for + * TDLS configuration to the host driver. + * + * @QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_TRIGGER_MODE: Configure the TDLS trigger + * mode in the host driver. enum qca_wlan_vendor_tdls_trigger_mode + * represents the different TDLS trigger modes. + * @QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_TX_STATS_PERIOD: Duration (u32) within + * which QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_TX_THRESHOLD number + * of packets shall meet the criteria for implicit TDLS setup. + * @QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_TX_THRESHOLD: Number (u32) of Tx/Rx packets + * within a duration QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_TX_STATS_PERIOD + * to initiate a TDLS setup. + * @QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_DISCOVERY_PERIOD: Time (u32) to initiate + * a TDLS Discovery to the peer. + * @QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_MAX_DISCOVERY_ATTEMPT: Max number (u32) of + * discovery attempts to know the TDLS capability of the peer. A peer is + * marked as TDLS not capable if there is no response for all the attempts. + * @QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_IDLE_TIMEOUT: Represents a duration (u32) + * within which QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_IDLE_PACKET_THRESHOLD + * number of TX / RX frames meet the criteria for TDLS teardown. + * @QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_IDLE_PACKET_THRESHOLD: Minimum number (u32) + * of Tx/Rx packets within a duration + * QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_IDLE_TIMEOUT to tear down a TDLS link. + * @QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_SETUP_RSSI_THRESHOLD: Threshold + * corresponding to the RSSI of the peer below which a TDLS setup is + * triggered. + * @QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_TEARDOWN_RSSI_THRESHOLD: Threshold + * corresponding to the RSSI of the peer above which a TDLS teardown is + * triggered. + */ +enum qca_wlan_vendor_attr_tdls_configuration { + QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_TRIGGER_MODE = 1, + + /* Attributes configuring the TDLS Implicit Trigger */ + QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_TX_STATS_PERIOD = 2, + QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_TX_THRESHOLD = 3, + QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_DISCOVERY_PERIOD = 4, + QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_MAX_DISCOVERY_ATTEMPT = 5, + QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_IDLE_TIMEOUT = 6, + QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_IDLE_PACKET_THRESHOLD = 7, + QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_SETUP_RSSI_THRESHOLD = 8, + QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_TEARDOWN_RSSI_THRESHOLD = 9, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_MAX = + QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_AFTER_LAST - 1 +}; + +/** + * enum qca_wlan_vendor_tdls_trigger_mode: Represents the TDLS trigger mode in + * the driver + * + * The following are the different values for + * QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_TRIGGER_MODE. + * + * @QCA_WLAN_VENDOR_TDLS_TRIGGER_MODE_EXPLICIT: The trigger to initiate/teardown + * the TDLS connection to a respective peer comes from the user space. + * wpa_supplicant provides the commands TDLS_SETUP, TDLS_TEARDOWN, + * TDLS_DISCOVER to do this. + * @QCA_WLAN_VENDOR_TDLS_TRIGGER_MODE_IMPLICIT: Host driver triggers this TDLS + * setup/teardown to the eligible peer once the configured criteria + * (such as TX/RX threshold, RSSI) is met. The attributes + * in QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_IMPLICIT_PARAMS correspond to + * the different configuration criteria for the TDLS trigger from the + * host driver. + * @QCA_WLAN_VENDOR_TDLS_TRIGGER_MODE_EXTERNAL: Enables the driver to trigger + * the TDLS setup / teardown through the implicit mode only to the + * configured MAC addresses (wpa_supplicant, with tdls_external_control=1, + * configures the MAC address through TDLS_SETUP / TDLS_TEARDOWN commands). + * External mode works on top of the implicit mode. Thus the host driver + * is expected to configure in TDLS Implicit mode too to operate in + * External mode. + * Configuring External mode alone without Implicit mode is invalid. + * + * All the above implementations work as expected only when the host driver + * advertises the capability WPA_DRIVER_FLAGS_TDLS_EXTERNAL_SETUP - representing + * that the TDLS message exchange is not internal to the host driver, but + * depends on wpa_supplicant to do the message exchange. + */ +enum qca_wlan_vendor_tdls_trigger_mode { + QCA_WLAN_VENDOR_TDLS_TRIGGER_MODE_EXPLICIT = 1 << 0, + QCA_WLAN_VENDOR_TDLS_TRIGGER_MODE_IMPLICIT = 1 << 1, + QCA_WLAN_VENDOR_TDLS_TRIGGER_MODE_EXTERNAL = 1 << 2, +}; + +/** + * enum qca_vendor_attr_sar_limits_selections - Source of SAR power limits + * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0: Select SAR profile #0 + * that is hard-coded in the Board Data File (BDF). + * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF1: Select SAR profile #1 + * that is hard-coded in the Board Data File (BDF). + * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF2: Select SAR profile #2 + * that is hard-coded in the Board Data File (BDF). + * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF3: Select SAR profile #3 + * that is hard-coded in the Board Data File (BDF). + * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4: Select SAR profile #4 + * that is hard-coded in the Board Data File (BDF). + * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE: Do not select any + * source of SAR power limits, thereby disabling the SAR power + * limit feature. + * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_USER: Select the SAR power + * limits configured by %QCA_NL80211_VENDOR_SUBCMD_SET_SAR. + * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_V2_0: Select the SAR power + * limits version 2.0 configured by %QCA_NL80211_VENDOR_SUBCMD_SET_SAR. + * + * This enumerates the valid set of values that may be supplied for + * attribute %QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT in an instance of + * the %QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS vendor command or in + * the response to an instance of the + * %QCA_NL80211_VENDOR_SUBCMD_GET_SAR_LIMITS vendor command. + */ +enum qca_vendor_attr_sar_limits_selections { + QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0 = 0, + QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF1 = 1, + QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF2 = 2, + QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF3 = 3, + QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4 = 4, + QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE = 5, + QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_USER = 6, + QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_V2_0 = 7, +}; + +/** + * enum qca_vendor_attr_sar_limits_spec_modulations - + * SAR limits specification modulation + * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_CCK - + * CCK modulation + * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_OFDM - + * OFDM modulation + * + * This enumerates the valid set of values that may be supplied for + * attribute %QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION in an + * instance of attribute %QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC in an + * instance of the %QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS vendor + * command or in the response to an instance of the + * %QCA_NL80211_VENDOR_SUBCMD_GET_SAR_LIMITS vendor command. + */ +enum qca_vendor_attr_sar_limits_spec_modulations { + QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_CCK = 0, + QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_OFDM = 1, +}; + +/** + * enum qca_vendor_attr_sar_limits - Attributes for SAR power limits + * + * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE: Optional (u32) value to + * select which SAR power limit table should be used. Valid + * values are enumerated in enum + * %qca_vendor_attr_sar_limits_selections. The existing SAR + * power limit selection is unchanged if this attribute is not + * present. + * + * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS: Optional (u32) value + * which specifies the number of SAR power limit specifications + * which will follow. + * + * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC: Nested array of SAR power + * limit specifications. The number of specifications is + * specified by @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS. Each + * specification contains a set of + * QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_* attributes. A + * specification is uniquely identified by the attributes + * %QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND, + * %QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN, and + * %QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION and always + * contains as a payload the attribute + * %QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT, + * %QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT_INDEX. + * Either %QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT or + * %QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT_INDEX is + * needed based upon the value of + * %QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE. + * + * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND: Optional (u32) value to + * indicate for which band this specification applies. Valid + * values are enumerated in enum %nl80211_band (although not all + * bands may be supported by a given device). If the attribute is + * not supplied then the specification will be applied to all + * supported bands. + * + * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN: Optional (u32) value + * to indicate for which antenna chain this specification + * applies, i.e. 1 for chain 1, 2 for chain 2, etc. If the + * attribute is not supplied then the specification will be + * applied to all chains. + * + * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION: Optional (u32) + * value to indicate for which modulation scheme this + * specification applies. Valid values are enumerated in enum + * %qca_vendor_attr_sar_limits_spec_modulations. If the attribute + * is not supplied then the specification will be applied to all + * modulation schemes. + * + * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT: Required (u32) + * value to specify the actual power limit value in units of 0.5 + * dBm (i.e., a value of 11 represents 5.5 dBm). + * This is required, when %QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT is + * %QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_USER. + * + * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT_INDEX: Required (u32) + * value to indicate SAR V2 indices (0 - 11) to select SAR V2 profiles. + * This is required, when %QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT is + * %QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_V2_0. + * + * These attributes are used with %QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS + * and %QCA_NL80211_VENDOR_SUBCMD_GET_SAR_LIMITS. + */ +enum qca_vendor_attr_sar_limits { + QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE = 1, + QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS = 2, + QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC = 3, + QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND = 4, + QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN = 5, + QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION = 6, + QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT = 7, + QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT_INDEX = 8, + + QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX = + QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_AFTER_LAST - 1 +}; + +/** + * enum qca_wlan_vendor_attr_get_wifi_info: Attributes for data used by + * QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO sub command. + */ +enum qca_wlan_vendor_attr_get_wifi_info { + QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION = 1, + QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION = 2, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX = + QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_AFTER_LAST - 1, +}; + +/* + * enum qca_wlan_vendor_attr_wifi_logger_start: Attributes for data used by + * QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START sub command. + */ +enum qca_wlan_vendor_attr_wifi_logger_start { + QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID = 1, + QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL = 2, + QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS = 3, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_GET_MAX = + QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_AFTER_LAST - 1, +}; + +enum qca_wlan_vendor_attr_logger_results { + QCA_WLAN_VENDOR_ATTR_LOGGER_RESULTS_INVALID = 0, + + /* Unsigned 32-bit value; must match the request Id supplied by + * Wi-Fi HAL in the corresponding subcmd NL msg. + */ + QCA_WLAN_VENDOR_ATTR_LOGGER_RESULTS_REQUEST_ID = 1, + + /* Unsigned 32-bit value; used to indicate the size of memory + * dump to be allocated. + */ + QCA_WLAN_VENDOR_ATTR_LOGGER_RESULTS_MEMDUMP_SIZE = 2, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_LOGGER_RESULTS_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_LOGGER_RESULTS_MAX = + QCA_WLAN_VENDOR_ATTR_LOGGER_RESULTS_AFTER_LAST - 1, +}; + +enum qca_wlan_vendor_attr_roaming_config_params { + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_INVALID = 0, + + QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD = 1, + QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID = 2, + + /* Attributes for wifi_set_ssid_white_list */ + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS = 3, + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST = 4, + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID = 5, + + /* Attributes for set_roam_params */ + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD = 6, + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD = 7, + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR = 8, + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR = 9, + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST = 10, + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS = 11, + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER = 12, + + /* Attribute for set_lazy_roam */ + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE = 13, + + /* Attribute for set_lazy_roam with preferences */ + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS = 14, + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID = 15, + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID = 16, + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER = 17, + + /* Attribute for set_blacklist bssid params */ + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS = 18, + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID = 19, + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID = 20, + /* Flag attribute indicates this BSSID blacklist as a hint */ + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_HINT = 21, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX = + QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_AFTER_LAST - 1, +}; + +/* + * enum qca_wlan_vendor_attr_roam_subcmd: Attributes for data used by + * QCA_NL80211_VENDOR_SUBCMD_ROAM sub command. + */ +enum qca_wlan_vendor_attr_roam_subcmd { + QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SSID_WHITE_LIST = 1, + QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_GSCAN_ROAM_PARAMS = 2, + QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_LAZY_ROAM = 3, + QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PREFS = 4, + QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BSSID_PARAMS = 5, + QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID = 6, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_MAX = + QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_AFTER_LAST - 1, +}; + +enum qca_wlan_vendor_attr_gscan_config_params { + QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_INVALID = 0, + + /* Unsigned 32-bit value */ + QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID = 1, + + /* Attributes for data used by + * QCA_NL80211_VENDOR_SUBCMD_GSCAN_GET_VALID_CHANNELS sub command. + */ + /* Unsigned 32-bit value */ + QCA_WLAN_VENDOR_ATTR_GSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_WIFI_BAND + = 2, + /* Unsigned 32-bit value */ + QCA_WLAN_VENDOR_ATTR_GSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_MAX_CHANNELS + = 3, + + /* Attributes for input params used by + * QCA_NL80211_VENDOR_SUBCMD_GSCAN_START sub command. + */ + + /* Unsigned 32-bit value; channel frequency */ + QCA_WLAN_VENDOR_ATTR_GSCAN_CHANNEL_SPEC_CHANNEL = 4, + /* Unsigned 32-bit value; dwell time in ms. */ + QCA_WLAN_VENDOR_ATTR_GSCAN_CHANNEL_SPEC_DWELL_TIME = 5, + /* Unsigned 8-bit value; 0: active; 1: passive; N/A for DFS */ + QCA_WLAN_VENDOR_ATTR_GSCAN_CHANNEL_SPEC_PASSIVE = 6, + /* Unsigned 8-bit value; channel class */ + QCA_WLAN_VENDOR_ATTR_GSCAN_CHANNEL_SPEC_CLASS = 7, + + /* Unsigned 8-bit value; bucket index, 0 based */ + QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_INDEX = 8, + /* Unsigned 8-bit value; band. */ + QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_BAND = 9, + /* Unsigned 32-bit value; desired period, in ms. */ + QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_PERIOD = 10, + /* Unsigned 8-bit value; report events semantics. */ + QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_REPORT_EVENTS = 11, + /* Unsigned 32-bit value. Followed by a nested array of + * GSCAN_CHANNEL_SPEC_* attributes. + */ + QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_NUM_CHANNEL_SPECS = 12, + + /* Array of QCA_WLAN_VENDOR_ATTR_GSCAN_CHANNEL_SPEC_* attributes. + * Array size: QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_NUM_CHANNEL_SPECS + */ + QCA_WLAN_VENDOR_ATTR_GSCAN_CHANNEL_SPEC = 13, + + /* Unsigned 32-bit value; base timer period in ms. */ + QCA_WLAN_VENDOR_ATTR_GSCAN_SCAN_CMD_PARAMS_BASE_PERIOD = 14, + /* Unsigned 32-bit value; number of APs to store in each scan in the + * BSSID/RSSI history buffer (keep the highest RSSI APs). + */ + QCA_WLAN_VENDOR_ATTR_GSCAN_SCAN_CMD_PARAMS_MAX_AP_PER_SCAN = 15, + /* Unsigned 8-bit value; in %, when scan buffer is this much full, wake + * up AP. + */ + QCA_WLAN_VENDOR_ATTR_GSCAN_SCAN_CMD_PARAMS_REPORT_THRESHOLD_PERCENT + = 16, + + /* Unsigned 8-bit value; number of scan bucket specs; followed by a + * nested array of_GSCAN_BUCKET_SPEC_* attributes and values. The size + * of the array is determined by NUM_BUCKETS. + */ + QCA_WLAN_VENDOR_ATTR_GSCAN_SCAN_CMD_PARAMS_NUM_BUCKETS = 17, + + /* Array of QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_* attributes. + * Array size: QCA_WLAN_VENDOR_ATTR_GSCAN_SCAN_CMD_PARAMS_NUM_BUCKETS + */ + QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC = 18, + + /* Unsigned 8-bit value */ + QCA_WLAN_VENDOR_ATTR_GSCAN_GET_CACHED_SCAN_RESULTS_CONFIG_PARAM_FLUSH + = 19, + /* Unsigned 32-bit value; maximum number of results to be returned. */ + QCA_WLAN_VENDOR_ATTR_GSCAN_GET_CACHED_SCAN_RESULTS_CONFIG_PARAM_MAX + = 20, + + /* An array of 6 x unsigned 8-bit value */ + QCA_WLAN_VENDOR_ATTR_GSCAN_AP_THRESHOLD_PARAM_BSSID = 21, + /* Signed 32-bit value */ + QCA_WLAN_VENDOR_ATTR_GSCAN_AP_THRESHOLD_PARAM_RSSI_LOW = 22, + /* Signed 32-bit value */ + QCA_WLAN_VENDOR_ATTR_GSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH = 23, + /* Unsigned 32-bit value */ + QCA_WLAN_VENDOR_ATTR_GSCAN_AP_THRESHOLD_PARAM_CHANNEL = 24, + + /* Number of hotlist APs as unsigned 32-bit value, followed by a nested + * array of AP_THRESHOLD_PARAM attributes and values. The size of the + * array is determined by NUM_AP. + */ + QCA_WLAN_VENDOR_ATTR_GSCAN_BSSID_HOTLIST_PARAMS_NUM_AP = 25, + + /* Array of QCA_WLAN_VENDOR_ATTR_GSCAN_AP_THRESHOLD_PARAM_* attributes. + * Array size: QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_NUM_CHANNEL_SPECS + */ + QCA_WLAN_VENDOR_ATTR_GSCAN_AP_THRESHOLD_PARAM = 26, + + /* Unsigned 32-bit value; number of samples for averaging RSSI. */ + QCA_WLAN_VENDOR_ATTR_GSCAN_SIGNIFICANT_CHANGE_PARAMS_RSSI_SAMPLE_SIZE + = 27, + /* Unsigned 32-bit value; number of samples to confirm AP loss. */ + QCA_WLAN_VENDOR_ATTR_GSCAN_SIGNIFICANT_CHANGE_PARAMS_LOST_AP_SAMPLE_SIZE + = 28, + /* Unsigned 32-bit value; number of APs breaching threshold. */ + QCA_WLAN_VENDOR_ATTR_GSCAN_SIGNIFICANT_CHANGE_PARAMS_MIN_BREACHING = 29, + /* Unsigned 32-bit value; number of APs. Followed by an array of + * AP_THRESHOLD_PARAM attributes. Size of the array is NUM_AP. + */ + QCA_WLAN_VENDOR_ATTR_GSCAN_SIGNIFICANT_CHANGE_PARAMS_NUM_AP = 30, + /* Unsigned 32-bit value; number of samples to confirm AP loss. */ + QCA_WLAN_VENDOR_ATTR_GSCAN_BSSID_HOTLIST_PARAMS_LOST_AP_SAMPLE_SIZE + = 31, + /* Unsigned 32-bit value. If max_period is non zero or different than + * period, then this bucket is an exponential backoff bucket. + */ + QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_MAX_PERIOD = 32, + /* Unsigned 32-bit value. */ + QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_BASE = 33, + /* Unsigned 32-bit value. For exponential back off bucket, number of + * scans to perform for a given period. + */ + QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_STEP_COUNT = 34, + /* Unsigned 8-bit value; in number of scans, wake up AP after these + * many scans. + */ + QCA_WLAN_VENDOR_ATTR_GSCAN_SCAN_CMD_PARAMS_REPORT_THRESHOLD_NUM_SCANS + = 35, + + /* Attributes for data used by + * QCA_NL80211_VENDOR_SUBCMD_GSCAN_SET_SSID_HOTLIST sub command. + */ + /* Unsigned 3-2bit value; number of samples to confirm SSID loss. */ + QCA_WLAN_VENDOR_ATTR_GSCAN_SSID_HOTLIST_PARAMS_LOST_SSID_SAMPLE_SIZE + = 36, + /* Number of hotlist SSIDs as unsigned 32-bit value, followed by a + * nested array of SSID_THRESHOLD_PARAM_* attributes and values. The + * size of the array is determined by NUM_SSID. + */ + QCA_WLAN_VENDOR_ATTR_GSCAN_SSID_HOTLIST_PARAMS_NUM_SSID = 37, + /* Array of QCA_WLAN_VENDOR_ATTR_GSCAN_SSID_THRESHOLD_PARAM_* + * attributes. + * Array size: QCA_WLAN_VENDOR_ATTR_GSCAN_SSID_HOTLIST_PARAMS_NUM_SSID + */ + QCA_WLAN_VENDOR_ATTR_GSCAN_SSID_THRESHOLD_PARAM = 38, + + /* An array of 33 x unsigned 8-bit value; NULL terminated SSID */ + QCA_WLAN_VENDOR_ATTR_GSCAN_SSID_THRESHOLD_PARAM_SSID = 39, + /* Unsigned 8-bit value */ + QCA_WLAN_VENDOR_ATTR_GSCAN_SSID_THRESHOLD_PARAM_BAND = 40, + /* Signed 32-bit value */ + QCA_WLAN_VENDOR_ATTR_GSCAN_SSID_THRESHOLD_PARAM_RSSI_LOW = 41, + /* Signed 32-bit value */ + QCA_WLAN_VENDOR_ATTR_GSCAN_SSID_THRESHOLD_PARAM_RSSI_HIGH = 42, + /* Unsigned 32-bit value; a bitmask with additional gscan config flag. + */ + QCA_WLAN_VENDOR_ATTR_GSCAN_CONFIGURATION_FLAGS = 43, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_MAX = + QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_AFTER_LAST - 1, +}; + +enum qca_wlan_vendor_attr_gscan_results { + QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_INVALID = 0, + + /* Unsigned 32-bit value; must match the request Id supplied by + * Wi-Fi HAL in the corresponding subcmd NL msg. + */ + QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_REQUEST_ID = 1, + + /* Unsigned 32-bit value; used to indicate the status response from + * firmware/driver for the vendor sub-command. + */ + QCA_WLAN_VENDOR_ATTR_GSCAN_STATUS = 2, + + /* GSCAN Valid Channels attributes */ + /* Unsigned 32bit value; followed by a nested array of CHANNELS. */ + QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_CHANNELS = 3, + /* An array of NUM_CHANNELS x unsigned 32-bit value integers + * representing channel numbers. + */ + QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CHANNELS = 4, + + /* GSCAN Capabilities attributes */ + /* Unsigned 32-bit value */ + QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_CACHE_SIZE = 5, + /* Unsigned 32-bit value */ + QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_BUCKETS = 6, + /* Unsigned 32-bit value */ + QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_AP_CACHE_PER_SCAN + = 7, + /* Unsigned 32-bit value */ + QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_RSSI_SAMPLE_SIZE + = 8, + /* Signed 32-bit value */ + QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_REPORTING_THRESHOLD + = 9, + /* Unsigned 32-bit value */ + QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_BSSIDS = 10, + /* Unsigned 32-bit value */ + QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SIGNIFICANT_WIFI_CHANGE_APS + = 11, + /* Unsigned 32-bit value */ + QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_BSSID_HISTORY_ENTRIES + = 12, + + /* GSCAN Attributes used with + * QCA_NL80211_VENDOR_SUBCMD_GSCAN_SCAN_RESULTS_AVAILABLE sub-command. + */ + + /* Unsigned 32-bit value */ + QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE = 13, + + /* GSCAN attributes used with + * QCA_NL80211_VENDOR_SUBCMD_GSCAN_FULL_SCAN_RESULT sub-command. + */ + + /* An array of NUM_RESULTS_AVAILABLE x + * QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_* + */ + QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_LIST = 14, + + /* Unsigned 64-bit value; age of sample at the time of retrieval */ + QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_TIME_STAMP = 15, + /* 33 x unsigned 8-bit value; NULL terminated SSID */ + QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_SSID = 16, + /* An array of 6 x unsigned 8-bit value */ + QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BSSID = 17, + /* Unsigned 32-bit value; channel frequency in MHz */ + QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_CHANNEL = 18, + /* Signed 32-bit value */ + QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RSSI = 19, + /* Unsigned 32-bit value */ + QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT = 20, + /* Unsigned 32-bit value */ + QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT_SD = 21, + /* Unsigned 16-bit value */ + QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BEACON_PERIOD = 22, + /* Unsigned 16-bit value */ + QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_CAPABILITY = 23, + /* Unsigned 32-bit value; size of the IE DATA blob */ + QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_IE_LENGTH = 24, + /* An array of IE_LENGTH x unsigned 8-bit value; blob of all the + * information elements found in the beacon; this data should be a + * packed list of wifi_information_element objects, one after the + * other. + */ + QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_IE_DATA = 25, + + /* Unsigned 8-bit value; set by driver to indicate more scan results are + * available. + */ + QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_MORE_DATA = 26, + + /* GSCAN attributes for + * QCA_NL80211_VENDOR_SUBCMD_GSCAN_SCAN_EVENT sub-command. + */ + /* Unsigned 8-bit value */ + QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_EVENT_TYPE = 27, + /* Unsigned 32-bit value */ + QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_EVENT_STATUS = 28, + + /* GSCAN attributes for + * QCA_NL80211_VENDOR_SUBCMD_GSCAN_HOTLIST_AP_FOUND sub-command. + */ + /* Use attr QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE + * to indicate number of results. + * Also, use QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_LIST to indicate the + * list of results. + */ + + /* GSCAN attributes for + * QCA_NL80211_VENDOR_SUBCMD_GSCAN_SIGNIFICANT_CHANGE sub-command. + */ + /* An array of 6 x unsigned 8-bit value */ + QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_BSSID = 29, + /* Unsigned 32-bit value */ + QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_CHANNEL + = 30, + /* Unsigned 32-bit value. */ + QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_NUM_RSSI + = 31, + /* A nested array of signed 32-bit RSSI values. Size of the array is + * determined by (NUM_RSSI of SIGNIFICANT_CHANGE_RESULT_NUM_RSSI. + */ + QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_RSSI_LIST + = 32, + + /* GSCAN attributes used with + * QCA_NL80211_VENDOR_SUBCMD_GSCAN_GET_CACHED_RESULTS sub-command. + */ + /* Use attr QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE + * to indicate number of gscan cached results returned. + * Also, use QCA_WLAN_VENDOR_ATTR_GSCAN_CACHED_RESULTS_LIST to indicate + * the list of gscan cached results. + */ + + /* An array of NUM_RESULTS_AVAILABLE x + * QCA_NL80211_VENDOR_ATTR_GSCAN_CACHED_RESULTS_* + */ + QCA_WLAN_VENDOR_ATTR_GSCAN_CACHED_RESULTS_LIST = 33, + /* Unsigned 32-bit value; a unique identifier for the scan unit. */ + QCA_WLAN_VENDOR_ATTR_GSCAN_CACHED_RESULTS_SCAN_ID = 34, + /* Unsigned 32-bit value; a bitmask w/additional information about scan. + */ + QCA_WLAN_VENDOR_ATTR_GSCAN_CACHED_RESULTS_FLAGS = 35, + /* Use attr QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE + * to indicate number of wifi scan results/bssids retrieved by the scan. + * Also, use QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_LIST to indicate the + * list of wifi scan results returned for each cached result block. + */ + + /* GSCAN attributes for + * QCA_NL80211_VENDOR_SUBCMD_PNO_NETWORK_FOUND sub-command. + */ + /* Use QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE for + * number of results. + * Use QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_LIST to indicate the nested + * list of wifi scan results returned for each + * wifi_passpoint_match_result block. + * Array size: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE. + */ + + /* GSCAN attributes for + * QCA_NL80211_VENDOR_SUBCMD_PNO_PASSPOINT_NETWORK_FOUND sub-command. + */ + /* Unsigned 32-bit value */ + QCA_WLAN_VENDOR_ATTR_GSCAN_PNO_RESULTS_PASSPOINT_NETWORK_FOUND_NUM_MATCHES + = 36, + /* A nested array of + * QCA_WLAN_VENDOR_ATTR_GSCAN_PNO_RESULTS_PASSPOINT_MATCH_* + * attributes. Array size = + * *_ATTR_GSCAN_PNO_RESULTS_PASSPOINT_NETWORK_FOUND_NUM_MATCHES. + */ + QCA_WLAN_VENDOR_ATTR_GSCAN_PNO_RESULTS_PASSPOINT_MATCH_RESULT_LIST = 37, + + /* Unsigned 32-bit value; network block id for the matched network */ + QCA_WLAN_VENDOR_ATTR_GSCAN_PNO_RESULTS_PASSPOINT_MATCH_ID = 38, + /* Use QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_LIST to indicate the nested + * list of wifi scan results returned for each + * wifi_passpoint_match_result block. + */ + /* Unsigned 32-bit value */ + QCA_WLAN_VENDOR_ATTR_GSCAN_PNO_RESULTS_PASSPOINT_MATCH_ANQP_LEN = 39, + /* An array size of PASSPOINT_MATCH_ANQP_LEN of unsigned 8-bit values; + * ANQP data in the information_element format. + */ + QCA_WLAN_VENDOR_ATTR_GSCAN_PNO_RESULTS_PASSPOINT_MATCH_ANQP = 40, + + /* Unsigned 32-bit value; a GSCAN Capabilities attribute. */ + QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_SSIDS = 41, + /* Unsigned 32-bit value; a GSCAN Capabilities attribute. */ + QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS = 42, + /* Unsigned 32-bit value; a GSCAN Capabilities attribute. */ + QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS_BY_SSID + = 43, + /* Unsigned 32-bit value; a GSCAN Capabilities attribute. */ + QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_WHITELISTED_SSID + = 44, + + QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_BUCKETS_SCANNED = 45, + + /* Unsigned 32-bit value; a GSCAN Capabilities attribute. + * This is used to limit the maximum number of BSSIDs while sending + * the vendor command QCA_NL80211_VENDOR_SUBCMD_ROAM with attributes + * QCA_WLAN_VENDOR_ATTR_ROAM_SUBCMD_SET_BLACKLIST_BSSID and + * QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID. + */ + QCA_WLAN_VENDOR_ATTR_GSCAN_MAX_NUM_BLACKLISTED_BSSID = 46, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX = + QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_AFTER_LAST - 1, +}; + +enum qca_wlan_vendor_attr_pno_config_params { + QCA_WLAN_VENDOR_ATTR_PNO_INVALID = 0, + /* Attributes for data used by + * QCA_NL80211_VENDOR_SUBCMD_PNO_SET_PASSPOINT_LIST sub command. + */ + /* Unsigned 32-bit value */ + QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NUM = 1, + /* Array of nested QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_* + * attributes. Array size = + * QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NUM. + */ + QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NETWORK_ARRAY = 2, + + /* Unsigned 32-bit value */ + QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ID = 3, + /* An array of 256 x unsigned 8-bit value; NULL terminated UTF-8 encoded + * realm, 0 if unspecified. + */ + QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_REALM = 4, + /* An array of 16 x unsigned 32-bit value; roaming consortium ids to + * match, 0 if unspecified. + */ + QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ROAM_CNSRTM_ID = 5, + /* An array of 6 x unsigned 8-bit value; MCC/MNC combination, 0s if + * unspecified. + */ + QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ROAM_PLMN = 6, + + /* Attributes for data used by + * QCA_NL80211_VENDOR_SUBCMD_PNO_SET_LIST sub command. + */ + /* Unsigned 32-bit value */ + QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_NUM_NETWORKS = 7, + /* Array of nested + * QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_* + * attributes. Array size = + * QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_NUM_NETWORKS. + */ + QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORKS_LIST = 8, + /* An array of 33 x unsigned 8-bit value; NULL terminated SSID */ + QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_SSID = 9, + /* Signed 8-bit value; threshold for considering this SSID as found, + * required granularity for this threshold is 4 dBm to 8 dBm. + */ + QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_RSSI_THRESHOLD + = 10, + /* Unsigned 8-bit value; WIFI_PNO_FLAG_XXX */ + QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_FLAGS = 11, + /* Unsigned 8-bit value; auth bit field for matching WPA IE */ + QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_AUTH_BIT = 12, + /* Unsigned 8-bit to indicate ePNO type; + * It takes values from qca_wlan_epno_type + */ + QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_TYPE = 13, + + /* Nested attribute to send the channel list */ + QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_CHANNEL_LIST = 14, + + /* Unsigned 32-bit value; indicates the interval between PNO scan + * cycles in msec. + */ + QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_SCAN_INTERVAL = 15, + QCA_WLAN_VENDOR_ATTR_EPNO_MIN5GHZ_RSSI = 16, + QCA_WLAN_VENDOR_ATTR_EPNO_MIN24GHZ_RSSI = 17, + QCA_WLAN_VENDOR_ATTR_EPNO_INITIAL_SCORE_MAX = 18, + QCA_WLAN_VENDOR_ATTR_EPNO_CURRENT_CONNECTION_BONUS = 19, + QCA_WLAN_VENDOR_ATTR_EPNO_SAME_NETWORK_BONUS = 20, + QCA_WLAN_VENDOR_ATTR_EPNO_SECURE_BONUS = 21, + QCA_WLAN_VENDOR_ATTR_EPNO_BAND5GHZ_BONUS = 22, + /* Unsigned 32-bit value, representing the PNO Request ID */ + QCA_WLAN_VENDOR_ATTR_PNO_CONFIG_REQUEST_ID = 23, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_PNO_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_PNO_MAX = + QCA_WLAN_VENDOR_ATTR_PNO_AFTER_LAST - 1, +}; + +/** + * qca_wlan_vendor_acs_select_reason: This represents the different reasons why + * the ACS has to be triggered. These values are used by + * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_REASON and + * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_REASON + */ +enum qca_wlan_vendor_acs_select_reason { + /* Represents the reason that the ACS triggered during the AP start */ + QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT, + /* Represents the reason that DFS found with the current channel */ + QCA_WLAN_VENDOR_ACS_SELECT_REASON_DFS, + /* Represents the reason that LTE co-exist in the current band. */ + QCA_WLAN_VENDOR_ACS_SELECT_REASON_LTE_COEX, +}; + +/** + * qca_wlan_vendor_attr_external_acs_policy: Attribute values for + * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_POLICY to the vendor subcmd + * QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS. This represents the + * external ACS policies to select the channels w.r.t. the PCL weights. + * (QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PCL represents the channels and + * their PCL weights.) + * @QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_POLICY_PCL_MANDATORY: Mandatory to + * select a channel with non-zero PCL weight. + * @QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_POLICY_PCL_PREFERRED: Prefer a + * channel with non-zero PCL weight. + * + */ +enum qca_wlan_vendor_attr_external_acs_policy { + QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_POLICY_PCL_PREFERRED, + QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_POLICY_PCL_MANDATORY, +}; + +/** + * qca_wlan_vendor_channel_prop_flags: This represent the flags for a channel. + * This is used by QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAGS. + */ +enum qca_wlan_vendor_channel_prop_flags { + /* Bits 0, 1, 2, and 3 are reserved */ + + /* Turbo channel */ + QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_TURBO = 1 << 4, + /* CCK channel */ + QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_CCK = 1 << 5, + /* OFDM channel */ + QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_OFDM = 1 << 6, + /* 2.4 GHz spectrum channel. */ + QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_2GHZ = 1 << 7, + /* 5 GHz spectrum channel */ + QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_5GHZ = 1 << 8, + /* Only passive scan allowed */ + QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_PASSIVE = 1 << 9, + /* Dynamic CCK-OFDM channel */ + QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_DYN = 1 << 10, + /* GFSK channel (FHSS PHY) */ + QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_GFSK = 1 << 11, + /* Radar found on channel */ + QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_RADAR = 1 << 12, + /* 11a static turbo channel only */ + QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_STURBO = 1 << 13, + /* Half rate channel */ + QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_HALF = 1 << 14, + /* Quarter rate channel */ + QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_QUARTER = 1 << 15, + /* HT 20 channel */ + QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_HT20 = 1 << 16, + /* HT 40 with extension channel above */ + QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_HT40PLUS = 1 << 17, + /* HT 40 with extension channel below */ + QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_HT40MINUS = 1 << 18, + /* HT 40 intolerant */ + QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_HT40INTOL = 1 << 19, + /* VHT 20 channel */ + QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_VHT20 = 1 << 20, + /* VHT 40 with extension channel above */ + QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_VHT40PLUS = 1 << 21, + /* VHT 40 with extension channel below */ + QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_VHT40MINUS = 1 << 22, + /* VHT 80 channel */ + QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_VHT80 = 1 << 23, + /* HT 40 intolerant mark bit for ACS use */ + QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_HT40INTOLMARK = 1 << 24, + /* Channel temporarily blocked due to noise */ + QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_BLOCKED = 1 << 25, + /* VHT 160 channel */ + QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_VHT160 = 1 << 26, + /* VHT 80+80 channel */ + QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_VHT80_80 = 1 << 27, + /* HE 20 channel */ + QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_HE20 = 1 << 28, + /* HE 40 with extension channel above */ + QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_HE40PLUS = 1 << 29, + /* HE 40 with extension channel below */ + QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_HE40MINUS = 1 << 30, + /* HE 40 intolerant */ + QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_HE40INTOL = 1 << 31, +}; + +/** + * qca_wlan_vendor_channel_prop_flags_2: This represents the flags for a + * channel, and is a continuation of qca_wlan_vendor_channel_prop_flags. This is + * used by QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAGS_2. + */ +enum qca_wlan_vendor_channel_prop_flags_2 { + /* HE 40 intolerant mark bit for ACS use */ + QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_HE40INTOLMARK = 1 << 0, + /* HE 80 channel */ + QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_HE80 = 1 << 1, + /* HE 160 channel */ + QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_HE160 = 1 << 2, + /* HE 80+80 channel */ + QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_HE80_80 = 1 << 3, +}; + +/** + * qca_wlan_vendor_channel_prop_flags_ext: This represent the extended flags for + * each channel. This is used by + * QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAG_EXT. + */ +enum qca_wlan_vendor_channel_prop_flags_ext { + /* Radar found on channel */ + QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_EXT_RADAR_FOUND = 1 << 0, + /* DFS required on channel */ + QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_EXT_DFS = 1 << 1, + /* DFS required on channel for 2nd band of 80+80 */ + QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_EXT_DFS_CFREQ2 = 1 << 2, + /* If channel has been checked for DFS */ + QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_EXT_DFS_CLEAR = 1 << 3, + /* Excluded in 802.11d */ + QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_EXT_11D_EXCLUDED = 1 << 4, + /* Channel Switch Announcement received on this channel */ + QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_EXT_CSA_RECEIVED = 1 << 5, + /* Ad-hoc is not allowed */ + QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_EXT_DISALLOW_ADHOC = 1 << 6, + /* Station only channel */ + QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_EXT_DISALLOW_HOSTAP = 1 << 7, + /* DFS radar history for slave device (STA mode) */ + QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_EXT_HISTORY_RADAR = 1 << 8, + /* DFS CAC valid for slave device (STA mode) */ + QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_EXT_CAC_VALID = 1 << 9, +}; + +/** + * qca_wlan_vendor_external_acs_event_chan_info_attr: Represents per channel + * information. These attributes are sent as part of + * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO. Each set of the following + * attributes correspond to a single channel. + */ +enum qca_wlan_vendor_external_acs_event_chan_info_attr { + QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_INVALID = 0, + + /* A bitmask (u32) with flags specified in + * enum qca_wlan_vendor_channel_prop_flags. + */ + QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAGS = 1, + /* A bitmask (u32) with flags specified in + * enum qca_wlan_vendor_channel_prop_flags_ext. + */ + QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAG_EXT = 2, + /* frequency in MHz (u32) */ + QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ = 3, + /* maximum regulatory transmission power (u32) */ + QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_REG_POWER = 4, + /* maximum transmission power (u32) */ + QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_POWER = 5, + /* minimum transmission power (u32) */ + QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MIN_POWER = 6, + /* regulatory class id (u8) */ + QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_REG_CLASS_ID = 7, + /* maximum antenna gain in (u8) */ + QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_ANTENNA_GAIN = 8, + /* VHT segment 0 (u8) */ + QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_0 = 9, + /* VHT segment 1 (u8) */ + QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_1 = 10, + /* A bitmask (u32) with flags specified in + * enum qca_wlan_vendor_channel_prop_flags_2. + */ + QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAGS_2 = 11, + + /* keep last */ + QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_LAST, + QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX = + QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_LAST - 1, +}; + +/** + * qca_wlan_vendor_attr_pcl: Represents attributes for + * preferred channel list (PCL). These attributes are sent as part of + * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PCL and + * QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST. + */ +enum qca_wlan_vendor_attr_pcl { + QCA_WLAN_VENDOR_ATTR_PCL_INVALID = 0, + + /* Channel number (u8) */ + QCA_WLAN_VENDOR_ATTR_PCL_CHANNEL = 1, + /* Channel weightage (u8) */ + QCA_WLAN_VENDOR_ATTR_PCL_WEIGHT = 2, + /* Channel frequency (u32) in MHz */ + QCA_WLAN_VENDOR_ATTR_PCL_FREQ = 3, + /* Channel flags (u32) + * bit 0 set: channel to be used for GO role, + * bit 1 set: channel to be used on CLI role, + * bit 2 set: channel must be considered for operating channel + * selection & peer chosen operating channel should be + * one of the channels with this flag set, + * bit 3 set: channel should be excluded in GO negotiation + */ + QCA_WLAN_VENDOR_ATTR_PCL_FLAG = 4, +}; + +/** + * qca_wlan_vendor_attr_external_acs_event: Attribute to vendor sub-command + * QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS. This attribute will be sent by + * host driver. + */ +enum qca_wlan_vendor_attr_external_acs_event { + QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_INVALID = 0, + + /* This reason (u8) refers to enum qca_wlan_vendor_acs_select_reason. + * This helps ACS module to understand why ACS needs to be started. + */ + QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_REASON = 1, + /* Flag attribute to indicate if driver supports spectral scanning */ + QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_SPECTRAL_SUPPORTED = 2, + /* Flag attribute to indicate if 11ac is offloaded to firmware */ + QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_OFFLOAD_ENABLED = 3, + /* Flag attribute to indicate if driver provides additional channel + * capability as part of scan operation + */ + QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_ADD_CHAN_STATS_SUPPORT = 4, + /* Flag attribute to indicate interface status is UP */ + QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_AP_UP = 5, + /* Operating mode (u8) of interface. Takes one of enum nl80211_iftype + * values. + */ + QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_SAP_MODE = 6, + /* Channel width (u8). It takes one of enum nl80211_chan_width values. + * This is the upper bound of channel width. ACS logic should try to get + * a channel with the specified width and if not found, look for lower + * values. + */ + QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_WIDTH = 7, + /* This (u8) will hold values of one of enum nl80211_bands */ + QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_BAND = 8, + /* PHY/HW mode (u8). Takes one of enum qca_wlan_vendor_acs_hw_mode + * values + */ + QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PHY_MODE = 9, + /* Array of (u32) supported frequency list among which ACS should choose + * best frequency. + */ + QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_FREQ_LIST = 10, + /* Preferred channel list by the driver which will have array of nested + * values as per enum qca_wlan_vendor_attr_pcl attribute. + */ + QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PCL = 11, + /* Array of nested attribute for each channel. It takes attr as defined + * in enum qca_wlan_vendor_external_acs_event_chan_info_attr. + */ + QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO = 12, + /* External ACS policy such as PCL mandatory, PCL preferred, etc. + * It uses values defined in enum + * qca_wlan_vendor_attr_external_acs_policy. + */ + QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_POLICY = 13, + /* Reference RF Operating Parameter (RROP) availability information + * (u16). It uses values defined in enum + * qca_wlan_vendor_attr_rropavail_info. + */ + QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_RROPAVAIL_INFO = 14, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_LAST, + QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_MAX = + QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_LAST - 1, +}; + +/** + * qca_wlan_vendor_attr_external_acs_channels: Attributes to vendor subcmd + * QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS. This carries a list of channels + * in priority order as decided after ACS operation in userspace. + */ +enum qca_wlan_vendor_attr_external_acs_channels { + QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_INVALID = 0, + + /* One of reason code (u8) from enum qca_wlan_vendor_acs_select_reason + */ + QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_REASON = 1, + + /* Array of nested values for each channel with following attributes: + * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_BAND, + * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_PRIMARY, + * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_SECONDARY, + * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG0, + * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG1, + * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_WIDTH + */ + QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_LIST = 2, + /* This (u8) will hold values of one of enum nl80211_bands */ + QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_BAND = 3, + /* Primary channel (u8) */ + QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_PRIMARY = 4, + /* Secondary channel (u8) used for HT 40 MHz channels */ + QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_SECONDARY = 5, + /* VHT seg0 channel (u8) */ + QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG0 = 6, + /* VHT seg1 channel (u8) */ + QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG1 = 7, + /* Channel width (u8). Takes one of enum nl80211_chan_width values. */ + QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_WIDTH = 8, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_LAST, + QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_MAX = + QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_LAST - 1 +}; + +enum qca_chip_power_save_failure_reason { + /* Indicates if the reason for the failure is due to a protocol + * layer/module. + */ + QCA_CHIP_POWER_SAVE_FAILURE_REASON_PROTOCOL = 0, + /* Indicates if the reason for the failure is due to a hardware issue. + */ + QCA_CHIP_POWER_SAVE_FAILURE_REASON_HARDWARE = 1, +}; + +/** + * qca_attr_chip_power_save_failure: Attributes to vendor subcmd + * QCA_NL80211_VENDOR_SUBCMD_CHIP_PWRSAVE_FAILURE. This carries the requisite + * information leading to the power save failure. + */ +enum qca_attr_chip_power_save_failure { + QCA_ATTR_CHIP_POWER_SAVE_FAILURE_INVALID = 0, + /* Reason to cause the power save failure. + * These reasons are represented by + * enum qca_chip_power_save_failure_reason. + */ + QCA_ATTR_CHIP_POWER_SAVE_FAILURE_REASON = 1, + + /* keep last */ + QCA_ATTR_CHIP_POWER_SAVE_FAILURE_LAST, + QCA_ATTR_CHIP_POWER_SAVE_FAILURE_MAX = + QCA_ATTR_CHIP_POWER_SAVE_FAILURE_LAST - 1, +}; + +/** + * qca_wlan_vendor_nud_stats_data_pkt_flags: Flag representing the various + * data types for which the stats have to get collected. + */ +enum qca_wlan_vendor_nud_stats_data_pkt_flags { + QCA_WLAN_VENDOR_NUD_STATS_DATA_ARP = 1 << 0, + QCA_WLAN_VENDOR_NUD_STATS_DATA_DNS = 1 << 1, + QCA_WLAN_VENDOR_NUD_STATS_DATA_TCP_HANDSHAKE = 1 << 2, + QCA_WLAN_VENDOR_NUD_STATS_DATA_ICMPV4 = 1 << 3, + QCA_WLAN_VENDOR_NUD_STATS_DATA_ICMPV6 = 1 << 4, + /* Used by QCA_ATTR_NUD_STATS_PKT_TYPE only in nud stats get + * to represent the stats of respective data type. + */ + QCA_WLAN_VENDOR_NUD_STATS_DATA_TCP_SYN = 1 << 5, + QCA_WLAN_VENDOR_NUD_STATS_DATA_TCP_SYN_ACK = 1 << 6, + QCA_WLAN_VENDOR_NUD_STATS_DATA_TCP_ACK = 1 << 7, +}; + +enum qca_wlan_vendor_nud_stats_set_data_pkt_info { + QCA_ATTR_NUD_STATS_DATA_PKT_INFO_INVALID = 0, + /* Represents the data packet type to be monitored (u32). + * Host driver tracks the stats corresponding to each data frame + * represented by these flags. + * These data packets are represented by + * enum qca_wlan_vendor_nud_stats_data_pkt_flags + */ + QCA_ATTR_NUD_STATS_DATA_PKT_INFO_TYPE = 1, + /* Name corresponding to the DNS frame for which the respective DNS + * stats have to get monitored (string). Max string length 255. + */ + QCA_ATTR_NUD_STATS_DATA_PKT_INFO_DNS_DOMAIN_NAME = 2, + /* source port on which the respective proto stats have to get + * collected (u32). + */ + QCA_ATTR_NUD_STATS_DATA_PKT_INFO_SRC_PORT = 3, + /* destination port on which the respective proto stats have to get + * collected (u32). + */ + QCA_ATTR_NUD_STATS_DATA_PKT_INFO_DEST_PORT = 4, + /* IPv4 address for which the destined data packets have to be + * monitored. (in network byte order), u32. + */ + QCA_ATTR_NUD_STATS_DATA_PKT_INFO_DEST_IPV4 = 5, + /* IPv6 address for which the destined data packets have to be + * monitored. (in network byte order), 16 bytes array. + */ + QCA_ATTR_NUD_STATS_DATA_PKT_INFO_DEST_IPV6 = 6, + + QCA_ATTR_NUD_STATS_DATA_PKT_INFO_LAST, + QCA_ATTR_NUD_STATS_DATA_PKT_INFO_MAX = + QCA_ATTR_NUD_STATS_DATA_PKT_INFO_LAST - 1, +}; + +/** + * qca_wlan_vendor_attr_nud_stats_set: Attributes to vendor subcmd + * QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_SET. This carries the requisite + * information to start/stop the NUD statistics collection. + */ +enum qca_attr_nud_stats_set { + QCA_ATTR_NUD_STATS_SET_INVALID = 0, + + /* Flag to start/stop the NUD statistics collection. + * Start - If included, Stop - If not included + */ + QCA_ATTR_NUD_STATS_SET_START = 1, + /* IPv4 address of the default gateway (in network byte order), u32 */ + QCA_ATTR_NUD_STATS_GW_IPV4 = 2, + /* Represents the list of data packet types to be monitored. + * Host driver tracks the stats corresponding to each data frame + * represented by these flags. + * These data packets are represented by + * enum qca_wlan_vendor_nud_stats_set_data_pkt_info + */ + QCA_ATTR_NUD_STATS_SET_DATA_PKT_INFO = 3, + + /* keep last */ + QCA_ATTR_NUD_STATS_SET_LAST, + QCA_ATTR_NUD_STATS_SET_MAX = + QCA_ATTR_NUD_STATS_SET_LAST - 1, +}; + +enum qca_attr_nud_data_stats { + QCA_ATTR_NUD_DATA_STATS_INVALID = 0, + /* Data packet type for which the stats are collected (u32). + * Represented by enum qca_wlan_vendor_nud_stats_data_pkt_flags + */ + QCA_ATTR_NUD_STATS_PKT_TYPE = 1, + /* Name corresponding to the DNS frame for which the respective DNS + * stats are monitored (string). Max string length 255. + */ + QCA_ATTR_NUD_STATS_PKT_DNS_DOMAIN_NAME = 2, + /* source port on which the respective proto stats are collected (u32). + */ + QCA_ATTR_NUD_STATS_PKT_SRC_PORT = 3, + /* destination port on which the respective proto stats are collected + * (u32). + */ + QCA_ATTR_NUD_STATS_PKT_DEST_PORT = 4, + /* IPv4 address for which the destined data packets have to be + * monitored. (in network byte order), u32. + */ + QCA_ATTR_NUD_STATS_PKT_DEST_IPV4 = 5, + /* IPv6 address for which the destined data packets have to be + * monitored. (in network byte order), 16 bytes array. + */ + QCA_ATTR_NUD_STATS_PKT_DEST_IPV6 = 6, + /* Data packet Request count received from netdev (u32). */ + QCA_ATTR_NUD_STATS_PKT_REQ_COUNT_FROM_NETDEV = 7, + /* Data packet Request count sent to lower MAC from upper MAC (u32). */ + QCA_ATTR_NUD_STATS_PKT_REQ_COUNT_TO_LOWER_MAC = 8, + /* Data packet Request count received by lower MAC from upper MAC + * (u32) + */ + QCA_ATTR_NUD_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC = 9, + /* Data packet Request count successfully transmitted by the device + * (u32) + */ + QCA_ATTR_NUD_STATS_PKT_REQ_COUNT_TX_SUCCESS = 10, + /* Data packet Response count received by lower MAC (u32) */ + QCA_ATTR_NUD_STATS_PKT_RSP_RX_COUNT_BY_LOWER_MAC = 11, + /* Data packet Response count received by upper MAC (u32) */ + QCA_ATTR_NUD_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC = 12, + /* Data packet Response count delivered to netdev (u32) */ + QCA_ATTR_NUD_STATS_PKT_RSP_COUNT_TO_NETDEV = 13, + /* Data Packet Response count that are dropped out of order (u32) */ + QCA_ATTR_NUD_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP = 14, + + /* keep last */ + QCA_ATTR_NUD_DATA_STATS_LAST, + QCA_ATTR_NUD_DATA_STATS_MAX = + QCA_ATTR_NUD_DATA_STATS_LAST - 1, +}; + +/** + * qca_attr_nud_stats_get: Attributes to vendor subcmd + * QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET. This carries the requisite + * NUD statistics collected when queried. + */ +enum qca_attr_nud_stats_get { + QCA_ATTR_NUD_STATS_GET_INVALID = 0, + /* ARP Request count from netdev (u32) */ + QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_FROM_NETDEV = 1, + /* ARP Request count sent to lower MAC from upper MAC (u32) */ + QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TO_LOWER_MAC = 2, + /* ARP Request count received by lower MAC from upper MAC (u32) */ + QCA_ATTR_NUD_STATS_ARP_REQ_RX_COUNT_BY_LOWER_MAC = 3, + /* ARP Request count successfully transmitted by the device (u32) */ + QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TX_SUCCESS = 4, + /* ARP Response count received by lower MAC (u32) */ + QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_LOWER_MAC = 5, + /* ARP Response count received by upper MAC (u32) */ + QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_UPPER_MAC = 6, + /* ARP Response count delivered to netdev (u32) */ + QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_TO_NETDEV = 7, + /* ARP Response count dropped due to out of order reception (u32) */ + QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_OUT_OF_ORDER_DROP = 8, + /* Flag indicating if the station's link to the AP is active. + * Active Link - If included, Inactive link - If not included + */ + QCA_ATTR_NUD_STATS_AP_LINK_ACTIVE = 9, + /* Flag indicating if there is any duplicate address detected (DAD). + * Yes - If detected, No - If not detected. + */ + QCA_ATTR_NUD_STATS_IS_DAD = 10, + /* List of Data packet types for which the stats are requested. + * This list does not carry ARP stats as they are done by the + * above attributes. Represented by enum qca_attr_nud_data_stats. + */ + QCA_ATTR_NUD_STATS_DATA_PKT_STATS = 11, + + /* keep last */ + QCA_ATTR_NUD_STATS_GET_LAST, + QCA_ATTR_NUD_STATS_GET_MAX = + QCA_ATTR_NUD_STATS_GET_LAST - 1, +}; + +enum qca_wlan_btm_candidate_status { + QCA_STATUS_ACCEPT = 0, + QCA_STATUS_REJECT_EXCESSIVE_FRAME_LOSS_EXPECTED = 1, + QCA_STATUS_REJECT_EXCESSIVE_DELAY_EXPECTED = 2, + QCA_STATUS_REJECT_INSUFFICIENT_QOS_CAPACITY = 3, + QCA_STATUS_REJECT_LOW_RSSI = 4, + QCA_STATUS_REJECT_HIGH_INTERFERENCE = 5, + QCA_STATUS_REJECT_UNKNOWN = 6, +}; + +enum qca_wlan_vendor_attr_btm_candidate_info { + QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_INVALID = 0, + + /* 6-byte MAC address representing the BSSID of transition candidate */ + QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_BSSID = 1, + /* Unsigned 32-bit value from enum qca_wlan_btm_candidate_status + * returned by the driver. It says whether the BSSID provided in + * QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_BSSID is acceptable by + * the driver, if not it specifies the reason for rejection. + * Note that the user-space can overwrite the transition reject reason + * codes provided by driver based on more information. + */ + QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_STATUS = 2, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_MAX = + QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_AFTER_LAST - 1, +}; + +enum qca_attr_trace_level { + QCA_ATTR_TRACE_LEVEL_INVALID = 0, + /* + * Nested array of the following attributes: + * QCA_ATTR_TRACE_LEVEL_MODULE, + * QCA_ATTR_TRACE_LEVEL_MASK. + */ + QCA_ATTR_TRACE_LEVEL_PARAM = 1, + /* + * Specific QCA host driver module. Please refer to the QCA host + * driver implementation to get the specific module ID. + */ + QCA_ATTR_TRACE_LEVEL_MODULE = 2, + /* Different trace level masks represented in the QCA host driver. */ + QCA_ATTR_TRACE_LEVEL_MASK = 3, + + /* keep last */ + QCA_ATTR_TRACE_LEVEL_AFTER_LAST, + QCA_ATTR_TRACE_LEVEL_MAX = + QCA_ATTR_TRACE_LEVEL_AFTER_LAST - 1, +}; + +/** + * enum qca_wlan_vendor_attr_get_he_capabilities - IEEE 802.11ax HE capabilities + */ +enum qca_wlan_vendor_attr_get_he_capabilities { + QCA_WLAN_VENDOR_ATTR_HE_CAPABILITIES_INVALID = 0, + /* Whether HE capabilities is supported + * (u8 attribute: 0 = not supported, 1 = supported) + */ + QCA_WLAN_VENDOR_ATTR_HE_SUPPORTED = 1, + /* HE PHY capabilities, array of 3 u32 values */ + QCA_WLAN_VENDOR_ATTR_PHY_CAPAB = 2, + /* HE MAC capabilities (u32 attribute) */ + QCA_WLAN_VENDOR_ATTR_MAC_CAPAB = 3, + /* HE MCS map (u32 attribute) */ + QCA_WLAN_VENDOR_ATTR_HE_MCS = 4, + /* Number of SS (u32 attribute) */ + QCA_WLAN_VENDOR_ATTR_NUM_SS = 5, + /* RU count (u32 attribute) */ + QCA_WLAN_VENDOR_ATTR_RU_IDX_MASK = 6, + /* PPE threshold data, array of 8 u32 values */ + QCA_WLAN_VENDOR_ATTR_PPE_THRESHOLD = 7, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_HE_CAPABILITIES_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_HE_CAPABILITIES_MAX = + QCA_WLAN_VENDOR_ATTR_HE_CAPABILITIES_AFTER_LAST - 1, +}; + +/** + * enum qca_wlan_vendor_attr_spectral_scan - Spectral scan config parameters + */ +enum qca_wlan_vendor_attr_spectral_scan { + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_INVALID = 0, + /* Number of times the chip enters spectral scan mode before + * deactivating spectral scans. When set to 0, chip will enter spectral + * scan mode continuously. u32 attribute. + */ + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SCAN_COUNT = 1, + /* Spectral scan period. Period increment resolution is 256*Tclk, + * where Tclk = 1/44 MHz (Gmode), 1/40 MHz (Amode). u32 attribute. + */ + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SCAN_PERIOD = 2, + /* Spectral scan priority. u32 attribute. */ + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_PRIORITY = 3, + /* Number of FFT data points to compute. u32 attribute. */ + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_SIZE = 4, + /* Enable targeted gain change before starting the spectral scan FFT. + * u32 attribute. + */ + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_GC_ENA = 5, + /* Restart a queued spectral scan. u32 attribute. */ + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RESTART_ENA = 6, + /* Noise floor reference number for the calculation of bin power. + * u32 attribute. + */ + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_NOISE_FLOOR_REF = 7, + /* Disallow spectral scan triggers after TX/RX packets by setting + * this delay value to roughly SIFS time period or greater. + * u32 attribute. + */ + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_INIT_DELAY = 8, + /* Number of strong bins (inclusive) per sub-channel, below + * which a signal is declared a narrow band tone. u32 attribute. + */ + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_NB_TONE_THR = 9, + /* Specify the threshold over which a bin is declared strong (for + * scan bandwidth analysis). u32 attribute. + */ + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_STR_BIN_THR = 10, + /* Spectral scan report mode. u32 attribute. */ + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_WB_RPT_MODE = 11, + /* RSSI report mode, if the ADC RSSI is below + * QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_THR, + * then FFTs will not trigger, but timestamps and summaries get + * reported. u32 attribute. + */ + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_RPT_MODE = 12, + /* ADC RSSI must be greater than or equal to this threshold (signed dB) + * to ensure spectral scan reporting with normal error code. + * u32 attribute. + */ + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_THR = 13, + /* Format of frequency bin magnitude for spectral scan triggered FFTs: + * 0: linear magnitude, 1: log magnitude (20*log10(lin_mag)). + * u32 attribute. + */ + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_PWR_FORMAT = 14, + /* Format of FFT report to software for spectral scan triggered FFTs. + * 0: No FFT report (only spectral scan summary report) + * 1: 2-dword summary of metrics for each completed FFT + spectral scan + * report + * 2: 2-dword summary of metrics for each completed FFT + 1x-oversampled + * bins (in-band) per FFT + spectral scan summary report + * 3: 2-dword summary of metrics for each completed FFT + 2x-oversampled + * bins (all) per FFT + spectral scan summary report + * u32 attribute. + */ + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RPT_MODE = 15, + /* Number of LSBs to shift out in order to scale the FFT bins. + * u32 attribute. + */ + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_BIN_SCALE = 16, + /* Set to 1 (with spectral_scan_pwr_format=1), to report bin magnitudes + * in dBm power. u32 attribute. + */ + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DBM_ADJ = 17, + /* Per chain enable mask to select input ADC for search FFT. + * u32 attribute. + */ + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_CHN_MASK = 18, + /* An unsigned 64-bit integer provided by host driver to identify the + * spectral scan request. This attribute is included in the scan + * response message for @QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_START + * and used as an attribute in + * @QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_STOP to identify the + * specific scan to be stopped. + */ + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_COOKIE = 19, + /* Skip interval for FFT reports. u32 attribute */ + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_PERIOD = 20, + /* Set to report only one set of FFT results. + * u32 attribute. + */ + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SHORT_REPORT = 21, + /* Debug level for spectral module in driver. + * 0 : Verbosity level 0 + * 1 : Verbosity level 1 + * 2 : Verbosity level 2 + * 3 : Matched filterID display + * 4 : One time dump of FFT report + * u32 attribute. + */ + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DEBUG_LEVEL = 22, + /* Type of spectral scan request. u32 attribute. + * It uses values defined in enum + * qca_wlan_vendor_attr_spectral_scan_request_type. + */ + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_REQUEST_TYPE = 23, + + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_MAX = + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_AFTER_LAST - 1, +}; + +/** + * enum qca_wlan_vendor_attr_spectral_diag_stats - Used by the vendor command + * QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_GET_DIAG_STATS. + */ +enum qca_wlan_vendor_attr_spectral_diag_stats { + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_INVALID = 0, + /* Number of spectral TLV signature mismatches. + * u64 attribute. + */ + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_SIG_MISMATCH = 1, + /* Number of spectral phyerror events with insufficient length when + * parsing for secondary 80 search FFT report. u64 attribute. + */ + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_SEC80_SFFT_INSUFFLEN = 2, + /* Number of spectral phyerror events without secondary 80 + * search FFT report. u64 attribute. + */ + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_NOSEC80_SFFT = 3, + /* Number of spectral phyerror events with vht operation segment 1 id + * mismatches in search fft report. u64 attribute. + */ + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_VHTSEG1ID_MISMATCH = 4, + /* Number of spectral phyerror events with vht operation segment 2 id + * mismatches in search fft report. u64 attribute. + */ + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_VHTSEG2ID_MISMATCH = 5, + + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_MAX = + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_AFTER_LAST - 1, +}; + +/** + * enum qca_wlan_vendor_attr_spectral_cap - Used by the vendor command + * QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_GET_CAP_INFO. + */ +enum qca_wlan_vendor_attr_spectral_cap { + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_INVALID = 0, + /* Flag attribute to indicate phydiag capability */ + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_PHYDIAG = 1, + /* Flag attribute to indicate radar detection capability */ + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_RADAR = 2, + /* Flag attribute to indicate spectral capability */ + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_SPECTRAL = 3, + /* Flag attribute to indicate advanced spectral capability */ + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_ADVANCED_SPECTRAL = 4, + /* Spectral hardware generation. u32 attribute. + * It uses values defined in enum + * qca_wlan_vendor_spectral_scan_cap_hw_gen. + */ + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_HW_GEN = 5, + /* Spectral bin scaling formula ID. u16 attribute. + * It uses values defined in enum + * qca_wlan_vendor_spectral_scan_cap_formula_id. + */ + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_FORMULA_ID = 6, + /* Spectral bin scaling param - low level offset. + * s16 attribute. + */ + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_LOW_LEVEL_OFFSET = 7, + /* Spectral bin scaling param - high level offset. + * s16 attribute. + */ + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_HIGH_LEVEL_OFFSET = 8, + /* Spectral bin scaling param - RSSI threshold. + * s16 attribute. + */ + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_RSSI_THR = 9, + /* Spectral bin scaling param - default AGC max gain. + * u8 attribute. + */ + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_DEFAULT_AGC_MAX_GAIN = 10, + + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_MAX = + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_AFTER_LAST - 1, +}; + +/** + * enum qca_wlan_vendor_attr_spectral_scan_status - used by the vendor command + * QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_GET_STATUS. + */ +enum qca_wlan_vendor_attr_spectral_scan_status { + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_STATUS_INVALID = 0, + /* Flag attribute to indicate whether spectral scan is enabled */ + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_STATUS_IS_ENABLED = 1, + /* Flag attribute to indicate whether spectral scan is in progress*/ + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_STATUS_IS_ACTIVE = 2, + + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_STATUS_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_STATUS_MAX = + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_STATUS_AFTER_LAST - 1, +}; + +/** + * qca_wlan_vendor_attr_spectral_scan_request_type: Attribute values for + * QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_REQUEST_TYPE to the vendor subcmd + * QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_START. This represents the + * spectral scan request types. + * @QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_REQUEST_TYPE_SCAN_AND_CONFIG: Request to + * set the spectral parameters and start scan. + * @QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_REQUEST_TYPE_SCAN: Request to + * only set the spectral parameters. + * @QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_REQUEST_TYPE_CONFIG: Request to + * only start the spectral scan. + */ +enum qca_wlan_vendor_attr_spectral_scan_request_type { + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_REQUEST_TYPE_SCAN_AND_CONFIG, + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_REQUEST_TYPE_SCAN, + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_REQUEST_TYPE_CONFIG, +}; + +/** + * qca_wlan_vendor_spectral_scan_cap_hw_gen: Attribute values for + * QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_HW_GEN to the vendor subcmd + * QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_GET_CAP_INFO. This represents the + * spectral hardware generation. + * @QCA_WLAN_VENDOR_SPECTRAL_SCAN_CAP_HW_GEN_1: generation 1 + * @QCA_WLAN_VENDOR_SPECTRAL_SCAN_CAP_HW_GEN_2: generation 2 + * @QCA_WLAN_VENDOR_SPECTRAL_SCAN_CAP_HW_GEN_3: generation 3 + */ +enum qca_wlan_vendor_spectral_scan_cap_hw_gen { + QCA_WLAN_VENDOR_SPECTRAL_SCAN_CAP_HW_GEN_1 = 0, + QCA_WLAN_VENDOR_SPECTRAL_SCAN_CAP_HW_GEN_2 = 1, + QCA_WLAN_VENDOR_SPECTRAL_SCAN_CAP_HW_GEN_3 = 2, +}; + +enum qca_wlan_vendor_tos { + QCA_WLAN_VENDOR_TOS_BK = 0, + QCA_WLAN_VENDOR_TOS_BE = 1, + QCA_WLAN_VENDOR_TOS_VI = 2, + QCA_WLAN_VENDOR_TOS_VO = 3, +}; + +/** + * enum qca_wlan_vendor_attr_active_tos - Used by the vendor command + * QCA_NL80211_VENDOR_SUBCMD_ACTIVE_TOS. + */ +enum qca_wlan_vendor_attr_active_tos { + QCA_WLAN_VENDOR_ATTR_ACTIVE_TOS_INVALID = 0, + /* Type Of Service - Represented by qca_wlan_vendor_tos */ + QCA_WLAN_VENDOR_ATTR_ACTIVE_TOS = 1, + /* Flag attribute representing the start (attribute included) or stop + * (attribute not included) of the respective TOS. + */ + QCA_WLAN_VENDOR_ATTR_ACTIVE_TOS_START = 2, +}; + +enum qca_wlan_vendor_hang_reason { + /* Unspecified reason */ + QCA_WLAN_HANG_REASON_UNSPECIFIED = 0, + /* No Map for the MAC entry for the received frame */ + QCA_WLAN_HANG_RX_HASH_NO_ENTRY_FOUND = 1, + /* Peer deletion timeout happened */ + QCA_WLAN_HANG_PEER_DELETION_TIMEDOUT = 2, + /* Peer unmap timeout */ + QCA_WLAN_HANG_PEER_UNMAP_TIMEDOUT = 3, + /* Scan request timed out */ + QCA_WLAN_HANG_SCAN_REQ_EXPIRED = 4, + /* Consecutive Scan attempt failures */ + QCA_WLAN_HANG_SCAN_ATTEMPT_FAILURES = 5, + /* Unable to get the message buffer */ + QCA_WLAN_HANG_GET_MSG_BUFF_FAILURE = 6, + /* Current command processing is timedout */ + QCA_WLAN_HANG_ACTIVE_LIST_TIMEOUT = 7, + /* Timeout for an ACK from FW for suspend request */ + QCA_WLAN_HANG_SUSPEND_TIMEOUT = 8, + /* Timeout for an ACK from FW for resume request */ + QCA_WLAN_HANG_RESUME_TIMEOUT = 9, + /* Transmission timeout for consecutive data frames */ + QCA_WLAN_HANG_TRANSMISSIONS_TIMEOUT = 10, + /* Timeout for the TX completion status of data frame */ + QCA_WLAN_HANG_TX_COMPLETE_TIMEOUT = 11, + /* DXE failure for TX/RX, DXE resource unavailability */ + QCA_WLAN_HANG_DXE_FAILURE = 12, + /* WMI pending commands exceed the maximum count */ + QCA_WLAN_HANG_WMI_EXCEED_MAX_PENDING_CMDS = 13, +}; + +/** + * enum qca_wlan_vendor_attr_hang - Used by the vendor command + * QCA_NL80211_VENDOR_SUBCMD_HANG. + */ +enum qca_wlan_vendor_attr_hang { + QCA_WLAN_VENDOR_ATTR_HANG_INVALID = 0, + /* Reason for the hang - u32 attribute with a value from enum + * qca_wlan_vendor_hang_reason. + */ + QCA_WLAN_VENDOR_ATTR_HANG_REASON = 1, + + QCA_WLAN_VENDOR_ATTR_HANG_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_HANG_MAX = + QCA_WLAN_VENDOR_ATTR_HANG_AFTER_LAST - 1, +}; + +/** + * enum qca_wlan_vendor_attr_flush_pending - Attributes for + * flushing pending traffic in firmware. + * + * @QCA_WLAN_VENDOR_ATTR_PEER_ADDR: Configure peer MAC address. + * @QCA_WLAN_VENDOR_ATTR_AC: Configure access category of the pending + * packets. It is u8 value with bit 0~3 represent AC_BE, AC_BK, + * AC_VI, AC_VO respectively. Set the corresponding bit to 1 to + * flush packets with access category. + */ +enum qca_wlan_vendor_attr_flush_pending { + QCA_WLAN_VENDOR_ATTR_FLUSH_PENDING_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_PEER_ADDR = 1, + QCA_WLAN_VENDOR_ATTR_AC = 2, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_FLUSH_PENDING_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_FLUSH_PENDING_MAX = + QCA_WLAN_VENDOR_ATTR_FLUSH_PENDING_AFTER_LAST - 1, +}; + +/** + * qca_wlan_vendor_spectral_scan_cap_formula_id: Attribute values for + * QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_FORMULA_ID in the vendor subcmd + * QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_GET_CAP_INFO. This represents the + * Spectral bin scaling formula ID. + * @QCA_WLAN_VENDOR_SPECTRAL_SCAN_CAP_NO_SCALING: No scaling + * @QCA_WLAN_VENDOR_SPECTRAL_SCAN_CAP_AGC_GAIN_RSSI_CORR_BASED: AGC gain + * and RSSI threshold based formula. + */ +enum qca_wlan_vendor_spectral_scan_cap_formula_id { + QCA_WLAN_VENDOR_SPECTRAL_SCAN_CAP_NO_SCALING = 0, + QCA_WLAN_VENDOR_SPECTRAL_SCAN_CAP_AGC_GAIN_RSSI_CORR_BASED = 1, +}; + +/** + * enum qca_wlan_vendor_attr_rropavail_info - Specifies whether Representative + * RF Operating Parameter (RROP) information is available, and if so, at which + * point in the application-driver interaction sequence it can be retrieved by + * the application from the driver. This point may vary by architecture and + * other factors. This is a u16 value. + */ +enum qca_wlan_vendor_attr_rropavail_info { + /* RROP information is unavailable. */ + QCA_WLAN_VENDOR_ATTR_RROPAVAIL_INFO_UNAVAILABLE, + /* RROP information is available and the application can retrieve the + * information after receiving an QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS + * event from the driver. + */ + QCA_WLAN_VENDOR_ATTR_RROPAVAIL_INFO_EXTERNAL_ACS_START, + /* RROP information is available only after a vendor specific scan + * (requested using QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN) has + * successfully completed. The application can retrieve the information + * after receiving the QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE event from + * the driver. + */ + QCA_WLAN_VENDOR_ATTR_RROPAVAIL_INFO_VSCAN_END, +}; + +/** + * enum qca_wlan_vendor_attr_rrop_info - Specifies vendor specific + * Representative RF Operating Parameter (RROP) information. It is sent for the + * vendor command QCA_NL80211_VENDOR_SUBCMD_GET_RROP_INFO. This information is + * intended for use by external Auto Channel Selection applications. It provides + * guidance values for some RF parameters that are used by the system during + * operation. These values could vary by channel, band, radio, and so on. + */ +enum qca_wlan_vendor_attr_rrop_info { + QCA_WLAN_VENDOR_ATTR_RROP_INFO_INVALID = 0, + + /* Representative Tx Power List (RTPL) which has an array of nested + * values as per attributes in enum qca_wlan_vendor_attr_rtplinst. + */ + QCA_WLAN_VENDOR_ATTR_RROP_INFO_RTPL = 1, + + QCA_WLAN_VENDOR_ATTR_RROP_INFO_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_RROP_INFO_MAX = + QCA_WLAN_VENDOR_ATTR_RROP_INFO_AFTER_LAST - 1 +}; + +/** + * enum qca_wlan_vendor_attr_rtplinst - Specifies attributes for individual list + * entry instances in the Representative Tx Power List (RTPL). It provides + * simplified power values intended for helping external Auto channel Selection + * applications compare potential Tx power performance between channels, other + * operating conditions remaining identical. These values are not necessarily + * the actual Tx power values that will be used by the system. They are also not + * necessarily the max or average values that will be used. Instead, they are + * relative, summarized keys for algorithmic use computed by the driver or + * underlying firmware considering a number of vendor specific factors. + */ +enum qca_wlan_vendor_attr_rtplinst { + QCA_WLAN_VENDOR_ATTR_RTPLINST_INVALID = 0, + + /* Primary channel number (u8) */ + QCA_WLAN_VENDOR_ATTR_RTPLINST_PRIMARY = 1, + /* Representative Tx power in dBm (s32) with emphasis on throughput. */ + QCA_WLAN_VENDOR_ATTR_RTPLINST_TXPOWER_THROUGHPUT = 2, + /* Representative Tx power in dBm (s32) with emphasis on range. */ + QCA_WLAN_VENDOR_ATTR_RTPLINST_TXPOWER_RANGE = 3, + + QCA_WLAN_VENDOR_ATTR_RTPLINST_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_RTPLINST_MAX = + QCA_WLAN_VENDOR_ATTR_RTPLINST_AFTER_LAST - 1, +}; + +/** + * enum qca_wlan_vendor_attr_config_latency_level - Level for + * wlan latency module. + * + * There will be various of Wi-Fi functionality like scan/roaming/adaptive + * power saving which would causing data exchange out of service, this + * would be a big impact on latency. For latency sensitive applications over + * Wi-Fi are intolerant to such operations and thus would configure them + * to meet their respective needs. It is well understood by such applications + * that altering the default behavior would degrade the Wi-Fi functionality + * w.r.t the above pointed WLAN operations. + * + * @QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_NORMAL: + * Default WLAN operation level which throughput orientated. + * @QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_MODERATE: + * Use moderate level to improve latency by limit scan duration. + * @QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_LOW: + * Use low latency level to benifit application like concurrent + * downloading or video streaming via constraint scan/adaptive PS. + * @QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_ULTRALOW: + * Use ultra low latency level to benefit for gaming/voice + * application via constraint scan/roaming/adaptive PS. + */ +enum qca_wlan_vendor_attr_config_latency_level { + QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_NORMAL = 1, + QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_MODERATE = 2, + QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_LOW = 3, + QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_ULTRALOW = 4, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_MAX = + QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_AFTER_LAST - 1, +}; + +/** + * enum qca_wlan_vendor_attr_wlan_mac - Used by the vendor command + * QCA_NL80211_VENDOR_SUBCMD_WLAN_MAC_INFO. + */ +enum qca_wlan_vendor_attr_mac { + QCA_WLAN_VENDOR_ATTR_MAC_INVALID = 0, + + /* MAC mode info list which has an array of nested values as + * per attributes in enum qca_wlan_vendor_attr_mac_mode_info. + */ + QCA_WLAN_VENDOR_ATTR_MAC_INFO = 1, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_MAC_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_MAC_MAX = + QCA_WLAN_VENDOR_ATTR_MAC_AFTER_LAST - 1, +}; + +/** + * enum qca_wlan_vendor_attr_mac_iface_info - Information of the connected + * Wi-Fi netdev interface on a respective MAC. + * Used by the attribute QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO. + */ +enum qca_wlan_vendor_attr_mac_iface_info { + QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO_INVALID = 0, + /* Wi-Fi netdev's interface index (u32) */ + QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO_IFINDEX = 1, + /* Associated frequency in MHz of the connected Wi-Fi interface (u32) */ + QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO_FREQ = 2, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO_MAX = + QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO_AFTER_LAST - 1, +}; + +/** + * enum qca_wlan_vendor_attr_mac_info - Points to MAC the information. + * Used by the attribute QCA_WLAN_VENDOR_ATTR_MAC_INFO of the + * vendor command QCA_NL80211_VENDOR_SUBCMD_WLAN_MAC_INFO. + */ +enum qca_wlan_vendor_attr_mac_info { + QCA_WLAN_VENDOR_ATTR_MAC_INFO_INVALID = 0, + /* Hardware MAC ID associated for the MAC (u32) */ + QCA_WLAN_VENDOR_ATTR_MAC_INFO_MAC_ID = 1, + /* Band supported by the MAC at a given point. + * This is a u32 bitmask of BIT(NL80211_BAND_*) as described in %enum + * nl80211_band. + */ + QCA_WLAN_VENDOR_ATTR_MAC_INFO_BAND = 2, + /* Refers to list of WLAN netdev interfaces associated with this MAC. + * Represented by enum qca_wlan_vendor_attr_mac_iface_info. + */ + QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO = 3, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_MAC_INFO_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_MAC_INFO_MAX = + QCA_WLAN_VENDOR_ATTR_MAC_INFO_AFTER_LAST - 1, +}; + +/** + * enum qca_wlan_vendor_attr_get_logger_features - Used by the vendor command + * QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET. + */ +enum qca_wlan_vendor_attr_get_logger_features { + QCA_WLAN_VENDOR_ATTR_LOGGER_INVALID = 0, + /* Unsigned 32-bit enum value of wifi_logger_supported_features */ + QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED = 1, + /* keep last */ + QCA_WLAN_VENDOR_ATTR_LOGGER_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_LOGGER_MAX = + QCA_WLAN_VENDOR_ATTR_LOGGER_AFTER_LAST - 1, +}; + +/** + * enum wifi_logger_supported_features - Values for supported logger features + */ +enum wifi_logger_supported_features { + WIFI_LOGGER_MEMORY_DUMP_FEATURE = (1 << (0)), + WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_FEATURE = (1 << (1)), + WIFI_LOGGER_CONNECT_EVENT_FEATURE = (1 << (2)), + WIFI_LOGGER_POWER_EVENT_FEATURE = (1 << (3)), + WIFI_LOGGER_WAKE_LOCK_FEATURE = (1 << (4)), + WIFI_LOGGER_VERBOSE_FEATURE = (1 << (5)), + WIFI_LOGGER_WATCHDOG_TIMER_FEATURE = (1 << (6)), + WIFI_LOGGER_DRIVER_DUMP_FEATURE = (1 << (7)), + WIFI_LOGGER_PACKET_FATE_FEATURE = (1 << (8)), +}; + +/** + * enum qca_wlan_tdls_caps_features_supported - Values for TDLS get + * capabilities features + */ +enum qca_wlan_tdls_caps_features_supported { + WIFI_TDLS_SUPPORT = (1 << (0)), + WIFI_TDLS_EXTERNAL_CONTROL_SUPPORT = (1 << (1)), + WIFI_TDLS_OFFCHANNEL_SUPPORT = (1 << (2)) +}; + +/** + * enum qca_wlan_vendor_attr_tdls_get_capabilities - Used by the vendor command + * QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES. + */ +enum qca_wlan_vendor_attr_tdls_get_capabilities { + QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_INVALID = 0, + /* Indicates the max concurrent sessions */ + /* Unsigned 32-bit value */ + QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_MAX_CONC_SESSIONS, + /* Indicates the support for features */ + /* Unsigned 32-bit bitmap qca_wlan_tdls_caps_features_supported + */ + QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_FEATURES_SUPPORTED, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_MAX = + QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_AFTER_LAST - 1, +}; + +/** + * enum qca_wlan_offloaded_packets_sending_control - Offload packets control + * command used as value for the attribute + * QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL. + */ +enum qca_wlan_offloaded_packets_sending_control { + QCA_WLAN_OFFLOADED_PACKETS_SENDING_CONTROL_INVALID = 0, + QCA_WLAN_OFFLOADED_PACKETS_SENDING_START, + QCA_WLAN_OFFLOADED_PACKETS_SENDING_STOP +}; + +/** + * enum qca_wlan_vendor_attr_offloaded_packets - Used by the vendor command + * QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS. + */ +enum qca_wlan_vendor_attr_offloaded_packets { + QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_INVALID = 0, + /* Takes valid value from the enum + * qca_wlan_offloaded_packets_sending_control + * Unsigned 32-bit value + */ + QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL, + /* Unsigned 32-bit value */ + QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID, + /* array of u8 len: Max packet size */ + QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA, + /* 6-byte MAC address used to represent source MAC address */ + QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR, + /* 6-byte MAC address used to represent destination MAC address */ + QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR, + /* Unsigned 32-bit value, in milli seconds */ + QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD, + /* This optional unsigned 16-bit attribute is used for specifying + * ethernet protocol type. If not specified ethertype defaults to IPv4. + */ + QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_ETHER_PROTO_TYPE, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX = + QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_AFTER_LAST - 1, +}; + +/** + * enum qca_wlan_rssi_monitoring_control - RSSI control commands used as values + * by the attribute QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL. + */ +enum qca_wlan_rssi_monitoring_control { + QCA_WLAN_RSSI_MONITORING_CONTROL_INVALID = 0, + QCA_WLAN_RSSI_MONITORING_START, + QCA_WLAN_RSSI_MONITORING_STOP, +}; + +/** + * enum qca_wlan_vendor_attr_rssi_monitoring - Used by the vendor command + * QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI. + */ +enum qca_wlan_vendor_attr_rssi_monitoring { + QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_INVALID = 0, + /* Takes valid value from the enum + * qca_wlan_rssi_monitoring_control + * Unsigned 32-bit value enum qca_wlan_rssi_monitoring_control + */ + QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL, + /* Unsigned 32-bit value */ + QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID, + /* Signed 8-bit value in dBm */ + QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI, + /* Signed 8-bit value in dBm */ + QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI, + /* attributes to be used/received in callback */ + /* 6-byte MAC address used to represent current BSSID MAC address */ + QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID, + /* Signed 8-bit value indicating the current RSSI */ + QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI, + /* keep last */ + QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX = + QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_AFTER_LAST - 1, +}; + +/** + * enum qca_wlan_vendor_attr_ndp_params - Used by the vendor command + * QCA_NL80211_VENDOR_SUBCMD_NDP. + */ +enum qca_wlan_vendor_attr_ndp_params { + QCA_WLAN_VENDOR_ATTR_NDP_PARAM_INVALID = 0, + /* Unsigned 32-bit value + * enum of sub commands values in qca_wlan_ndp_sub_cmd + */ + QCA_WLAN_VENDOR_ATTR_NDP_SUBCMD, + /* Unsigned 16-bit value */ + QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID, + /* NL attributes for data used NDP SUB cmds */ + /* Unsigned 32-bit value indicating a service info */ + QCA_WLAN_VENDOR_ATTR_NDP_SERVICE_INSTANCE_ID, + /* Unsigned 32-bit value; channel frequency in MHz */ + QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL, + /* Interface Discovery MAC address. An array of 6 Unsigned int8 */ + QCA_WLAN_VENDOR_ATTR_NDP_PEER_DISCOVERY_MAC_ADDR, + /* Interface name on which NDP is being created */ + QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR, + /* Unsigned 32-bit value for security */ + /* CONFIG_SECURITY is deprecated, use NCS_SK_TYPE/PMK/SCID instead */ + QCA_WLAN_VENDOR_ATTR_NDP_CONFIG_SECURITY, + /* Unsigned 32-bit value for QoS */ + QCA_WLAN_VENDOR_ATTR_NDP_CONFIG_QOS, + /* Array of u8: len = QCA_WLAN_VENDOR_ATTR_NAN_DP_APP_INFO_LEN */ + QCA_WLAN_VENDOR_ATTR_NDP_APP_INFO, + /* Unsigned 32-bit value for NDP instance Id */ + QCA_WLAN_VENDOR_ATTR_NDP_INSTANCE_ID, + /* Array of instance Ids */ + QCA_WLAN_VENDOR_ATTR_NDP_INSTANCE_ID_ARRAY, + /* Unsigned 32-bit value for initiator/responder NDP response code + * accept/reject + */ + QCA_WLAN_VENDOR_ATTR_NDP_RESPONSE_CODE, + /* NDI MAC address. An array of 6 Unsigned int8 */ + QCA_WLAN_VENDOR_ATTR_NDP_NDI_MAC_ADDR, + /* Unsigned 32-bit value errors types returned by driver + * The wifi_nan.h in AOSP project platform/hardware/libhardware_legacy + * NanStatusType includes these values. + */ + QCA_WLAN_VENDOR_ATTR_NDP_DRV_RESPONSE_STATUS_TYPE, + /* Unsigned 32-bit value error values returned by driver + * The nan_i.h in AOSP project platform/hardware/qcom/wlan + * NanInternalStatusType includes these values. + */ + QCA_WLAN_VENDOR_ATTR_NDP_DRV_RETURN_VALUE, + /* Unsigned 32-bit value for Channel setup configuration + * The wifi_nan.h in AOSP project platform/hardware/libhardware_legacy + * NanDataPathChannelCfg includes these values. + */ + QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL_CONFIG, + /* Unsigned 32-bit value for Cipher Suite Shared Key Type */ + QCA_WLAN_VENDOR_ATTR_NDP_CSID, + /* Array of u8: len = NAN_PMK_INFO_LEN 32 bytes */ + QCA_WLAN_VENDOR_ATTR_NDP_PMK, + /* Security Context Identifier that contains the PMKID + * Array of u8: len = NAN_SCID_BUF_LEN 1024 bytes + */ + QCA_WLAN_VENDOR_ATTR_NDP_SCID, + /* Array of u8: len = NAN_SECURITY_MAX_PASSPHRASE_LEN 63 bytes */ + QCA_WLAN_VENDOR_ATTR_NDP_PASSPHRASE, + /* Array of u8: len = NAN_MAX_SERVICE_NAME_LEN 255 bytes */ + QCA_WLAN_VENDOR_ATTR_NDP_SERVICE_NAME, + /* Unsigned 32-bit bitmap indicating schedule update + * BIT_0: NSS Update + * BIT_1: Channel list update + */ + QCA_WLAN_VENDOR_ATTR_NDP_SCHEDULE_UPDATE_REASON, + /* Unsigned 32-bit value for NSS */ + QCA_WLAN_VENDOR_ATTR_NDP_NSS, + /* Unsigned 32-bit value for NUMBER NDP CHANNEL */ + QCA_WLAN_VENDOR_ATTR_NDP_NUM_CHANNELS, + /* Unsigned 32-bit value for CHANNEL BANDWIDTH + * 0:20 MHz, 1:40 MHz, 2:80 MHz, 3:160 MHz + */ + QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL_WIDTH, + /* Array of channel/band width */ + QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL_INFO, + /* IPv6 address used by NDP (in network byte order), 16 bytes array. + * This attribute is used and optional for ndp request, ndp response, + * ndp indication, and ndp confirm. + */ + QCA_WLAN_VENDOR_ATTR_NDP_IPV6_ADDR = 27, + /* Unsigned 16-bit value indicating transport port used by NDP. + * This attribute is used and optional for ndp response, ndp indication, + * and ndp confirm. + */ + QCA_WLAN_VENDOR_ATTR_NDP_TRANSPORT_PORT = 28, + /* Unsigned 8-bit value indicating protocol used by NDP and assigned by + * the Internet Assigned Numbers Authority (IANA) as per: + * https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml + * This attribute is used and optional for ndp response, ndp indication, + * and ndp confirm. + */ + QCA_WLAN_VENDOR_ATTR_NDP_TRANSPORT_PROTOCOL = 29, + /* Unsigned 8-bit value indicating if NDP remote peer supports NAN NDPE. + * 1:support 0:not support + */ + QCA_WLAN_VENDOR_ATTR_PEER_NDPE_SUPPORT = 30, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_NDP_PARAMS_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_NDP_PARAMS_MAX = + QCA_WLAN_VENDOR_ATTR_NDP_PARAMS_AFTER_LAST - 1, +}; + +enum qca_wlan_ndp_sub_cmd { + QCA_WLAN_VENDOR_ATTR_NDP_INVALID = 0, + /* Command to create a NAN data path interface */ + QCA_WLAN_VENDOR_ATTR_NDP_INTERFACE_CREATE = 1, + /* Command to delete a NAN data path interface */ + QCA_WLAN_VENDOR_ATTR_NDP_INTERFACE_DELETE = 2, + /* Command to initiate a NAN data path session */ + QCA_WLAN_VENDOR_ATTR_NDP_INITIATOR_REQUEST = 3, + /* Command to notify if the NAN data path session was sent */ + QCA_WLAN_VENDOR_ATTR_NDP_INITIATOR_RESPONSE = 4, + /* Command to respond to NAN data path session */ + QCA_WLAN_VENDOR_ATTR_NDP_RESPONDER_REQUEST = 5, + /* Command to notify on the responder about the response */ + QCA_WLAN_VENDOR_ATTR_NDP_RESPONDER_RESPONSE = 6, + /* Command to initiate a NAN data path end */ + QCA_WLAN_VENDOR_ATTR_NDP_END_REQUEST = 7, + /* Command to notify the if end request was sent */ + QCA_WLAN_VENDOR_ATTR_NDP_END_RESPONSE = 8, + /* Command to notify the peer about the end request */ + QCA_WLAN_VENDOR_ATTR_NDP_REQUEST_IND = 9, + /* Command to confirm the NAN data path session is complete */ + QCA_WLAN_VENDOR_ATTR_NDP_CONFIRM_IND = 10, + /* Command to indicate the peer about the end request being received */ + QCA_WLAN_VENDOR_ATTR_NDP_END_IND = 11, + /* Command to indicate the peer of schedule update */ + QCA_WLAN_VENDOR_ATTR_NDP_SCHEDULE_UPDATE_IND = 12 +}; + +/** + * enum qca_wlan_vendor_attr_nd_offload - Used by the vendor command + * QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD. + */ +enum qca_wlan_vendor_attr_nd_offload { + QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_INVALID = 0, + /* Flag to set Neighbour Discovery offload */ + QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG, + /* Keep last */ + QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX = + QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_AFTER_LAST - 1, +}; + +/** + * enum packet_filter_sub_cmd - Packet filter sub commands + */ +enum packet_filter_sub_cmd { + /** + * Write packet filter program and/or data. The driver/firmware should + * disable APF before writing into local buffer and re-enable APF after + * writing is done. + */ + QCA_WLAN_SET_PACKET_FILTER = 1, + /* Get packet filter feature capabilities from driver */ + QCA_WLAN_GET_PACKET_FILTER = 2, + /** + * Write packet filter program and/or data. User space will send the + * %QCA_WLAN_DISABLE_PACKET_FILTER command before issuing this command + * and will send the %QCA_WLAN_ENABLE_PACKET_FILTER afterwards. The key + * difference from that %QCA_WLAN_SET_PACKET_FILTER is the control over + * enable/disable is given to user space with this command. Also, + * user space sends the length of program portion in the buffer within + * %QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROG_LENGTH. + */ + QCA_WLAN_WRITE_PACKET_FILTER = 3, + /* Read packet filter program and/or data */ + QCA_WLAN_READ_PACKET_FILTER = 4, + /* Enable APF feature */ + QCA_WLAN_ENABLE_PACKET_FILTER = 5, + /* Disable APF feature */ + QCA_WLAN_DISABLE_PACKET_FILTER = 6, +}; + +/** + * enum qca_wlan_vendor_attr_packet_filter - BPF control commands used by + * vendor QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER. + */ +enum qca_wlan_vendor_attr_packet_filter { + QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID = 0, + /* Unsigned 32-bit enum passed using packet_filter_sub_cmd */ + QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD, + /* Unsigned 32-bit value indicating the packet filter version */ + QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION, + /* Unsigned 32-bit value indicating the packet filter id */ + QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID, + /** + * Unsigned 32-bit value indicating the packet filter size including + * program + data. + */ + QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE, + /* Unsigned 32-bit value indicating the packet filter current offset */ + QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET, + /* Program and/or data in bytes */ + QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM, + /* Unsigned 32-bit value of the length of the program section in packet + * filter buffer. + */ + QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROG_LENGTH = 7, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX = + QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_AFTER_LAST - 1, +}; + +/** + * enum qca_wlan_vendor_drv_info - WLAN driver info used by vendor command + * QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE. + */ +enum qca_wlan_vendor_drv_info { + QCA_WLAN_VENDOR_ATTR_DRV_INFO_INVALID = 0, + /* Maximum Message size info between firmware & HOST + * Unsigned 32-bit value + */ + QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE, + /* keep last */ + QCA_WLAN_VENDOR_ATTR_DRV_INFO_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_DRV_INFO_MAX = + QCA_WLAN_VENDOR_ATTR_DRV_INFO_AFTER_LAST - 1, +}; + +/** + * enum qca_wlan_vendor_attr_wake_stats - Wake lock stats used by vendor + * command QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS. + */ +enum qca_wlan_vendor_attr_wake_stats { + QCA_WLAN_VENDOR_ATTR_WAKE_STATS_INVALID = 0, + /* Unsigned 32-bit value indicating the total count of wake event */ + QCA_WLAN_VENDOR_ATTR_WAKE_STATS_TOTAL_CMD_EVENT_WAKE, + /* Array of individual wake count, each index representing wake reason + */ + QCA_WLAN_VENDOR_ATTR_WAKE_STATS_CMD_EVENT_WAKE_CNT_PTR, + /* Unsigned 32-bit value representing wake count array */ + QCA_WLAN_VENDOR_ATTR_WAKE_STATS_CMD_EVENT_WAKE_CNT_SZ, + /* Unsigned 32-bit total wake count value of driver/fw */ + QCA_WLAN_VENDOR_ATTR_WAKE_STATS_TOTAL_DRIVER_FW_LOCAL_WAKE, + /* Array of wake stats of driver/fw */ + QCA_WLAN_VENDOR_ATTR_WAKE_STATS_DRIVER_FW_LOCAL_WAKE_CNT_PTR, + /* Unsigned 32-bit total wake count value of driver/fw */ + QCA_WLAN_VENDOR_ATTR_WAKE_STATS_DRIVER_FW_LOCAL_WAKE_CNT_SZ, + /* Unsigned 32-bit total wake count value of packets received */ + QCA_WLAN_VENDOR_ATTR_WAKE_STATS_TOTAL_RX_DATA_WAKE, + /* Unsigned 32-bit wake count value unicast packets received */ + QCA_WLAN_VENDOR_ATTR_WAKE_STATS_RX_UNICAST_CNT, + /* Unsigned 32-bit wake count value multicast packets received */ + QCA_WLAN_VENDOR_ATTR_WAKE_STATS_RX_MULTICAST_CNT, + /* Unsigned 32-bit wake count value broadcast packets received */ + QCA_WLAN_VENDOR_ATTR_WAKE_STATS_RX_BROADCAST_CNT, + /* Unsigned 32-bit wake count value of ICMP packets */ + QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP_PKT, + /* Unsigned 32-bit wake count value of ICMP6 packets */ + QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_PKT, + /* Unsigned 32-bit value ICMP6 router advertisement */ + QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_RA, + /* Unsigned 32-bit value ICMP6 neighbor advertisement */ + QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_NA, + /* Unsigned 32-bit value ICMP6 neighbor solicitation */ + QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_NS, + /* Unsigned 32-bit wake count value of receive side ICMP4 multicast */ + QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP4_RX_MULTICAST_CNT, + /* Unsigned 32-bit wake count value of receive side ICMP6 multicast */ + QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_RX_MULTICAST_CNT, + /* Unsigned 32-bit wake count value of receive side multicast */ + QCA_WLAN_VENDOR_ATTR_WAKE_STATS_OTHER_RX_MULTICAST_CNT, + /* Unsigned 32-bit wake count value of a given RSSI breach */ + QCA_WLAN_VENDOR_ATTR_WAKE_STATS_RSSI_BREACH_CNT, + /* Unsigned 32-bit wake count value of low RSSI */ + QCA_WLAN_VENDOR_ATTR_WAKE_STATS_LOW_RSSI_CNT, + /* Unsigned 32-bit value GSCAN count */ + QCA_WLAN_VENDOR_ATTR_WAKE_STATS_GSCAN_CNT, + /* Unsigned 32-bit value PNO complete count */ + QCA_WLAN_VENDOR_ATTR_WAKE_STATS_PNO_COMPLETE_CNT, + /* Unsigned 32-bit value PNO match count */ + QCA_WLAN_VENDOR_ATTR_WAKE_STATS_PNO_MATCH_CNT, + /* keep last */ + QCA_WLAN_VENDOR_GET_WAKE_STATS_AFTER_LAST, + QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX = + QCA_WLAN_VENDOR_GET_WAKE_STATS_AFTER_LAST - 1, +}; + +/** + * enum qca_wlan_vendor_attr_thermal_cmd - Vendor subcmd attributes to set + * cmd value. Used for NL attributes for data used by + * QCA_NL80211_VENDOR_SUBCMD_THERMAL_CMD sub command. + */ +enum qca_wlan_vendor_attr_thermal_cmd { + QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_INVALID = 0, + /* The value of command, driver will implement different operations + * according to this value. It uses values defined in + * enum qca_wlan_vendor_attr_thermal_cmd_type. + * u32 attribute. + */ + QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_VALUE = 1, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_MAX = + QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_AFTER_LAST - 1 +}; + +/** + * qca_wlan_vendor_attr_thermal_cmd_type: Attribute values for + * QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_VALUE to the vendor subcmd + * QCA_NL80211_VENDOR_SUBCMD_THERMAL_CMD. This represents the + * thermal command types sent to driver. + * @QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_PARAMS: Request to + * get thermal shutdown configuration parameters for display. Parameters + * responded from driver are defined in + * enum qca_wlan_vendor_attr_get_thermal_params_rsp. + * @QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_TEMPERATURE: Request to + * get temperature. Host should respond with a temperature data. It is defined + * in enum qca_wlan_vendor_attr_thermal_get_temperature. + * @QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_SUSPEND: Request to execute thermal + * suspend action. + * @QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_RESUME: Request to execute thermal + * resume action. + */ +enum qca_wlan_vendor_attr_thermal_cmd_type { + QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_PARAMS, + QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_TEMPERATURE, + QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_SUSPEND, + QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_RESUME, +}; + +/** + * enum qca_wlan_vendor_attr_thermal_get_temperature - vendor subcmd attributes + * to get chip temperature by user. + * enum values are used for NL attributes for data used by + * QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_TEMPERATURE command for data used + * by QCA_NL80211_VENDOR_SUBCMD_THERMAL_CMD sub command. + */ +enum qca_wlan_vendor_attr_thermal_get_temperature { + QCA_WLAN_VENDOR_ATTR_THERMAL_GET_TEMPERATURE_INVALID = 0, + /* Temperature value (degree Celsius) from driver. + * u32 attribute. + */ + QCA_WLAN_VENDOR_ATTR_THERMAL_GET_TEMPERATURE_DATA, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_THERMAL_GET_TEMPERATURE_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_THERMAL_GET_TEMPERATURE_MAX = + QCA_WLAN_VENDOR_ATTR_THERMAL_GET_TEMPERATURE_AFTER_LAST - 1, +}; + +/** + * enum qca_wlan_vendor_attr_get_thermal_params_rsp - vendor subcmd attributes + * to get configuration parameters of thermal shutdown feature. Enum values are + * used by QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_PARAMS command for data + * used by QCA_NL80211_VENDOR_SUBCMD_THERMAL_CMD sub command. + */ +enum qca_wlan_vendor_attr_get_thermal_params_rsp { + QCA_WLAN_VENDOR_ATTR_GET_THERMAL_PARAMS_RSP_INVALID = 0, + /* Indicate if the thermal shutdown feature is enabled. + * NLA_FLAG attribute. + */ + QCA_WLAN_VENDOR_ATTR_GET_THERMAL_PARAMS_RSP_SHUTDOWN_EN, + /* Indicate if the auto mode is enabled. + * Enable: Driver triggers the suspend/resume action. + * Disable: User space triggers the suspend/resume action. + * NLA_FLAG attribute. + */ + QCA_WLAN_VENDOR_ATTR_GET_THERMAL_PARAMS_RSP_SHUTDOWN_AUTO_EN, + /* Thermal resume threshold (degree Celsius). Issue the resume command + * if the temperature value is lower than this threshold. + * u16 attribute. + */ + QCA_WLAN_VENDOR_ATTR_GET_THERMAL_PARAMS_RSP_RESUME_THRESH, + /* Thermal warning threshold (degree Celsius). FW reports temperature + * to driver if it's higher than this threshold. + * u16 attribute. + */ + QCA_WLAN_VENDOR_ATTR_GET_THERMAL_PARAMS_RSP_WARNING_THRESH, + /* Thermal suspend threshold (degree Celsius). Issue the suspend command + * if the temperature value is higher than this threshold. + * u16 attribute. + */ + QCA_WLAN_VENDOR_ATTR_GET_THERMAL_PARAMS_RSP_SUSPEND_THRESH, + /* FW reports temperature data periodically at this interval (ms). + * u16 attribute. + */ + QCA_WLAN_VENDOR_ATTR_GET_THERMAL_PARAMS_RSP_SAMPLE_RATE, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_GET_THERMAL_PARAMS_RSP_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_GET_THERMAL_PARAMS_RSP_MAX = + QCA_WLAN_VENDOR_ATTR_GET_THERMAL_PARAMS_RSP_AFTER_LAST - 1, +}; + +/** + * enum qca_wlan_vendor_attr_thermal_event - vendor subcmd attributes to + * report thermal events from driver to user space. + * enum values are used for NL attributes for data used by + * QCA_NL80211_VENDOR_SUBCMD_THERMAL_EVENT sub command. + */ +enum qca_wlan_vendor_attr_thermal_event { + QCA_WLAN_VENDOR_ATTR_THERMAL_EVENT_INVALID = 0, + /* Temperature value (degree Celsius) from driver. + * u32 attribute. + */ + QCA_WLAN_VENDOR_ATTR_THERMAL_EVENT_TEMPERATURE, + /* Indication of resume completion from power save mode. + * NLA_FLAG attribute. + */ + QCA_WLAN_VENDOR_ATTR_THERMAL_EVENT_RESUME_COMPLETE, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_THERMAL_EVENT_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_THERMAL_EVENT_MAX = + QCA_WLAN_VENDOR_ATTR_THERMAL_EVENT_AFTER_LAST - 1, +}; + +/** + * enum he_fragmentation_val - HE fragmentation support values + * Indicates level of dynamic fragmentation that is supported by + * a STA as a recipient. + * HE fragmentation values are defined in IEEE P802.11ax/D2.0, 9.4.2.237.2 + * (HE MAC Capabilities Information field) and are used in HE Capabilities + * element to advertise the support. These values are validated in the driver + * to check the device capability and advertised in the HE Capabilities + * element. These values are used to configure testbed device to allow the + * advertised hardware capabilities to be downgraded for testing purposes. + * + * @HE_FRAG_DISABLE: no support for dynamic fragmentation + * @HE_FRAG_LEVEL1: support for dynamic fragments that are + * contained within an MPDU or S-MPDU, no support for dynamic fragments + * within an A-MPDU that is not an S-MPDU. + * @HE_FRAG_LEVEL2: support for dynamic fragments that are + * contained within an MPDU or S-MPDU and support for up to one dynamic + * fragment for each MSDU, each A-MSDU if supported by the recipient, and + * each MMPDU within an A-MPDU or multi-TID A-MPDU that is not an + * MPDU or S-MPDU. + * @HE_FRAG_LEVEL3: support for dynamic fragments that are + * contained within an MPDU or S-MPDU and support for multiple dynamic + * fragments for each MSDU and for each A-MSDU if supported by the + * recipient within an A-MPDU or multi-TID AMPDU and up to one dynamic + * fragment for each MMPDU in a multi-TID A-MPDU that is not an S-MPDU. + */ +enum he_fragmentation_val { + HE_FRAG_DISABLE, + HE_FRAG_LEVEL1, + HE_FRAG_LEVEL2, + HE_FRAG_LEVEL3, +}; + +/** + * enum he_mcs_config - HE MCS support configuration + * + * Configures the HE Tx/Rx MCS map in HE capability IE for given bandwidth. + * These values are used in driver to configure the HE MCS map to advertise + * Tx/Rx MCS map in HE capability and these values are applied for all the + * streams supported by the device. To configure MCS for different bandwidths, + * vendor command needs to be sent using this attribute with appropriate value. + * For example, to configure HE_80_MCS_0_7, send vendor command using HE MCS + * attribute with HE_80_MCS0_7. And to configure HE MCS for HE_160_MCS0_11 + * send this command using HE MCS config attribute with value HE_160_MCS0_11. + * These values are used to configure testbed device to allow the advertised + * hardware capabilities to be downgraded for testing purposes. The enum values + * are defined such that BIT[1:0] indicates the MCS map value. Values 3,7 and + * 11 are not used as BIT[1:0] value is 3 which is used to disable MCS map. + * These values are validated in the driver before setting the MCS map and + * driver returns error if the input is other than these enum values. + * + * @HE_80_MCS0_7: support for HE 80/40/20 MHz MCS 0 to 7 + * @HE_80_MCS0_9: support for HE 80/40/20 MHz MCS 0 to 9 + * @HE_80_MCS0_11: support for HE 80/40/20 MHz MCS 0 to 11 + * @HE_160_MCS0_7: support for HE 160 MHz MCS 0 to 7 + * @HE_160_MCS0_9: support for HE 160 MHz MCS 0 to 9 + * @HE_160_MCS0_11: support for HE 160 MHz MCS 0 to 11 + * @HE_80P80_MCS0_7: support for HE 80p80 MHz MCS 0 to 7 + * @HE_80P80_MCS0_9: support for HE 80p80 MHz MCS 0 to 9 + * @HE_80P80_MCS0_11: support for HE 80p80 MHz MCS 0 to 11 + */ +enum he_mcs_config { + HE_80_MCS0_7 = 0, + HE_80_MCS0_9 = 1, + HE_80_MCS0_11 = 2, + HE_160_MCS0_7 = 4, + HE_160_MCS0_9 = 5, + HE_160_MCS0_11 = 6, + HE_80P80_MCS0_7 = 8, + HE_80P80_MCS0_9 = 9, + HE_80P80_MCS0_11 = 10, +}; + +/** + * enum qca_wlan_ba_session_config - BA session configuration + * + * Indicates the configuration values for BA session configuration attribute. + * + * @QCA_WLAN_ADD_BA: Establish a new BA session with given configuration. + * @QCA_WLAN_DELETE_BA: Delete the existing BA session for given TID. + */ +enum qca_wlan_ba_session_config { + QCA_WLAN_ADD_BA = 1, + QCA_WLAN_DELETE_BA = 2, +}; + +/** + * enum qca_wlan_ac_type - Access category type + * + * Indicates the access category type value. + * + * @QCA_WLAN_AC_BE: BE access category + * @QCA_WLAN_AC_BK: BK access category + * @QCA_WLAN_AC_VI: VI access category + * @QCA_WLAN_AC_VO: VO access category + * @QCA_WLAN_AC_ALL: All ACs + */ +enum qca_wlan_ac_type { + QCA_WLAN_AC_BE = 0, + QCA_WLAN_AC_BK = 1, + QCA_WLAN_AC_VI = 2, + QCA_WLAN_AC_VO = 3, + QCA_WLAN_AC_ALL = 4, +}; + +/** + * enum qca_wlan_he_ltf_cfg - HE LTF configuration + * + * Indicates the HE LTF configuration value. + * + * @QCA_WLAN_HE_LTF_AUTO: HE-LTF is automatically set to the mandatory HE-LTF, + * based on the GI setting + * @QCA_WLAN_HE_LTF_1X: 1X HE LTF is 3.2us LTF + * @QCA_WLAN_HE_LTF_2X: 2X HE LTF is 6.4us LTF + * @QCA_WLAN_HE_LTF_4X: 4X HE LTF is 12.8us LTF + */ +enum qca_wlan_he_ltf_cfg { + QCA_WLAN_HE_LTF_AUTO = 0, + QCA_WLAN_HE_LTF_1X = 1, + QCA_WLAN_HE_LTF_2X = 2, + QCA_WLAN_HE_LTF_4X = 3, +}; + +/** + * enum qca_wlan_he_mac_padding_dur - HE trigger frame MAC padding duration + * + * Indicates the HE trigger frame MAC padding duration value. + * + * @QCA_WLAN_HE_NO_ADDITIONAL_PROCESS_TIME: no additional time required to + * process the trigger frame. + * @QCA_WLAN_HE_8US_OF_PROCESS_TIME: indicates the 8us of processing time for + * trigger frame. + * @QCA_WLAN_HE_16US_OF_PROCESS_TIME: indicates the 16us of processing time for + * trigger frame. + */ +enum qca_wlan_he_mac_padding_dur { + QCA_WLAN_HE_NO_ADDITIONAL_PROCESS_TIME = 0, + QCA_WLAN_HE_8US_OF_PROCESS_TIME = 1, + QCA_WLAN_HE_16US_OF_PROCESS_TIME = 2, +}; + +/** + * enum qca_wlan_he_om_ctrl_ch_bw - HE OM control field BW configuration + * + * Indicates the HE Operating mode control channel width setting value. + * + * @QCA_WLAN_HE_OM_CTRL_BW_20M: Primary 20 MHz + * @QCA_WLAN_HE_OM_CTRL_BW_40M: Primary 40 MHz + * @QCA_WLAN_HE_OM_CTRL_BW_80M: Primary 80 MHz + * @QCA_WLAN_HE_OM_CTRL_BW_160M: 160 MHz and 80+80 MHz + */ +enum qca_wlan_he_om_ctrl_ch_bw { + QCA_WLAN_HE_OM_CTRL_BW_20M = 0, + QCA_WLAN_HE_OM_CTRL_BW_40M = 1, + QCA_WLAN_HE_OM_CTRL_BW_80M = 2, + QCA_WLAN_HE_OM_CTRL_BW_160M = 3, +}; + +/** + * enum qca_wlan_vendor_attr_he_omi_tx: Represents attributes for + * HE operating mode control transmit request. These attributes are + * sent as part of QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OMI_TX and + * QCA_NL80211_VENDOR_SUBCMD_WIFI_TEST_CONFIGURATION. + * + * @QCA_WLAN_VENDOR_ATTR_HE_OMI_RX_NSS: Mandatory 8-bit unsigned value + * indicates the maximum number of spatial streams, NSS, that the STA + * supports in reception for PPDU bandwidths less than or equal to 80 MHz + * and is set to NSS - 1. + * + * @QCA_WLAN_VENDOR_ATTR_HE_OMI_CH_BW: Mandatory 8-bit unsigned value + * indicates the operating channel width supported by the STA for both + * reception and transmission. Uses enum qca_wlan_he_om_ctrl_ch_bw values. + * + * @QCA_WLAN_VENDOR_ATTR_HE_OMI_ULMU_DISABLE: Mandatory 8-bit unsigned value + * indicates the all trigger based UL MU operations by the STA. + * 0 - UL MU operations are enabled by the STA. + * 1 - All triggered UL MU transmissions are suspended by the STA. + * + * @QCA_WLAN_VENDOR_ATTR_HE_OMI_TX_NSTS: Mandatory 8-bit unsigned value + * indicates the maximum number of space-time streams, NSTS, that + * the STA supports in transmission and is set to NSTS - 1. + * + * @QCA_WLAN_VENDOR_ATTR_HE_OMI_ULMU_DATA_DISABLE: 8-bit unsigned value + * combined with the UL MU Disable subfield and the recipient's setting + * of the OM Control UL MU Data Disable RX Support subfield in the HE MAC + * capabilities to determine which HE TB PPDUs are possible by the + * STA to transmit. + * 0 - UL MU data operations are enabled by the STA. + * 1 - Determine which HE TB PPDU types are allowed by the STA if UL MU disable + * bit is not set, else UL MU Tx is suspended. + * + */ +enum qca_wlan_vendor_attr_he_omi_tx { + QCA_WLAN_VENDOR_ATTR_HE_OMI_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_HE_OMI_RX_NSS = 1, + QCA_WLAN_VENDOR_ATTR_HE_OMI_CH_BW = 2, + QCA_WLAN_VENDOR_ATTR_HE_OMI_ULMU_DISABLE = 3, + QCA_WLAN_VENDOR_ATTR_HE_OMI_TX_NSTS = 4, + QCA_WLAN_VENDOR_ATTR_HE_OMI_ULMU_DATA_DISABLE = 5, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_HE_OMI_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_HE_OMI_MAX = + QCA_WLAN_VENDOR_ATTR_HE_OMI_AFTER_LAST - 1, +}; + +/* Attributes for data used by + * QCA_NL80211_VENDOR_SUBCMD_WIFI_TEST_CONFIGURATION + */ +enum qca_wlan_vendor_attr_wifi_test_config { + QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_INVALID = 0, + /* 8-bit unsigned value to configure the driver to enable/disable + * WMM feature. This attribute is used to configure testbed device. + * 1-enable, 0-disable + */ + QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WMM_ENABLE = 1, + + /* 8-bit unsigned value to configure the driver to accept/reject + * the addba request from peer. This attribute is used to configure + * the testbed device. + * 1-accept addba, 0-reject addba + */ + QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ACCEPT_ADDBA_REQ = 2, + + /* 8-bit unsigned value to configure the driver to send or not to + * send the addba request to peer. + * This attribute is used to configure the testbed device. + * 1-send addba, 0-do not send addba + */ + QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_SEND_ADDBA_REQ = 3, + + /* 8-bit unsigned value to indicate the HE fragmentation support. + * Uses enum he_fragmentation_val values. + * This attribute is used to configure the testbed device to + * allow the advertised hardware capabilities to be downgraded + * for testing purposes. + */ + QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_FRAGMENTATION = 4, + + /* 8-bit unsigned value to indicate the HE MCS support. + * Uses enum he_mcs_config values. + * This attribute is used to configure the testbed device to + * allow the advertised hardware capabilities to be downgraded + * for testing purposes. + */ + QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MCS = 5, + + /* 8-bit unsigned value to configure the driver to allow or not to + * allow the connection with WEP/TKIP in HT/VHT/HE modes. + * This attribute is used to configure the testbed device. + * 1-allow WEP/TKIP in HT/VHT/HE, 0-do not allow WEP/TKIP. + */ + QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WEP_TKIP_IN_HE = 6, + + /* 8-bit unsigned value to configure the driver to add a + * new BA session or delete the existing BA session for + * given TID. ADDBA command uses the buffer size and TID + * configuration if user specifies the values else default + * value for buffer size is used for all TIDs if the TID + * also not specified. For DEL_BA command TID value is + * required to process the command. + * Uses enum qca_wlan_ba_session_config values. + * This attribute is used to configure the testbed device. + */ + QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADD_DEL_BA_SESSION = 7, + + /* 16-bit unsigned value to configure the buffer size in addba + * request and response frames. + * This attribute is used to configure the testbed device. + * The range of the value is 0 to 256. + */ + QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADDBA_BUFF_SIZE = 8, + + /* 8-bit unsigned value to configure the buffer size in addba + * request and response frames. + * This attribute is used to configure the testbed device. + */ + QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BA_TID = 9, + + /* 8-bit unsigned value to configure the no ack policy. + * To configure no ack policy, access category value is + * required to process the command. + * This attribute is used to configure the testbed device. + * 1 - enable no ack, 0 - disable no ack. + */ + QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_NO_ACK = 10, + + /* 8-bit unsigned value to configure the AC for no ack policy + * This attribute is used to configure the testbed device. + * Uses the enum qca_wlan_ac_type values. + */ + QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_NO_ACK_AC = 11, + + /* 8-bit unsigned value to configure the HE LTF + * This attribute is used to configure the testbed device. + * Uses the enum qca_wlan_he_ltf_cfg values. + */ + QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_LTF = 12, + + /* 8-bit unsigned value to configure the tx beamformee. + * This attribute is used to configure the testbed device. + * 1-enable, 0-disable. + */ + QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_TX_BEAMFORMEE = 13, + + /* 8-bit unsigned value to configure the tx beamformee number + * of space-time streams. + * This attribute is used to configure the testbed device. + * The range of the value is 0 to 8. + */ + QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TX_BEAMFORMEE_NSTS = 14, + + /* 8-bit unsigned value to configure the MU EDCA params for given AC + * This attribute is used to configure the testbed device. + * Uses the enum qca_wlan_ac_type values. + */ + QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MU_EDCA_AC = 15, + + /* 8-bit unsigned value to configure the MU EDCA AIFSN for given AC + * To configure MU EDCA AIFSN value, MU EDCA access category value + * is required to process the command. + * This attribute is used to configure the testbed device. + */ + QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MU_EDCA_AIFSN = 16, + + /* 8-bit unsigned value to configure the MU EDCA ECW min value for + * given AC. + * To configure MU EDCA ECW min value, MU EDCA access category value + * is required to process the command. + * This attribute is used to configure the testbed device. + */ + QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MU_EDCA_ECWMIN = 17, + + /* 8-bit unsigned value to configure the MU EDCA ECW max value for + * given AC. + * To configure MU EDCA ECW max value, MU EDCA access category value + * is required to process the command. + * This attribute is used to configure the testbed device. + */ + QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MU_EDCA_ECWMAX = 18, + + /* 8-bit unsigned value to configure the MU EDCA timer for given AC + * To configure MU EDCA timer value, MU EDCA access category value + * is required to process the command. + * This attribute is used to configure the testbed device. + */ + QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MU_EDCA_TIMER = 19, + + /* 8-bit unsigned value to configure the HE trigger frame MAC padding + * duration. + * This attribute is used to configure the testbed device. + * Uses the enum qca_wlan_he_mac_padding_dur values. + */ + QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MAC_PADDING_DUR = 20, + + /* 8-bit unsigned value to override the MU EDCA params to defaults + * regardless of the AP beacon MU EDCA params. If it is enabled use + * the default values else use the MU EDCA params from AP beacon. + * This attribute is used to configure the testbed device. + * 1-enable, 0-disable. + */ + QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_OVERRIDE_MU_EDCA = 21, + + /* 8-bit unsigned value to configure the support for receiving + * an MPDU that contains an operating mode control subfield. + * This attribute is used to configure the testbed device. + * 1-enable, 0-disable. + */ + QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OM_CTRL_SUPP = 22, + + /* Nested attribute values required to setup the TWT session. + * enum qca_wlan_vendor_attr_twt_setup provides the necessary + * information to set up the session. It contains broadcast flags, + * set_up flags, trigger value, flow type, flow ID, wake interval + * exponent, protection, target wake time, wake duration, wake interval + * mantissa. These nested attributes are used to setup a host triggered + * TWT session. + */ + QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_SETUP = 23, + + /* This nested attribute is used to terminate the current TWT session. + * It does not currently carry any attributes. + */ + QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_TERMINATE = 24, + + /* This nested attribute is used to suspend the current TWT session. + * It does not currently carry any attributes. + */ + QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_SUSPEND = 25, + + /* Nested attribute values to indicate the request for resume. + * This attribute is used to resume the TWT session. + * enum qca_wlan_vendor_attr_twt_resume provides the necessary + * parameters required to resume the TWT session. + */ + QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_RESUME = 26, + + /* 8-bit unsigned value to set the HE operating mode control + * (OM CTRL) Channel Width subfield. + * The Channel Width subfield indicates the operating channel width + * supported by the STA for both reception and transmission. + * Uses the enum qca_wlan_he_om_ctrl_ch_bw values. + * This setting is cleared with the + * QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_CLEAR_HE_OM_CTRL_CONFIG + * flag attribute to reset defaults. + * This attribute is used to configure the testbed device. + */ + QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OM_CTRL_BW = 27, + + /* 8-bit unsigned value to configure the number of spatial + * streams in HE operating mode control field. + * This setting is cleared with the + * QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_CLEAR_HE_OM_CTRL_CONFIG + * flag attribute to reset defaults. + * This attribute is used to configure the testbed device. + */ + QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OM_CTRL_NSS = 28, + + /* Flag attribute to configure the UL MU disable bit in + * HE operating mode control field. + * This setting is cleared with the + * QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_CLEAR_HE_OM_CTRL_CONFIG + * flag attribute to reset defaults. + * This attribute is used to configure the testbed device. + */ + QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OM_CTRL_UL_MU_DISABLE = 29, + + /* Flag attribute to clear the previously set HE operating mode + * control field configuration. + * This attribute is used to configure the testbed device to reset + * defaults to clear any previously set HE operating mode control + * field configuration. + */ + QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_CLEAR_HE_OM_CTRL_CONFIG = 30, + + /* 8-bit unsigned value to configure HE single user PPDU + * transmission. By default this setting is disabled and it + * is disabled in the reset defaults of the device configuration. + * This attribute is used to configure the testbed device. + * 1-enable, 0-disable + */ + QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TX_SUPPDU = 31, + + /* 8-bit unsigned value to configure action frame transmission + * in HE trigger based PPDU transmission. + * By default this setting is disabled and it is disabled in + * the reset defaults of the device configuration. + * This attribute is used to configure the testbed device. + * 1-enable, 0-disable + */ + QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_ACTION_TX_TB_PPDU = 32, + + /* Nested attribute to indicate HE operating mode control field + * transmission. It contains operating mode control field Nss, + * channel bandwidth, Tx Nsts and UL MU disable attributes. + * These nested attributes are used to send HE operating mode control + * with configured values. + * Uses the enum qca_wlan_vendor_attr_he_omi_tx attributes. + * This attribute is used to configure the testbed device. + */ + QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OMI_TX = 33, + + /* 8-bit unsigned value to configure +HTC_HE support to indicate the + * support for the reception of a frame that carries an HE variant + * HT Control field. + * This attribute is used to configure the testbed device. + * 1-enable, 0-disable + */ + QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_HTC_HE_SUPP = 34, + + /* 8-bit unsigned value to configure VHT support in 2.4G band. + * This attribute is used to configure the testbed device. + * 1-enable, 0-disable + */ + QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_2G_VHT = 35, + + /* 8-bit unsigned value to configure HE testbed defaults. + * This attribute is used to configure the testbed device. + * 1-set the device HE capabilities to testbed defaults. + * 0-reset the device HE capabilities to supported config. + */ + QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_SET_HE_TESTBED_DEFAULTS = 36, + + /* 8-bit unsigned value to configure TWT request support. + * This attribute is used to configure the testbed device. + * 1-enable, 0-disable. + */ + QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TWT_REQ_SUPPORT = 37, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX = + QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_AFTER_LAST - 1, +}; + +/** + * enum qca_wlan_vendor_attr_bss_filter - Used by the vendor command + * QCA_NL80211_VENDOR_SUBCMD_BSS_FILTER. + * The user can add/delete the filter by specifying the BSSID/STA MAC address in + * QCA_WLAN_VENDOR_ATTR_BSS_FILTER_MAC_ADDR, filter type in + * QCA_WLAN_VENDOR_ATTR_BSS_FILTER_TYPE, add/delete action in + * QCA_WLAN_VENDOR_ATTR_BSS_FILTER_ACTION in the request. The user can get the + * statistics of an unassociated station by specifying the MAC address in + * QCA_WLAN_VENDOR_ATTR_BSS_FILTER_MAC_ADDR, station type in + * QCA_WLAN_VENDOR_ATTR_BSS_FILTER_TYPE, GET action in + * QCA_WLAN_VENDOR_ATTR_BSS_FILTER_ACTION in the request. The user also can get + * the statistics of all unassociated stations by specifying the Broadcast MAC + * address (ff:ff:ff:ff:ff:ff) in QCA_WLAN_VENDOR_ATTR_BSS_FILTER_MAC_ADDR with + * above procedure. In the response, driver shall specify statistics + * information nested in QCA_WLAN_VENDOR_ATTR_BSS_FILTER_STA_STATS. + */ +enum qca_wlan_vendor_attr_bss_filter { + QCA_WLAN_VENDOR_ATTR_BSS_FILTER_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_BSS_FILTER_MAC_ADDR = 1, + /* Other BSS filter type, unsigned 8 bit value. One of the values + * in enum qca_wlan_vendor_bss_filter_type. + */ + QCA_WLAN_VENDOR_ATTR_BSS_FILTER_TYPE = 2, + /* Other BSS filter action, unsigned 8 bit value. One of the values + * in enum qca_wlan_vendor_bss_filter_action. + */ + QCA_WLAN_VENDOR_ATTR_BSS_FILTER_ACTION = 3, + /* Array of nested attributes where each entry is the statistics + * information of the specified station that belong to another BSS. + * Attributes for each entry are taken from enum + * qca_wlan_vendor_bss_filter_sta_stats. + * Other BSS station configured in + * QCA_NL80211_VENDOR_SUBCMD_BSS_FILTER with filter type + * QCA_WLAN_VENDOR_BSS_FILTER_TYPE_STA. + * Statistics returned by QCA_NL80211_VENDOR_SUBCMD_BSS_FILTER + * with filter action QCA_WLAN_VENDOR_BSS_FILTER_ACTION_GET. + */ + QCA_WLAN_VENDOR_ATTR_BSS_FILTER_STA_STATS = 4, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_BSS_FILTER_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_BSS_FILTER_MAX = + QCA_WLAN_VENDOR_ATTR_BSS_FILTER_AFTER_LAST - 1, +}; + +/** + * enum qca_wlan_vendor_bss_filter_type - Type of + * filter used in other BSS filter operations. Used by the vendor command + * QCA_NL80211_VENDOR_SUBCMD_BSS_FILTER. + * + * @QCA_WLAN_VENDOR_BSS_FILTER_TYPE_BSSID: BSSID filter + * @QCA_WLAN_VENDOR_BSS_FILTER_TYPE_STA: Station MAC address filter + */ +enum qca_wlan_vendor_bss_filter_type { + QCA_WLAN_VENDOR_BSS_FILTER_TYPE_BSSID, + QCA_WLAN_VENDOR_BSS_FILTER_TYPE_STA, +}; + +/** + * enum qca_wlan_vendor_bss_filter_action - Type of + * action in other BSS filter operations. Used by the vendor command + * QCA_NL80211_VENDOR_SUBCMD_BSS_FILTER. + * + * @QCA_WLAN_VENDOR_BSS_FILTER_ACTION_ADD: Add filter + * @QCA_WLAN_VENDOR_BSS_FILTER_ACTION_DEL: Delete filter + * @QCA_WLAN_VENDOR_BSS_FILTER_ACTION_GET: Get the statistics + */ +enum qca_wlan_vendor_bss_filter_action { + QCA_WLAN_VENDOR_BSS_FILTER_ACTION_ADD, + QCA_WLAN_VENDOR_BSS_FILTER_ACTION_DEL, + QCA_WLAN_VENDOR_BSS_FILTER_ACTION_GET, +}; + +/** + * enum qca_wlan_vendor_bss_filter_sta_stats - Attributes for + * the statistics of a specific unassociated station belonging to another BSS. + * The statistics provides information of the unassociated station + * filtered by other BSS operation - such as MAC, signal value. + * Used by the vendor command QCA_NL80211_VENDOR_SUBCMD_BSS_FILTER. + * + * @QCA_WLAN_VENDOR_BSS_FILTER_STA_STATS_MAC: MAC address of the station. + * @QCA_WLAN_VENDOR_BSS_FILTER_STA_STATS_RSSI: Last received signal strength + * of the station. Unsigned 8 bit number containing RSSI. + * @QCA_WLAN_VENDOR_BSS_FILTER_STA_STATS_RSSI_TS: Time stamp of the host + * driver for the last received RSSI. Unsigned 64 bit number containing + * nanoseconds from the boottime. + */ +enum qca_wlan_vendor_bss_filter_sta_stats { + QCA_WLAN_VENDOR_BSS_FILTER_STA_STATS_INVALID = 0, + QCA_WLAN_VENDOR_BSS_FILTER_STA_STATS_MAC = 1, + QCA_WLAN_VENDOR_BSS_FILTER_STA_STATS_RSSI = 2, + QCA_WLAN_VENDOR_BSS_FILTER_STA_STATS_RSSI_TS = 3, + + /* keep last */ + QCA_WLAN_VENDOR_BSS_FILTER_STA_STATS_AFTER_LAST, + QCA_WLAN_VENDOR_BSS_FILTER_STA_STATS_MAX = + QCA_WLAN_VENDOR_BSS_FILTER_STA_STATS_AFTER_LAST - 1 +}; + +/* enum qca_wlan_nan_subcmd_type - Type of NAN command used by attribute + * QCA_WLAN_VENDOR_ATTR_NAN_SUBCMD_TYPE as a part of vendor command + * QCA_NL80211_VENDOR_SUBCMD_NAN_EXT. + */ +enum qca_wlan_nan_ext_subcmd_type { + /* Subcmd of type NAN Enable Request */ + QCA_WLAN_NAN_EXT_SUBCMD_TYPE_ENABLE_REQ = 1, + /* Subcmd of type NAN Disable Request */ + QCA_WLAN_NAN_EXT_SUBCMD_TYPE_DISABLE_REQ = 2, +}; + +/** + * enum qca_wlan_vendor_attr_nan_params - Used by the vendor command + * QCA_NL80211_VENDOR_SUBCMD_NAN_EXT. + */ +enum qca_wlan_vendor_attr_nan_params { + QCA_WLAN_VENDOR_ATTR_NAN_INVALID = 0, + /* Carries NAN command for firmware component. Every vendor command + * QCA_NL80211_VENDOR_SUBCMD_NAN_EXT must contain this attribute with a + * payload containing the NAN command. NLA_BINARY attribute. + */ + QCA_WLAN_VENDOR_ATTR_NAN_CMD_DATA = 1, + /* Indicates the type of NAN command sent with + * QCA_NL80211_VENDOR_SUBCMD_NAN_EXT. enum qca_wlan_nan_ext_subcmd_type + * describes the possible range of values. This attribute is mandatory + * if the command being issued is either + * QCA_WLAN_NAN_EXT_SUBCMD_TYPE_ENABLE_REQ or + * QCA_WLAN_NAN_EXT_SUBCMD_TYPE_DISABLE_REQ. NLA_U32 attribute. + */ + QCA_WLAN_VENDOR_ATTR_NAN_SUBCMD_TYPE = 2, + /* Frequency (in MHz) of primary NAN discovery social channel in 2.4 GHz + * band. This attribute is mandatory when command type is + * QCA_WLAN_NAN_EXT_SUBCMD_TYPE_ENABLE_REQ. NLA_U32 attribute. + */ + QCA_WLAN_VENDOR_ATTR_NAN_DISC_24GHZ_BAND_FREQ = 3, + /* Frequency (in MHz) of secondary NAN discovery social channel in 5 GHz + * band. This attribute is optional and should be included when command + * type is QCA_WLAN_NAN_EXT_SUBCMD_TYPE_ENABLE_REQ and NAN discovery + * has to be started on 5GHz along with 2.4GHz. NLA_U32 attribute. + */ + QCA_WLAN_VENDOR_ATTR_NAN_DISC_5GHZ_BAND_FREQ = 4, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_NAN_PARAMS_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_NAN_PARAMS_MAX = + QCA_WLAN_VENDOR_ATTR_NAN_PARAMS_AFTER_LAST - 1 +}; + +/** + * enum qca_wlan_vendor_attr_twt_setup: Represents attributes for + * TWT (Target Wake Time) setup request. These attributes are sent as part of + * %QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_SETUP and + * %QCA_NL80211_VENDOR_SUBCMD_WIFI_TEST_CONFIGURATION. + * + * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST: Flag attribute. + * Disable (flag attribute not present) - Individual TWT + * Enable (flag attribute present) - Broadcast TWT. + * Individual means the session is between the STA and the AP. + * This session is established using a separate negotiation between + * STA and AP. + * Broadcast means the session is across multiple STAs and an AP. The + * configuration parameters are announced in Beacon frames by the AP. + * + * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_REQ_TYPE: Required (u8). + * Unsigned 8-bit qca_wlan_vendor_twt_setup_req_type to + * specify the TWT request type + * + * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_TRIGGER: Flag attribute + * Enable (flag attribute present) - TWT with trigger support. + * Disable (flag attribute not present) - TWT without trigger support. + * Trigger means the AP will send the trigger frame to allow STA to send data. + * Without trigger, the STA will wait for the MU EDCA timer before + * transmitting the data. + * + * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_FLOW_TYPE: Required (u8) + * 0 - Announced TWT - In this mode, STA may skip few service periods to + * save more power. If STA wants to wake up, it will send a PS-POLL/QoS + * NULL frame to AP. + * 1 - Unannounced TWT - The STA will wakeup during every SP. + * + * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_FLOW_ID: Optional (u8) + * Flow ID is the unique identifier for each TWT session. + * Currently this is not required and dialog ID will be set to zero. + * + * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_EXP: Required (u8) + * This attribute (exp) is used along with the mantissa to derive the + * wake interval using the following formula: + * pow(2,exp) = wake_intvl_us/wake_intvl_mantis + * Wake interval is the interval between 2 successive SP. + * + * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_PROTECTION: Flag attribute + * Enable (flag attribute present) - Protection required. + * Disable (flag attribute not present) - Protection not required. + * If protection is enabled, then the AP will use protection + * mechanism using RTS/CTS to self to reserve the airtime. + * + * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_TIME: Optional (u32) + * This attribute is used as the SP offset which is the offset from + * TSF after which the wake happens. The units are in microseconds. If + * this attribute is not provided, then the value will be set to zero. + * + * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_DURATION: Required (u32) + * This is the duration of the service period. The units are in TU. + * + * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_MANTISSA: Required (u32) + * This attribute is used to configure wake interval mantissa. + * The units are in TU. + */ +enum qca_wlan_vendor_attr_twt_setup { + QCA_WLAN_VENDOR_ATTR_TWT_SETUP_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST = 1, + QCA_WLAN_VENDOR_ATTR_TWT_SETUP_REQ_TYPE = 2, + QCA_WLAN_VENDOR_ATTR_TWT_SETUP_TRIGGER = 3, + QCA_WLAN_VENDOR_ATTR_TWT_SETUP_FLOW_TYPE = 4, + QCA_WLAN_VENDOR_ATTR_TWT_SETUP_FLOW_ID = 5, + QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_EXP = 6, + QCA_WLAN_VENDOR_ATTR_TWT_SETUP_PROTECTION = 7, + QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_TIME = 8, + QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_DURATION = 9, + QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_MANTISSA = 10, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_TWT_SETUP_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX = + QCA_WLAN_VENDOR_ATTR_TWT_SETUP_AFTER_LAST - 1, +}; + +/** + * enum qca_wlan_vendor_attr_twt_resume: Represents attributes for + * TWT (Target Wake Time) resume request. These attributes are sent as part of + * %QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_RESUME and + * %QCA_NL80211_VENDOR_SUBCMD_WIFI_TEST_CONFIGURATION. + * + * @QCA_WLAN_VENDOR_ATTR_TWT_RESUME_NEXT_TWT: Optional (u8) + * This attribute is used as the SP offset which is the offset from + * TSF after which the wake happens. The units are in microseconds. + * If this attribute is not provided, then the value will be set to + * zero. + * + * @QCA_WLAN_VENDOR_ATTR_TWT_RESUME_NEXT_TWT_SIZE: Required (u32) + * This attribute represents the next TWT subfield size. + */ +enum qca_wlan_vendor_attr_twt_resume { + QCA_WLAN_VENDOR_ATTR_TWT_RESUME_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_TWT_RESUME_NEXT_TWT = 1, + QCA_WLAN_VENDOR_ATTR_TWT_RESUME_NEXT_TWT_SIZE = 2, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_TWT_RESUME_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_TWT_RESUME_MAX = + QCA_WLAN_VENDOR_ATTR_TWT_RESUME_AFTER_LAST - 1, +}; + +/** + * enum qca_wlan_vendor_twt_setup_req_type - Required (u8) + * Represents the setup type being requested for TWT. + * @QCA_WLAN_VENDOR_TWT_SETUP_REQUEST: STA is not specifying all the TWT + * parameters but relying on AP to fill the parameters during the negotiation. + * @QCA_WLAN_VENDOR_TWT_SETUP_SUGGEST: STA will provide all the suggested + * values which the AP may accept or AP may provide alternative parameters + * which the STA may accept. + * @QCA_WLAN_VENDOR_TWT_SETUP_DEMAND: STA is not willing to accept any + * alternate parameters than the requested ones. + */ +enum qca_wlan_vendor_twt_setup_req_type { + QCA_WLAN_VENDOR_TWT_SETUP_REQUEST = 1, + QCA_WLAN_VENDOR_TWT_SETUP_SUGGEST = 2, + QCA_WLAN_VENDOR_TWT_SETUP_DEMAND = 3, +}; + +/** + * enum qca_wlan_roam_scan_event_type - Type of roam scan event + * + * Indicates the type of roam scan event sent by firmware/driver. + * + * @QCA_WLAN_ROAM_SCAN_TRIGGER_EVENT: Roam scan trigger event type. + * @QCA_WLAN_ROAM_SCAN_STOP_EVENT: Roam scan stopped event type. + */ +enum qca_wlan_roam_scan_event_type { + QCA_WLAN_ROAM_SCAN_TRIGGER_EVENT = 0, + QCA_WLAN_ROAM_SCAN_STOP_EVENT = 1, +}; + +/** + * enum qca_wlan_roam_scan_trigger_reason - Roam scan trigger reason + * + * Indicates the reason for triggering roam scan by firmware/driver. + * + * @QCA_WLAN_ROAM_SCAN_TRIGGER_REASON_LOW_RSSI: Due to low RSSI of current AP. + * @QCA_WLAN_ROAM_SCAN_TRIGGER_REASON_HIGH_PER: Due to high packet error rate. + */ +enum qca_wlan_roam_scan_trigger_reason { + QCA_WLAN_ROAM_SCAN_TRIGGER_REASON_LOW_RSSI = 0, + QCA_WLAN_ROAM_SCAN_TRIGGER_REASON_HIGH_PER = 1, +}; + +/** + * enum qca_wlan_vendor_attr_roam_scan - Vendor subcmd attributes to report + * roam scan related details from driver/firmware to user space. enum values + * are used for NL attributes sent with + * %QCA_NL80211_VENDOR_SUBCMD_ROAM_SCAN_EVENT sub command. + */ +enum qca_wlan_vendor_attr_roam_scan { + QCA_WLAN_VENDOR_ATTR_ROAM_SCAN_INVALID = 0, + /* Encapsulates type of roam scan event being reported. enum + * qca_wlan_roam_scan_event_type describes the possible range of + * values. u32 attribute. + */ + QCA_WLAN_VENDOR_ATTR_ROAM_SCAN_EVENT_TYPE = 1, + /* Encapsulates reason for triggering roam scan. enum + * qca_wlan_roam_scan_trigger_reason describes the possible range of + * values. u32 attribute. + */ + QCA_WLAN_VENDOR_ATTR_ROAM_SCAN_TRIGGER_REASON = 2, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_ROAM_SCAN_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_ROAM_SCAN_MAX = + QCA_WLAN_VENDOR_ATTR_ROAM_SCAN_AFTER_LAST - 1, +}; + +/** + * enum qca_wlan_vendor_cfr_method - QCA vendor CFR methods used by + * attribute QCA_WLAN_VENDOR_ATTR_PEER_CFR_METHOD as part of vendor + * command QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG. + */ +enum qca_wlan_vendor_cfr_method { + /* CFR method using QOS Null frame */ + QCA_WLAN_VENDOR_CFR_METHOD_QOS_NULL = 0, +}; + +/** + * enum qca_wlan_vendor_peer_cfr_capture_attr - Used by the vendor command + * QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG to configure peer + * Channel Frequency Response capture parameters and enable periodic CFR + * capture. + */ +enum qca_wlan_vendor_peer_cfr_capture_attr { + QCA_WLAN_VENDOR_ATTR_PEER_CFR_CAPTURE_INVALID = 0, + /* 6-byte MAC address of the peer. + * This attribute is mandatory. + */ + QCA_WLAN_VENDOR_ATTR_CFR_PEER_MAC_ADDR = 1, + /* Enable peer CFR Capture, flag attribute. + * This attribute is mandatory to enable peer CFR capture. + * If this attribute is not present, peer CFR capture is disabled. + */ + QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE = 2, + /* BW of measurement, attribute uses the values in enum nl80211_chan_width + * Supported values: 20, 40, 80, 80+80, 160. + * Note that all targets may not support all bandwidths. + * u8 attribute. This attribute is mandatory if attribute + * QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE is used. + */ + QCA_WLAN_VENDOR_ATTR_PEER_CFR_BANDWIDTH = 3, + /* Periodicity of CFR measurement in msec. + * Periodicity should be a multiple of Base timer. + * Current Base timer value supported is 10 msecs (default). + * 0 for one shot capture. u32 attribute. + * This attribute is mandatory if attribute + * QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE is used. + */ + QCA_WLAN_VENDOR_ATTR_PEER_CFR_PERIODICITY = 4, + /* Method used to capture Channel Frequency Response. + * Attribute uses the values defined in enum qca_wlan_vendor_cfr_method. + * u8 attribute. This attribute is mandatory if attribute + * QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE is used. + */ + QCA_WLAN_VENDOR_ATTR_PEER_CFR_METHOD = 5, + /* Enable periodic CFR capture, flag attribute. + * This attribute is mandatory to enable Periodic CFR capture. + * If this attribute is not present, periodic CFR capture is disabled. + */ + QCA_WLAN_VENDOR_ATTR_PERIODIC_CFR_CAPTURE_ENABLE = 6, + + /* Keep last */ + QCA_WLAN_VENDOR_ATTR_PEER_CFR_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_PEER_CFR_MAX = + QCA_WLAN_VENDOR_ATTR_PEER_CFR_AFTER_LAST - 1, +}; + +/** + * enum qca_wlan_throughput_level - Current throughput level + * + * Indicates the current level of throughput calculated by the driver. The + * driver may choose different thresholds to decide whether the throughput level + * is low or medium or high based on variety of parameters like physical link + * capacity of the current connection, the number of packets being dispatched + * per second, etc. The throughput level events might not be consistent with the + * actual current throughput value being observed. + * + * @QCA_WLAN_THROUGHPUT_LEVEL_LOW: Low level of throughput + * @QCA_WLAN_THROUGHPUT_LEVEL_MEDIUM: Medium level of throughput + * @QCA_WLAN_THROUGHPUT_LEVEL_HIGH: High level of throughput + */ +enum qca_wlan_throughput_level { + QCA_WLAN_THROUGHPUT_LEVEL_LOW = 0, + QCA_WLAN_THROUGHPUT_LEVEL_MEDIUM = 1, + QCA_WLAN_THROUGHPUT_LEVEL_HIGH = 2, +}; + +/** + * enum qca_wlan_vendor_attr_throughput_change - Vendor subcmd attributes to + * report throughput changes from the driver to user space. enum values are used + * for netlink attributes sent with + * %QCA_NL80211_VENDOR_SUBCMD_THROUGHPUT_CHANGE_EVENT sub command. + */ +enum qca_wlan_vendor_attr_throughput_change { + QCA_WLAN_VENDOR_ATTR_THROUGHPUT_CHANGE_INVALID = 0, + /* Indicates the direction of throughput in which the change is being + * reported. u8 attribute. Value is 0 for TX and 1 for RX. + */ + QCA_WLAN_VENDOR_ATTR_THROUGHPUT_CHANGE_DIRECTION = 1, + /* Indicates the newly observed throughput level. enum + * qca_wlan_throughput_level describes the possible range of values. + * u8 attribute. + */ + QCA_WLAN_VENDOR_ATTR_THROUGHPUT_CHANGE_THROUGHPUT_LEVEL = 2, + /* Indicates the driver's guidance on the new value to be set to + * kernel's TCP parameter tcp_limit_output_bytes. u32 attribute. The + * driver may optionally include this attribute. + */ + QCA_WLAN_VENDOR_ATTR_THROUGHPUT_CHANGE_TCP_LIMIT_OUTPUT_BYTES = 3, + /* Indicates the driver's guidance on the new value to be set to + * kernel's TCP parameter tcp_adv_win_scale. s8 attribute. Possible + * values are from -31 to 31. The driver may optionally include this + * attribute. + */ + QCA_WLAN_VENDOR_ATTR_THROUGHPUT_CHANGE_TCP_ADV_WIN_SCALE = 4, + /* Indicates the driver's guidance on the new value to be set to + * kernel's TCP parameter tcp_delack_seg. u32 attribute. The driver may + * optionally include this attribute. + */ + QCA_WLAN_VENDOR_ATTR_THROUGHPUT_CHANGE_TCP_DELACK_SEG = 5, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_THROUGHPUT_CHANGE_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_THROUGHPUT_CHANGE_MAX = + QCA_WLAN_VENDOR_ATTR_THROUGHPUT_CHANGE_AFTER_LAST - 1, +}; + +/** + * enum qca_coex_config_profiles - This enum defines different types of + * traffic streams that can be prioritized one over the other during coex + * scenarios. + * The types defined in this enum are categorized in the below manner. + * 0 - 31 values corresponds to WLAN + * 32 - 63 values corresponds to BT + * 64 - 95 values corresponds to Zigbee + * @QCA_WIFI_STA_DISCOVERY: Prioritize discovery frames for WLAN STA + * @QCA_WIFI_STA_CONNECTION: Prioritize connection frames for WLAN STA + * @QCA_WIFI_STA_CLASS_3_MGMT: Prioritize class 3 mgmt frames for WLAN STA + * @QCA_WIFI_STA_DATA : Prioritize data frames for WLAN STA + * @QCA_WIFI_STA_ALL: Priritize all frames for WLAN STA + * @QCA_WIFI_SAP_DISCOVERY: Prioritize discovery frames for WLAN SAP + * @QCA_WIFI_SAP_CONNECTION: Prioritize connection frames for WLAN SAP + * @QCA_WIFI_SAP_CLASS_3_MGMT: Prioritize class 3 mgmt frames for WLAN SAP + * @QCA_WIFI_SAP_DATA: Prioritize data frames for WLAN SAP + * @QCA_WIFI_SAP_ALL: Prioritize all frames for WLAN SAP + * @QCA_BT_A2DP: Prioritize BT A2DP + * @QCA_BT_BLE: Prioritize BT BLE + * @QCA_BT_SCO: Prioritize BT SCO + * @QCA_ZB_LOW: Prioritize Zigbee Low + * @QCA_ZB_HIGH: Prioritize Zigbee High + */ +enum qca_coex_config_profiles { + /* 0 - 31 corresponds to WLAN */ + QCA_WIFI_STA_DISCOVERY = 0, + QCA_WIFI_STA_CONNECTION = 1, + QCA_WIFI_STA_CLASS_3_MGMT = 2, + QCA_WIFI_STA_DATA = 3, + QCA_WIFI_STA_ALL = 4, + QCA_WIFI_SAP_DISCOVERY = 5, + QCA_WIFI_SAP_CONNECTION = 6, + QCA_WIFI_SAP_CLASS_3_MGMT = 7, + QCA_WIFI_SAP_DATA = 8, + QCA_WIFI_SAP_ALL = 9, + QCA_WIFI_CASE_MAX = 31, + /* 32 - 63 corresponds to BT */ + QCA_BT_A2DP = 32, + QCA_BT_BLE = 33, + QCA_BT_SCO = 34, + QCA_BT_CASE_MAX = 63, + /* 64 - 95 corresponds to Zigbee */ + QCA_ZB_LOW = 64, + QCA_ZB_HIGH = 65, + QCA_ZB_CASE_MAX = 95, + /* 0xff is default value if the u8 profile value is not set. */ + QCA_COEX_CONFIG_PROFILE_DEFAULT_VALUE = 255 +}; + +/** + * enum qca_vendor_attr_coex_config_types - Coex configurations types. + * This enum defines the valid set of values of coex configuration types. These + * values may used by attribute + * %QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_CONFIG_TYPE. + * + * @QCA_WLAN_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_COEX_RESET: Reset all the + * weights to default values. + * @QCA_WLAN_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_COEX_START: Start to config + * weights with configurability value. + */ +enum qca_vendor_attr_coex_config_types { + QCA_WLAN_VENDOR_ATTR_COEX_CONFIG_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_COEX_RESET = 1, + QCA_WLAN_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_COEX_START = 2, +}; + +/** + * enum qca_vendor_attr_coex_config - Specifies vendor coex config attributes + * + * @QCA_VENDOR_ATTR_COEX_CONFIG_PROFILES: This attribute contains variable + * length array of 8-bit values from enum qca_coex_config_profiles. + * FW will prioritize the profiles in the order given in the array encapsulated + * in this attribute. + * For example: + * ----------------------------------------------------------------------- + * | 1 | 34 | 32 | 65 | + * ----------------------------------------------------------------------- + * If the attribute contains the values defined in above array then it means + * 1) Wifi STA connection has priority over BT_SCO, BT_A2DP and ZIGBEE HIGH. + * 2) BT_SCO has priority over BT_A2DP. + * 3) BT_A2DP has priority over ZIGBEE HIGH. + * Profiles which are not listed in this array shall not be preferred over the + * profiles which are listed in the array as a part of this attribute. + */ +enum qca_vendor_attr_coex_config { + QCA_VENDOR_ATTR_COEX_CONFIG_INVALID = 0, + QCA_VENDOR_ATTR_COEX_CONFIG_PROFILES = 1, + + /* Keep last */ + QCA_VENDOR_ATTR_COEX_CONFIG_AFTER_LAST, + QCA_VENDOR_ATTR_COEX_CONFIG_MAX = + QCA_VENDOR_ATTR_COEX_CONFIG_AFTER_LAST - 1, +}; + +/** + * enum qca_vendor_attr_coex_config_three_way - Specifies vendor coex config + * attributes + * Attributes for data used by QCA_NL80211_VENDOR_SUBCMD_COEX_CONFIG + * + * QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_CONFIG_TYPE: u32 attribute. + * Indicate config type. + * The config types are 32-bit values from qca_vendor_attr_coex_config_types + * + * @QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_PRIORITY_1: u32 attribute. + * Indicate the Priority 1 profiles. + * The profiles are 8-bit values from enum qca_coex_config_profiles. + * In same priority level, maximum to 4 profiles can be set here. + * @QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_PRIORITY_2: u32 attribute. + * Indicate the Priority 2 profiles. + * The profiles are 8-bit values from enum qca_coex_config_profiles. + * In same priority level, maximum to 4 profiles can be set here. + * @QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_PRIORITY_3: u32 attribute. + * Indicate the Priority 3 profiles. + * The profiles are 8-bit values from enum qca_coex_config_profiles. + * In same priority level, maximum to 4 profiles can be set here. + * @QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_PRIORITY_4: u32 attribute. + * Indicate the Priority 4 profiles. + * The profiles are 8-bit values from enum qca_coex_config_profiles. + * In same priority level, maximum to 4 profiles can be set here. + * NOTE: + * Limitations for QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_PRIORITY_x priority + * arrangement: + * 1: In the same u32 attribute (priority x), the profiles enum values own + * same priority level. + * 2: 0xff is default value if the u8 profile value is not set. + * 3: max to 4 rules/profiles in same priority level. + * 4: max to 4 priority level (priority 1 - priority 4) + * 5: one priority level only supports one scenario from WLAN/BT/ZB, + * hybrid rules not support. + * 6: if WMI_COEX_CONFIG_THREE_WAY_COEX_RESET called, priority x will + * remain blank to reset all parameters. + * For example: + * + * If the attributes as follow: + * priority 1: + * ------------------------------------ + * | 0xff | 0 | 1 | 2 | + * ------------------------------------ + * priority 2: + * ------------------------------------- + * | 0xff | 0xff | 0xff | 32 | + * ------------------------------------- + * priority 3: + * ------------------------------------- + * | 0xff | 0xff | 0xff | 65 | + * ------------------------------------- + * then it means: + * 1: WIFI_STA_DISCOVERY, WIFI_STA_CLASS_3_MGMT and WIFI_STA_CONNECTION + * owns same priority level. + * 2: WIFI_STA_DISCOVERY, WIFI_STA_CLASS_3_MGMT and WIFI_STA_CONNECTION + * has priority over BT_A2DP and ZB_HIGH. + * 3: BT_A2DP has priority over ZB_HIGH. + */ + +enum qca_vendor_attr_coex_config_three_way { + QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_INVALID = 0, + QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_CONFIG_TYPE = 1, + QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_PRIORITY_1 = 2, + QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_PRIORITY_2 = 3, + QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_PRIORITY_3 = 4, + QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_PRIORITY_4 = 5, + + /* Keep last */ + QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_AFTER_LAST, + QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_MAX = + QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_AFTER_LAST - 1, +}; + +/** + * enum qca_wlan_vendor_attr_link_properties - Represent the link properties. + * + * @QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_MAC_ADDR: MAC address of the peer + * (STA/AP) for the connected link. + * @QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_STA_FLAGS: Attribute containing a + * &struct nl80211_sta_flag_update for the respective connected link. MAC + * address of the peer represented by + * QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_MAC_ADDR. + */ +enum qca_wlan_vendor_attr_link_properties { + QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_INVALID = 0, + /* 1 - 3 are reserved */ + QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_MAC_ADDR = 4, + QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_STA_FLAGS = 5, + + /* Keep last */ + QCA_VENDOR_ATTR_LINK_PROPERTIES_AFTER_LAST, + QCA_VENDOR_ATTR_LINK_PROPERTIES_MAX = + QCA_VENDOR_ATTR_LINK_PROPERTIES_AFTER_LAST - 1, +}; + +/** + * enum qca_vendor_attr_peer_stats_cache_type - Represents peer stats cache type + * This enum defines the valid set of values of peer stats cache types. These + * values are used by attribute + * %QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_TYPE. + * + * @QCA_WLAN_VENDOR_ATTR_PEER_TX_RATE_STATS: Represents peer TX rate statistics + * @QCA_WLAN_VENDOR_ATTR_PEER_RX_RATE_STATS: Represents peer RX rate statistics + * @QCA_WLAN_VENDOR_ATTR_PEER_TX_SOJOURN_STATS: Represents peer TX sojourn + * statistics + */ +enum qca_vendor_attr_peer_stats_cache_type { + QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_TYPE_INVALID = 0, + + QCA_WLAN_VENDOR_ATTR_PEER_TX_RATE_STATS, + QCA_WLAN_VENDOR_ATTR_PEER_RX_RATE_STATS, + QCA_WLAN_VENDOR_ATTR_PEER_TX_SOJOURN_STATS, +}; + +/** + * enum qca_wlan_vendor_attr_peer_stats_cache_params - This enum defines + * attributes required for QCA_NL80211_VENDOR_SUBCMD_PEER_STATS_CACHE_FLUSH + * Information in these attributes is used to flush peer rate statistics from + * the driver to user application. + * + * @QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_TYPE: Unsigned 32-bit attribute + * Indicate peer statistics cache type. + * The statistics types are 32-bit values from + * enum qca_vendor_attr_peer_stats_cache_type. + * @QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_PEER_MAC: Unsigned 8-bit array + * of size 6 octets, representing the peer MAC address. + * @QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_DATA: Opaque data attribute + * containing buffer of statistics to send to application layer entity. + * @QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_PEER_COOKIE: Unsigned 64-bit attribute + * representing a cookie for peer unique session. + */ +enum qca_wlan_vendor_attr_peer_stats_cache_params { + QCA_WLAN_VENDOR_ATTR_PEER_STATS_INVALID = 0, + + QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_TYPE = 1, + QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_PEER_MAC = 2, + QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_DATA = 3, + QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_PEER_COOKIE = 4, + + /* Keep last */ + QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_LAST, + QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_MAX = + QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_LAST - 1 +}; + +/** + * enum qca_mpta_helper_attr_zigbee_state - Current Zigbee state + * This enum defines all the possible states of Zigbee, which can be + * delivered in the QCA_MPTA_HELPER_VENDOR_ATTR_ZIGBEE_STATE attribute. + * + * @ZIGBEE_IDLE: Zigbee in idle state + * @ZIGBEE_FORM_NETWORK: Zigbee forming network + * @ZIGBEE_WAIT_JOIN: Zigbee waiting for joining network + * @ZIGBEE_JOIN: Zigbee joining network + * @ZIGBEE_NETWORK_UP: Zigbee network is up + * @ZIGBEE_HMI: Zigbee in HMI mode + */ +enum qca_mpta_helper_attr_zigbee_state { + ZIGBEE_IDLE = 0, + ZIGBEE_FORM_NETWORK = 1, + ZIGBEE_WAIT_JOIN = 2, + ZIGBEE_JOIN = 3, + ZIGBEE_NETWORK_UP = 4, + ZIGBEE_HMI = 5, +}; + +/* + * enum qca_mpta_helper_vendor_attr - Attributes used in vendor sub-command + * QCA_NL80211_VENDOR_SUBCMD_MPTA_HELPER_CONFIG. + */ +enum qca_mpta_helper_vendor_attr { + QCA_MPTA_HELPER_VENDOR_ATTR_INVALID = 0, + /* Optional attribute used to update Zigbee state. + * enum qca_mpta_helper_attr_zigbee_state. + * NLA_U32 attribute. + */ + QCA_MPTA_HELPER_VENDOR_ATTR_ZIGBEE_STATE = 1, + /* Optional attribute used to configure WLAN duration for Shape-OCS + * during interrupt. + * Set in pair with QCA_MPTA_HELPER_VENDOR_ATTR_INT_NON_WLAN_DURATION. + * Value range 0 ~ 300 (ms). + * NLA_U32 attribute. + */ + QCA_MPTA_HELPER_VENDOR_ATTR_INT_WLAN_DURATION = 2, + /* Optional attribute used to configure non-WLAN duration for Shape-OCS + * during interrupt. + * Set in pair with QCA_MPTA_HELPER_VENDOR_ATTR_INT_WLAN_DURATION. + * Value range 0 ~ 300 (ms). + * NLA_U32 attribute. + */ + QCA_MPTA_HELPER_VENDOR_ATTR_INT_NON_WLAN_DURATION = 3, + /* Optional attribute used to configure WLAN duration for Shape-OCS + * monitor period. + * Set in pair with QCA_MPTA_HELPER_VENDOR_ATTR_MON_NON_WLAN_DURATION. + * Value range 0 ~ 300 (ms) + * NLA_U32 attribute + */ + QCA_MPTA_HELPER_VENDOR_ATTR_MON_WLAN_DURATION = 4, + /* Optional attribute used to configure non-WLAN duration for Shape-OCS + * monitor period. + * Set in pair with QCA_MPTA_HELPER_VENDOR_ATTR_MON_WLAN_DURATION. + * Value range 0 ~ 300 (ms) + * NLA_U32 attribute + */ + QCA_MPTA_HELPER_VENDOR_ATTR_MON_NON_WLAN_DURATION = 5, + /* Optional attribute used to configure OCS interrupt duration. + * Set in pair with QCA_MPTA_HELPER_VENDOR_ATTR_MON_OCS_DURATION. + * Value range 1000 ~ 20000 (ms) + * NLA_U32 attribute + */ + QCA_MPTA_HELPER_VENDOR_ATTR_INT_OCS_DURATION = 6, + /* Optional attribute used to configure OCS monitor duration. + * Set in pair with QCA_MPTA_HELPER_VENDOR_ATTR_INT_OCS_DURATION. + * Value range 1000 ~ 20000 (ms) + * NLA_U32 attribute + */ + QCA_MPTA_HELPER_VENDOR_ATTR_MON_OCS_DURATION = 7, + /* Optional attribute used to notify WLAN firmware the current Zigbee + * channel. + * Value range 11 ~ 26 + * NLA_U32 attribute + */ + QCA_MPTA_HELPER_VENDOR_ATTR_ZIGBEE_CHAN = 8, + /* Optional attribute used to configure WLAN mute duration. + * Value range 0 ~ 400 (ms) + * NLA_U32 attribute + */ + QCA_MPTA_HELPER_VENDOR_ATTR_WLAN_MUTE_DURATION = 9, + + /* keep last */ + QCA_MPTA_HELPER_VENDOR_ATTR_AFTER_LAST, + QCA_MPTA_HELPER_VENDOR_ATTR_MAX = + QCA_MPTA_HELPER_VENDOR_ATTR_AFTER_LAST - 1 +}; + #endif /* QCA_VENDOR_H */ diff --git a/freebsd/contrib/wpa/src/common/sae.h b/freebsd/contrib/wpa/src/common/sae.h index a4270bc2..3eb6e323 100644 --- a/freebsd/contrib/wpa/src/common/sae.h +++ b/freebsd/contrib/wpa/src/common/sae.h @@ -39,16 +39,24 @@ struct sae_temporary_data { struct crypto_bignum *prime_buf; struct crypto_bignum *order_buf; struct wpabuf *anti_clogging_token; + char *pw_id; + int vlan_id; + u8 bssid[ETH_ALEN]; +}; + +enum sae_state { + SAE_NOTHING, SAE_COMMITTED, SAE_CONFIRMED, SAE_ACCEPTED }; struct sae_data { - enum { SAE_NOTHING, SAE_COMMITTED, SAE_CONFIRMED, SAE_ACCEPTED } state; + enum sae_state state; u16 send_confirm; u8 pmk[SAE_PMK_LEN]; u8 pmkid[SAE_PMKID_LEN]; struct crypto_bignum *peer_commit_scalar; int group; - int sync; + unsigned int sync; /* protocol instance variable: Sync */ + u16 rc; /* protocol instance variable: Rc (received send-confirm) */ struct sae_temporary_data *tmp; }; @@ -58,14 +66,15 @@ void sae_clear_data(struct sae_data *sae); int sae_prepare_commit(const u8 *addr1, const u8 *addr2, const u8 *password, size_t password_len, - struct sae_data *sae); + const char *identifier, struct sae_data *sae); int sae_process_commit(struct sae_data *sae); void sae_write_commit(struct sae_data *sae, struct wpabuf *buf, - const struct wpabuf *token); + const struct wpabuf *token, const char *identifier); u16 sae_parse_commit(struct sae_data *sae, const u8 *data, size_t len, const u8 **token, size_t *token_len, int *allowed_groups); void sae_write_confirm(struct sae_data *sae, struct wpabuf *buf); int sae_check_confirm(struct sae_data *sae, const u8 *data, size_t len); u16 sae_group_allowed(struct sae_data *sae, int *allowed_groups, u16 group); +const char * sae_state_txt(enum sae_state state); #endif /* SAE_H */ diff --git a/freebsd/contrib/wpa/src/common/version.h b/freebsd/contrib/wpa/src/common/version.h index 75e5c6e0..06fc5e4d 100644 --- a/freebsd/contrib/wpa/src/common/version.h +++ b/freebsd/contrib/wpa/src/common/version.h @@ -9,6 +9,6 @@ #define GIT_VERSION_STR_POSTFIX "" #endif /* GIT_VERSION_STR_POSTFIX */ -#define VERSION_STR "2.6" VERSION_STR_POSTFIX GIT_VERSION_STR_POSTFIX +#define VERSION_STR "2.8" VERSION_STR_POSTFIX GIT_VERSION_STR_POSTFIX #endif /* VERSION_H */ diff --git a/freebsd/contrib/wpa/src/common/wpa_common.c b/freebsd/contrib/wpa/src/common/wpa_common.c index f1802c36..b2b58793 100644 --- a/freebsd/contrib/wpa/src/common/wpa_common.c +++ b/freebsd/contrib/wpa/src/common/wpa_common.c @@ -2,7 +2,7 @@ /* * WPA/RSN - Shared functions for supplicant and authenticator - * Copyright (c) 2002-2015, Jouni Malinen <j@w1.fi> + * Copyright (c) 2002-2018, Jouni Malinen <j@w1.fi> * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -15,6 +15,7 @@ #include "crypto/sha1.h" #include "crypto/sha256.h" #include "crypto/sha384.h" +#include "crypto/sha512.h" #include "crypto/aes_wrap.h" #include "crypto/crypto.h" #include "ieee802_11_defs.h" @@ -22,27 +23,151 @@ #include "wpa_common.h" -static unsigned int wpa_kck_len(int akmp) +static unsigned int wpa_kck_len(int akmp, size_t pmk_len) { - if (akmp == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) + switch (akmp) { + case WPA_KEY_MGMT_IEEE8021X_SUITE_B_192: + case WPA_KEY_MGMT_FT_IEEE8021X_SHA384: + return 24; + case WPA_KEY_MGMT_FILS_SHA256: + case WPA_KEY_MGMT_FT_FILS_SHA256: + case WPA_KEY_MGMT_FILS_SHA384: + case WPA_KEY_MGMT_FT_FILS_SHA384: + return 0; + case WPA_KEY_MGMT_DPP: + return pmk_len / 2; + case WPA_KEY_MGMT_OWE: + return pmk_len / 2; + default: + return 16; + } +} + + +#ifdef CONFIG_IEEE80211R +static unsigned int wpa_kck2_len(int akmp) +{ + switch (akmp) { + case WPA_KEY_MGMT_FT_FILS_SHA256: + return 16; + case WPA_KEY_MGMT_FT_FILS_SHA384: return 24; - return 16; + default: + return 0; + } +} +#endif /* CONFIG_IEEE80211R */ + + +static unsigned int wpa_kek_len(int akmp, size_t pmk_len) +{ + switch (akmp) { + case WPA_KEY_MGMT_FILS_SHA384: + case WPA_KEY_MGMT_FT_FILS_SHA384: + return 64; + case WPA_KEY_MGMT_IEEE8021X_SUITE_B_192: + case WPA_KEY_MGMT_FILS_SHA256: + case WPA_KEY_MGMT_FT_FILS_SHA256: + case WPA_KEY_MGMT_FT_IEEE8021X_SHA384: + return 32; + case WPA_KEY_MGMT_DPP: + return pmk_len <= 32 ? 16 : 32; + case WPA_KEY_MGMT_OWE: + return pmk_len <= 32 ? 16 : 32; + default: + return 16; + } } -static unsigned int wpa_kek_len(int akmp) +#ifdef CONFIG_IEEE80211R +static unsigned int wpa_kek2_len(int akmp) { - if (akmp == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) + switch (akmp) { + case WPA_KEY_MGMT_FT_FILS_SHA256: + return 16; + case WPA_KEY_MGMT_FT_FILS_SHA384: return 32; - return 16; + default: + return 0; + } } +#endif /* CONFIG_IEEE80211R */ -unsigned int wpa_mic_len(int akmp) +unsigned int wpa_mic_len(int akmp, size_t pmk_len) { - if (akmp == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) + switch (akmp) { + case WPA_KEY_MGMT_IEEE8021X_SUITE_B_192: + case WPA_KEY_MGMT_FT_IEEE8021X_SHA384: return 24; - return 16; + case WPA_KEY_MGMT_FILS_SHA256: + case WPA_KEY_MGMT_FILS_SHA384: + case WPA_KEY_MGMT_FT_FILS_SHA256: + case WPA_KEY_MGMT_FT_FILS_SHA384: + return 0; + case WPA_KEY_MGMT_DPP: + return pmk_len / 2; + case WPA_KEY_MGMT_OWE: + return pmk_len / 2; + default: + return 16; + } +} + + +/** + * wpa_use_akm_defined - Is AKM-defined Key Descriptor Version used + * @akmp: WPA_KEY_MGMT_* used in key derivation + * Returns: 1 if AKM-defined Key Descriptor Version is used; 0 otherwise + */ +int wpa_use_akm_defined(int akmp) +{ + return akmp == WPA_KEY_MGMT_OSEN || + akmp == WPA_KEY_MGMT_OWE || + akmp == WPA_KEY_MGMT_DPP || + akmp == WPA_KEY_MGMT_FT_IEEE8021X_SHA384 || + wpa_key_mgmt_sae(akmp) || + wpa_key_mgmt_suite_b(akmp) || + wpa_key_mgmt_fils(akmp); +} + + +/** + * wpa_use_cmac - Is CMAC integrity algorithm used for EAPOL-Key MIC + * @akmp: WPA_KEY_MGMT_* used in key derivation + * Returns: 1 if CMAC is used; 0 otherwise + */ +int wpa_use_cmac(int akmp) +{ + return akmp == WPA_KEY_MGMT_OSEN || + akmp == WPA_KEY_MGMT_OWE || + akmp == WPA_KEY_MGMT_DPP || + wpa_key_mgmt_ft(akmp) || + wpa_key_mgmt_sha256(akmp) || + wpa_key_mgmt_sae(akmp) || + wpa_key_mgmt_suite_b(akmp); +} + + +/** + * wpa_use_aes_key_wrap - Is AES Keywrap algorithm used for EAPOL-Key Key Data + * @akmp: WPA_KEY_MGMT_* used in key derivation + * Returns: 1 if AES Keywrap is used; 0 otherwise + * + * Note: AKM 00-0F-AC:1 and 00-0F-AC:2 have special rules for selecting whether + * to use AES Keywrap based on the negotiated pairwise cipher. This function + * does not cover those special cases. + */ +int wpa_use_aes_key_wrap(int akmp) +{ + return akmp == WPA_KEY_MGMT_OSEN || + akmp == WPA_KEY_MGMT_OWE || + akmp == WPA_KEY_MGMT_DPP || + wpa_key_mgmt_ft(akmp) || + wpa_key_mgmt_sha256(akmp) || + wpa_key_mgmt_sae(akmp) || + wpa_key_mgmt_suite_b(akmp); } @@ -69,30 +194,50 @@ unsigned int wpa_mic_len(int akmp) int wpa_eapol_key_mic(const u8 *key, size_t key_len, int akmp, int ver, const u8 *buf, size_t len, u8 *mic) { - u8 hash[SHA384_MAC_LEN]; + u8 hash[SHA512_MAC_LEN]; + + if (key_len == 0) { + wpa_printf(MSG_DEBUG, + "WPA: KCK not set - cannot calculate MIC"); + return -1; + } switch (ver) { #ifndef CONFIG_FIPS case WPA_KEY_INFO_TYPE_HMAC_MD5_RC4: + wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key MIC using HMAC-MD5"); return hmac_md5(key, key_len, buf, len, mic); #endif /* CONFIG_FIPS */ case WPA_KEY_INFO_TYPE_HMAC_SHA1_AES: + wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key MIC using HMAC-SHA1"); if (hmac_sha1(key, key_len, buf, len, hash)) return -1; os_memcpy(mic, hash, MD5_MAC_LEN); break; #if defined(CONFIG_IEEE80211R) || defined(CONFIG_IEEE80211W) case WPA_KEY_INFO_TYPE_AES_128_CMAC: + wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key MIC using AES-CMAC"); return omac1_aes_128(key, buf, len, mic); #endif /* CONFIG_IEEE80211R || CONFIG_IEEE80211W */ case WPA_KEY_INFO_TYPE_AKM_DEFINED: switch (akmp) { +#ifdef CONFIG_SAE + case WPA_KEY_MGMT_SAE: + case WPA_KEY_MGMT_FT_SAE: + wpa_printf(MSG_DEBUG, + "WPA: EAPOL-Key MIC using AES-CMAC (AKM-defined - SAE)"); + return omac1_aes_128(key, buf, len, mic); +#endif /* CONFIG_SAE */ #ifdef CONFIG_HS20 case WPA_KEY_MGMT_OSEN: + wpa_printf(MSG_DEBUG, + "WPA: EAPOL-Key MIC using AES-CMAC (AKM-defined - OSEN)"); return omac1_aes_128(key, buf, len, mic); #endif /* CONFIG_HS20 */ #ifdef CONFIG_SUITEB case WPA_KEY_MGMT_IEEE8021X_SUITE_B: + wpa_printf(MSG_DEBUG, + "WPA: EAPOL-Key MIC using HMAC-SHA256 (AKM-defined - Suite B)"); if (hmac_sha256(key, key_len, buf, len, hash)) return -1; os_memcpy(mic, hash, MD5_MAC_LEN); @@ -100,16 +245,79 @@ int wpa_eapol_key_mic(const u8 *key, size_t key_len, int akmp, int ver, #endif /* CONFIG_SUITEB */ #ifdef CONFIG_SUITEB192 case WPA_KEY_MGMT_IEEE8021X_SUITE_B_192: + wpa_printf(MSG_DEBUG, + "WPA: EAPOL-Key MIC using HMAC-SHA384 (AKM-defined - Suite B 192-bit)"); if (hmac_sha384(key, key_len, buf, len, hash)) return -1; os_memcpy(mic, hash, 24); break; #endif /* CONFIG_SUITEB192 */ +#ifdef CONFIG_OWE + case WPA_KEY_MGMT_OWE: + wpa_printf(MSG_DEBUG, + "WPA: EAPOL-Key MIC using HMAC-SHA%u (AKM-defined - OWE)", + (unsigned int) key_len * 8 * 2); + if (key_len == 128 / 8) { + if (hmac_sha256(key, key_len, buf, len, hash)) + return -1; + } else if (key_len == 192 / 8) { + if (hmac_sha384(key, key_len, buf, len, hash)) + return -1; + } else if (key_len == 256 / 8) { + if (hmac_sha512(key, key_len, buf, len, hash)) + return -1; + } else { + wpa_printf(MSG_INFO, + "OWE: Unsupported KCK length: %u", + (unsigned int) key_len); + return -1; + } + os_memcpy(mic, hash, key_len); + break; +#endif /* CONFIG_OWE */ +#ifdef CONFIG_DPP + case WPA_KEY_MGMT_DPP: + wpa_printf(MSG_DEBUG, + "WPA: EAPOL-Key MIC using HMAC-SHA%u (AKM-defined - DPP)", + (unsigned int) key_len * 8 * 2); + if (key_len == 128 / 8) { + if (hmac_sha256(key, key_len, buf, len, hash)) + return -1; + } else if (key_len == 192 / 8) { + if (hmac_sha384(key, key_len, buf, len, hash)) + return -1; + } else if (key_len == 256 / 8) { + if (hmac_sha512(key, key_len, buf, len, hash)) + return -1; + } else { + wpa_printf(MSG_INFO, + "DPP: Unsupported KCK length: %u", + (unsigned int) key_len); + return -1; + } + os_memcpy(mic, hash, key_len); + break; +#endif /* CONFIG_DPP */ +#if defined(CONFIG_IEEE80211R) && defined(CONFIG_SHA384) + case WPA_KEY_MGMT_FT_IEEE8021X_SHA384: + wpa_printf(MSG_DEBUG, + "WPA: EAPOL-Key MIC using HMAC-SHA384 (AKM-defined - FT 802.1X SHA384)"); + if (hmac_sha384(key, key_len, buf, len, hash)) + return -1; + os_memcpy(mic, hash, 24); + break; +#endif /* CONFIG_IEEE80211R && CONFIG_SHA384 */ default: + wpa_printf(MSG_DEBUG, + "WPA: EAPOL-Key MIC algorithm not known (AKM-defined - akmp=0x%x)", + akmp); return -1; } break; default: + wpa_printf(MSG_DEBUG, + "WPA: EAPOL-Key MIC algorithm not known (ver=%d)", + ver); return -1; } @@ -134,21 +342,32 @@ int wpa_eapol_key_mic(const u8 *key, size_t key_len, int akmp, int ver, * IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy * PTK = PRF-X(PMK, "Pairwise key expansion", * Min(AA, SA) || Max(AA, SA) || - * Min(ANonce, SNonce) || Max(ANonce, SNonce)) + * Min(ANonce, SNonce) || Max(ANonce, SNonce) + * [ || Z.x ]) * - * STK = PRF-X(SMK, "Peer key expansion", - * Min(MAC_I, MAC_P) || Max(MAC_I, MAC_P) || - * Min(INonce, PNonce) || Max(INonce, PNonce)) + * The optional Z.x component is used only with DPP and that part is not defined + * in IEEE 802.11. */ int wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label, const u8 *addr1, const u8 *addr2, const u8 *nonce1, const u8 *nonce2, - struct wpa_ptk *ptk, int akmp, int cipher) + struct wpa_ptk *ptk, int akmp, int cipher, + const u8 *z, size_t z_len) { - u8 data[2 * ETH_ALEN + 2 * WPA_NONCE_LEN]; +#define MAX_Z_LEN 66 /* with NIST P-521 */ + u8 data[2 * ETH_ALEN + 2 * WPA_NONCE_LEN + MAX_Z_LEN]; + size_t data_len = 2 * ETH_ALEN + 2 * WPA_NONCE_LEN; u8 tmp[WPA_KCK_MAX_LEN + WPA_KEK_MAX_LEN + WPA_TK_MAX_LEN]; size_t ptk_len; + if (pmk_len == 0) { + wpa_printf(MSG_ERROR, "WPA: No PMK set for PTK derivation"); + return -1; + } + + if (z_len > MAX_Z_LEN) + return -1; + if (os_memcmp(addr1, addr2, ETH_ALEN) < 0) { os_memcpy(data, addr1, ETH_ALEN); os_memcpy(data + ETH_ALEN, addr2, ETH_ALEN); @@ -167,29 +386,74 @@ int wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label, WPA_NONCE_LEN); } - ptk->kck_len = wpa_kck_len(akmp); - ptk->kek_len = wpa_kek_len(akmp); + if (z && z_len) { + os_memcpy(data + 2 * ETH_ALEN + 2 * WPA_NONCE_LEN, z, z_len); + data_len += z_len; + } + + ptk->kck_len = wpa_kck_len(akmp, pmk_len); + ptk->kek_len = wpa_kek_len(akmp, pmk_len); ptk->tk_len = wpa_cipher_key_len(cipher); + if (ptk->tk_len == 0) { + wpa_printf(MSG_ERROR, + "WPA: Unsupported cipher (0x%x) used in PTK derivation", + cipher); + return -1; + } ptk_len = ptk->kck_len + ptk->kek_len + ptk->tk_len; -#ifdef CONFIG_SUITEB192 - if (wpa_key_mgmt_sha384(akmp)) - sha384_prf(pmk, pmk_len, label, data, sizeof(data), - tmp, ptk_len); - else -#endif /* CONFIG_SUITEB192 */ -#ifdef CONFIG_IEEE80211W - if (wpa_key_mgmt_sha256(akmp)) - sha256_prf(pmk, pmk_len, label, data, sizeof(data), - tmp, ptk_len); - else -#endif /* CONFIG_IEEE80211W */ - sha1_prf(pmk, pmk_len, label, data, sizeof(data), tmp, ptk_len); + if (wpa_key_mgmt_sha384(akmp)) { +#if defined(CONFIG_SUITEB192) || defined(CONFIG_FILS) + wpa_printf(MSG_DEBUG, "WPA: PTK derivation using PRF(SHA384)"); + if (sha384_prf(pmk, pmk_len, label, data, data_len, + tmp, ptk_len) < 0) + return -1; +#else /* CONFIG_SUITEB192 || CONFIG_FILS */ + return -1; +#endif /* CONFIG_SUITEB192 || CONFIG_FILS */ + } else if (wpa_key_mgmt_sha256(akmp) || akmp == WPA_KEY_MGMT_OWE) { +#if defined(CONFIG_IEEE80211W) || defined(CONFIG_SAE) || defined(CONFIG_FILS) + wpa_printf(MSG_DEBUG, "WPA: PTK derivation using PRF(SHA256)"); + if (sha256_prf(pmk, pmk_len, label, data, data_len, + tmp, ptk_len) < 0) + return -1; +#else /* CONFIG_IEEE80211W or CONFIG_SAE or CONFIG_FILS */ + return -1; +#endif /* CONFIG_IEEE80211W or CONFIG_SAE or CONFIG_FILS */ +#ifdef CONFIG_DPP + } else if (akmp == WPA_KEY_MGMT_DPP && pmk_len == 32) { + wpa_printf(MSG_DEBUG, "WPA: PTK derivation using PRF(SHA256)"); + if (sha256_prf(pmk, pmk_len, label, data, data_len, + tmp, ptk_len) < 0) + return -1; + } else if (akmp == WPA_KEY_MGMT_DPP && pmk_len == 48) { + wpa_printf(MSG_DEBUG, "WPA: PTK derivation using PRF(SHA384)"); + if (sha384_prf(pmk, pmk_len, label, data, data_len, + tmp, ptk_len) < 0) + return -1; + } else if (akmp == WPA_KEY_MGMT_DPP && pmk_len == 64) { + wpa_printf(MSG_DEBUG, "WPA: PTK derivation using PRF(SHA512)"); + if (sha512_prf(pmk, pmk_len, label, data, data_len, + tmp, ptk_len) < 0) + return -1; + } else if (akmp == WPA_KEY_MGMT_DPP) { + wpa_printf(MSG_INFO, "DPP: Unknown PMK length %u", + (unsigned int) pmk_len); + return -1; +#endif /* CONFIG_DPP */ + } else { + wpa_printf(MSG_DEBUG, "WPA: PTK derivation using PRF(SHA1)"); + if (sha1_prf(pmk, pmk_len, label, data, data_len, tmp, + ptk_len) < 0) + return -1; + } wpa_printf(MSG_DEBUG, "WPA: PTK derivation - A1=" MACSTR " A2=" MACSTR, MAC2STR(addr1), MAC2STR(addr2)); wpa_hexdump(MSG_DEBUG, "WPA: Nonce1", nonce1, WPA_NONCE_LEN); wpa_hexdump(MSG_DEBUG, "WPA: Nonce2", nonce2, WPA_NONCE_LEN); + if (z && z_len) + wpa_hexdump_key(MSG_DEBUG, "WPA: Z.x", z, z_len); wpa_hexdump_key(MSG_DEBUG, "WPA: PMK", pmk, pmk_len); wpa_hexdump_key(MSG_DEBUG, "WPA: PTK", tmp, ptk_len); @@ -202,11 +466,292 @@ int wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label, os_memcpy(ptk->tk, tmp + ptk->kck_len + ptk->kek_len, ptk->tk_len); wpa_hexdump_key(MSG_DEBUG, "WPA: TK", ptk->tk, ptk->tk_len); + ptk->kek2_len = 0; + ptk->kck2_len = 0; + os_memset(tmp, 0, sizeof(tmp)); + os_memset(data, 0, data_len); + return 0; +} + +#ifdef CONFIG_FILS + +int fils_rmsk_to_pmk(int akmp, const u8 *rmsk, size_t rmsk_len, + const u8 *snonce, const u8 *anonce, const u8 *dh_ss, + size_t dh_ss_len, u8 *pmk, size_t *pmk_len) +{ + u8 nonces[2 * FILS_NONCE_LEN]; + const u8 *addr[2]; + size_t len[2]; + size_t num_elem; + int res; + + /* PMK = HMAC-Hash(SNonce || ANonce, rMSK [ || DHss ]) */ + wpa_printf(MSG_DEBUG, "FILS: rMSK to PMK derivation"); + + if (wpa_key_mgmt_sha384(akmp)) + *pmk_len = SHA384_MAC_LEN; + else if (wpa_key_mgmt_sha256(akmp)) + *pmk_len = SHA256_MAC_LEN; + else + return -1; + + wpa_hexdump_key(MSG_DEBUG, "FILS: rMSK", rmsk, rmsk_len); + wpa_hexdump(MSG_DEBUG, "FILS: SNonce", snonce, FILS_NONCE_LEN); + wpa_hexdump(MSG_DEBUG, "FILS: ANonce", anonce, FILS_NONCE_LEN); + wpa_hexdump(MSG_DEBUG, "FILS: DHss", dh_ss, dh_ss_len); + + os_memcpy(nonces, snonce, FILS_NONCE_LEN); + os_memcpy(&nonces[FILS_NONCE_LEN], anonce, FILS_NONCE_LEN); + addr[0] = rmsk; + len[0] = rmsk_len; + num_elem = 1; + if (dh_ss) { + addr[1] = dh_ss; + len[1] = dh_ss_len; + num_elem++; + } + if (wpa_key_mgmt_sha384(akmp)) + res = hmac_sha384_vector(nonces, 2 * FILS_NONCE_LEN, num_elem, + addr, len, pmk); + else + res = hmac_sha256_vector(nonces, 2 * FILS_NONCE_LEN, num_elem, + addr, len, pmk); + if (res == 0) + wpa_hexdump_key(MSG_DEBUG, "FILS: PMK", pmk, *pmk_len); + else + *pmk_len = 0; + return res; +} + + +int fils_pmkid_erp(int akmp, const u8 *reauth, size_t reauth_len, + u8 *pmkid) +{ + const u8 *addr[1]; + size_t len[1]; + u8 hash[SHA384_MAC_LEN]; + int res; + + /* PMKID = Truncate-128(Hash(EAP-Initiate/Reauth)) */ + addr[0] = reauth; + len[0] = reauth_len; + if (wpa_key_mgmt_sha384(akmp)) + res = sha384_vector(1, addr, len, hash); + else if (wpa_key_mgmt_sha256(akmp)) + res = sha256_vector(1, addr, len, hash); + else + return -1; + if (res) + return res; + os_memcpy(pmkid, hash, PMKID_LEN); + wpa_hexdump(MSG_DEBUG, "FILS: PMKID", pmkid, PMKID_LEN); return 0; } +int fils_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const u8 *spa, const u8 *aa, + const u8 *snonce, const u8 *anonce, const u8 *dhss, + size_t dhss_len, struct wpa_ptk *ptk, + u8 *ick, size_t *ick_len, int akmp, int cipher, + u8 *fils_ft, size_t *fils_ft_len) +{ + u8 *data, *pos; + size_t data_len; + u8 tmp[FILS_ICK_MAX_LEN + WPA_KEK_MAX_LEN + WPA_TK_MAX_LEN + + FILS_FT_MAX_LEN]; + size_t key_data_len; + const char *label = "FILS PTK Derivation"; + int ret = -1; + + /* + * FILS-Key-Data = PRF-X(PMK, "FILS PTK Derivation", + * SPA || AA || SNonce || ANonce [ || DHss ]) + * ICK = L(FILS-Key-Data, 0, ICK_bits) + * KEK = L(FILS-Key-Data, ICK_bits, KEK_bits) + * TK = L(FILS-Key-Data, ICK_bits + KEK_bits, TK_bits) + * If doing FT initial mobility domain association: + * FILS-FT = L(FILS-Key-Data, ICK_bits + KEK_bits + TK_bits, + * FILS-FT_bits) + */ + data_len = 2 * ETH_ALEN + 2 * FILS_NONCE_LEN + dhss_len; + data = os_malloc(data_len); + if (!data) + goto err; + pos = data; + os_memcpy(pos, spa, ETH_ALEN); + pos += ETH_ALEN; + os_memcpy(pos, aa, ETH_ALEN); + pos += ETH_ALEN; + os_memcpy(pos, snonce, FILS_NONCE_LEN); + pos += FILS_NONCE_LEN; + os_memcpy(pos, anonce, FILS_NONCE_LEN); + pos += FILS_NONCE_LEN; + if (dhss) + os_memcpy(pos, dhss, dhss_len); + + ptk->kck_len = 0; + ptk->kek_len = wpa_kek_len(akmp, pmk_len); + ptk->tk_len = wpa_cipher_key_len(cipher); + if (wpa_key_mgmt_sha384(akmp)) + *ick_len = 48; + else if (wpa_key_mgmt_sha256(akmp)) + *ick_len = 32; + else + goto err; + key_data_len = *ick_len + ptk->kek_len + ptk->tk_len; + + if (fils_ft && fils_ft_len) { + if (akmp == WPA_KEY_MGMT_FT_FILS_SHA256) { + *fils_ft_len = 32; + } else if (akmp == WPA_KEY_MGMT_FT_FILS_SHA384) { + *fils_ft_len = 48; + } else { + *fils_ft_len = 0; + fils_ft = NULL; + } + key_data_len += *fils_ft_len; + } + + if (wpa_key_mgmt_sha384(akmp)) { + wpa_printf(MSG_DEBUG, "FILS: PTK derivation using PRF(SHA384)"); + if (sha384_prf(pmk, pmk_len, label, data, data_len, + tmp, key_data_len) < 0) + goto err; + } else { + wpa_printf(MSG_DEBUG, "FILS: PTK derivation using PRF(SHA256)"); + if (sha256_prf(pmk, pmk_len, label, data, data_len, + tmp, key_data_len) < 0) + goto err; + } + + wpa_printf(MSG_DEBUG, "FILS: PTK derivation - SPA=" MACSTR + " AA=" MACSTR, MAC2STR(spa), MAC2STR(aa)); + wpa_hexdump(MSG_DEBUG, "FILS: SNonce", snonce, FILS_NONCE_LEN); + wpa_hexdump(MSG_DEBUG, "FILS: ANonce", anonce, FILS_NONCE_LEN); + if (dhss) + wpa_hexdump_key(MSG_DEBUG, "FILS: DHss", dhss, dhss_len); + wpa_hexdump_key(MSG_DEBUG, "FILS: PMK", pmk, pmk_len); + wpa_hexdump_key(MSG_DEBUG, "FILS: FILS-Key-Data", tmp, key_data_len); + + os_memcpy(ick, tmp, *ick_len); + wpa_hexdump_key(MSG_DEBUG, "FILS: ICK", ick, *ick_len); + + os_memcpy(ptk->kek, tmp + *ick_len, ptk->kek_len); + wpa_hexdump_key(MSG_DEBUG, "FILS: KEK", ptk->kek, ptk->kek_len); + + os_memcpy(ptk->tk, tmp + *ick_len + ptk->kek_len, ptk->tk_len); + wpa_hexdump_key(MSG_DEBUG, "FILS: TK", ptk->tk, ptk->tk_len); + + if (fils_ft && fils_ft_len) { + os_memcpy(fils_ft, tmp + *ick_len + ptk->kek_len + ptk->tk_len, + *fils_ft_len); + wpa_hexdump_key(MSG_DEBUG, "FILS: FILS-FT", + fils_ft, *fils_ft_len); + } + + ptk->kek2_len = 0; + ptk->kck2_len = 0; + + os_memset(tmp, 0, sizeof(tmp)); + ret = 0; +err: + bin_clear_free(data, data_len); + return ret; +} + + +int fils_key_auth_sk(const u8 *ick, size_t ick_len, const u8 *snonce, + const u8 *anonce, const u8 *sta_addr, const u8 *bssid, + const u8 *g_sta, size_t g_sta_len, + const u8 *g_ap, size_t g_ap_len, + int akmp, u8 *key_auth_sta, u8 *key_auth_ap, + size_t *key_auth_len) +{ + const u8 *addr[6]; + size_t len[6]; + size_t num_elem = 4; + int res; + + wpa_printf(MSG_DEBUG, "FILS: Key-Auth derivation: STA-MAC=" MACSTR + " AP-BSSID=" MACSTR, MAC2STR(sta_addr), MAC2STR(bssid)); + wpa_hexdump_key(MSG_DEBUG, "FILS: ICK", ick, ick_len); + wpa_hexdump(MSG_DEBUG, "FILS: SNonce", snonce, FILS_NONCE_LEN); + wpa_hexdump(MSG_DEBUG, "FILS: ANonce", anonce, FILS_NONCE_LEN); + wpa_hexdump(MSG_DEBUG, "FILS: gSTA", g_sta, g_sta_len); + wpa_hexdump(MSG_DEBUG, "FILS: gAP", g_ap, g_ap_len); + + /* + * For (Re)Association Request frame (STA->AP): + * Key-Auth = HMAC-Hash(ICK, SNonce || ANonce || STA-MAC || AP-BSSID + * [ || gSTA || gAP ]) + */ + addr[0] = snonce; + len[0] = FILS_NONCE_LEN; + addr[1] = anonce; + len[1] = FILS_NONCE_LEN; + addr[2] = sta_addr; + len[2] = ETH_ALEN; + addr[3] = bssid; + len[3] = ETH_ALEN; + if (g_sta && g_ap_len && g_ap && g_ap_len) { + addr[4] = g_sta; + len[4] = g_sta_len; + addr[5] = g_ap; + len[5] = g_ap_len; + num_elem = 6; + } + + if (wpa_key_mgmt_sha384(akmp)) { + *key_auth_len = 48; + res = hmac_sha384_vector(ick, ick_len, num_elem, addr, len, + key_auth_sta); + } else if (wpa_key_mgmt_sha256(akmp)) { + *key_auth_len = 32; + res = hmac_sha256_vector(ick, ick_len, num_elem, addr, len, + key_auth_sta); + } else { + return -1; + } + if (res < 0) + return res; + + /* + * For (Re)Association Response frame (AP->STA): + * Key-Auth = HMAC-Hash(ICK, ANonce || SNonce || AP-BSSID || STA-MAC + * [ || gAP || gSTA ]) + */ + addr[0] = anonce; + addr[1] = snonce; + addr[2] = bssid; + addr[3] = sta_addr; + if (g_sta && g_ap_len && g_ap && g_ap_len) { + addr[4] = g_ap; + len[4] = g_ap_len; + addr[5] = g_sta; + len[5] = g_sta_len; + } + + if (wpa_key_mgmt_sha384(akmp)) + res = hmac_sha384_vector(ick, ick_len, num_elem, addr, len, + key_auth_ap); + else if (wpa_key_mgmt_sha256(akmp)) + res = hmac_sha256_vector(ick, ick_len, num_elem, addr, len, + key_auth_ap); + if (res < 0) + return res; + + wpa_hexdump(MSG_DEBUG, "FILS: Key-Auth (STA)", + key_auth_sta, *key_auth_len); + wpa_hexdump(MSG_DEBUG, "FILS: Key-Auth (AP)", + key_auth_ap, *key_auth_len); + + return 0; +} + +#endif /* CONFIG_FILS */ + + #ifdef CONFIG_IEEE80211R int wpa_ft_mic(const u8 *kck, size_t kck_len, const u8 *sta_addr, const u8 *ap_addr, u8 transaction_seqnum, @@ -218,14 +763,23 @@ int wpa_ft_mic(const u8 *kck, size_t kck_len, const u8 *sta_addr, const u8 *addr[9]; size_t len[9]; size_t i, num_elem = 0; - u8 zero_mic[16]; - - if (kck_len != 16) { + u8 zero_mic[24]; + size_t mic_len, fte_fixed_len; + + if (kck_len == 16) { + mic_len = 16; +#ifdef CONFIG_SHA384 + } else if (kck_len == 24) { + mic_len = 24; +#endif /* CONFIG_SHA384 */ + } else { wpa_printf(MSG_WARNING, "FT: Unsupported KCK length %u", (unsigned int) kck_len); return -1; } + fte_fixed_len = sizeof(struct rsn_ftie) - 16 + mic_len; + addr[num_elem] = sta_addr; len[num_elem] = ETH_ALEN; num_elem++; @@ -249,7 +803,7 @@ int wpa_ft_mic(const u8 *kck, size_t kck_len, const u8 *sta_addr, num_elem++; } if (ftie) { - if (ftie_len < 2 + sizeof(struct rsn_ftie)) + if (ftie_len < 2 + fte_fixed_len) return -1; /* IE hdr and mic_control */ @@ -258,14 +812,14 @@ int wpa_ft_mic(const u8 *kck, size_t kck_len, const u8 *sta_addr, num_elem++; /* MIC field with all zeros */ - os_memset(zero_mic, 0, sizeof(zero_mic)); + os_memset(zero_mic, 0, mic_len); addr[num_elem] = zero_mic; - len[num_elem] = sizeof(zero_mic); + len[num_elem] = mic_len; num_elem++; /* Rest of FTIE */ - addr[num_elem] = ftie + 2 + 2 + 16; - len[num_elem] = ftie_len - (2 + 2 + 16); + addr[num_elem] = ftie + 2 + 2 + mic_len; + len[num_elem] = ftie_len - (2 + 2 + mic_len); num_elem++; } if (ric) { @@ -276,7 +830,17 @@ int wpa_ft_mic(const u8 *kck, size_t kck_len, const u8 *sta_addr, for (i = 0; i < num_elem; i++) wpa_hexdump(MSG_MSGDUMP, "FT: MIC data", addr[i], len[i]); - if (omac1_aes_128_vector(kck, num_elem, addr, len, mic)) +#ifdef CONFIG_SHA384 + if (kck_len == 24) { + u8 hash[SHA384_MAC_LEN]; + + if (hmac_sha384_vector(kck, kck_len, num_elem, addr, len, hash)) + return -1; + os_memcpy(mic, hash, 24); + } +#endif /* CONFIG_SHA384 */ + if (kck_len == 16 && + omac1_aes_128_vector(kck, num_elem, addr, len, mic)) return -1; return 0; @@ -284,23 +848,27 @@ int wpa_ft_mic(const u8 *kck, size_t kck_len, const u8 *sta_addr, static int wpa_ft_parse_ftie(const u8 *ie, size_t ie_len, - struct wpa_ft_ies *parse) + struct wpa_ft_ies *parse, int use_sha384) { const u8 *end, *pos; parse->ftie = ie; parse->ftie_len = ie_len; - pos = ie + sizeof(struct rsn_ftie); + pos = ie + (use_sha384 ? sizeof(struct rsn_ftie_sha384) : + sizeof(struct rsn_ftie)); end = ie + ie_len; + wpa_hexdump(MSG_DEBUG, "FT: Parse FTE subelements", pos, end - pos); while (end - pos >= 2) { u8 id, len; id = *pos++; len = *pos++; - if (len > end - pos) + if (len > end - pos) { + wpa_printf(MSG_DEBUG, "FT: Truncated subelement"); break; + } switch (id) { case FTIE_SUBELEM_R1KH_ID: @@ -332,6 +900,15 @@ static int wpa_ft_parse_ftie(const u8 *ie, size_t ie_len, parse->igtk_len = len; break; #endif /* CONFIG_IEEE80211W */ +#ifdef CONFIG_OCV + case FTIE_SUBELEM_OCI: + parse->oci = pos; + parse->oci_len = len; + break; +#endif /* CONFIG_OCV */ + default: + wpa_printf(MSG_DEBUG, "FT: Unknown subelem id %u", id); + break; } pos += len; @@ -342,13 +919,19 @@ static int wpa_ft_parse_ftie(const u8 *ie, size_t ie_len, int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, - struct wpa_ft_ies *parse) + struct wpa_ft_ies *parse, int use_sha384) { const u8 *end, *pos; struct wpa_ie_data data; int ret; const struct rsn_ftie *ftie; int prot_ie_count = 0; + int update_use_sha384 = 0; + + if (use_sha384 < 0) { + use_sha384 = 0; + update_use_sha384 = 1; + } os_memset(parse, 0, sizeof(*parse)); if (ies == NULL) @@ -366,6 +949,7 @@ int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, switch (id) { case WLAN_EID_RSN: + wpa_hexdump(MSG_DEBUG, "FT: RSNE", pos, len); parse->rsn = pos; parse->rsn_len = len; ret = wpa_parse_wpa_ie_rsn(parse->rsn - 2, @@ -378,22 +962,65 @@ int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, } if (data.num_pmkid == 1 && data.pmkid) parse->rsn_pmkid = data.pmkid; + parse->key_mgmt = data.key_mgmt; + parse->pairwise_cipher = data.pairwise_cipher; + if (update_use_sha384) { + use_sha384 = + wpa_key_mgmt_sha384(parse->key_mgmt); + update_use_sha384 = 0; + } break; case WLAN_EID_MOBILITY_DOMAIN: + wpa_hexdump(MSG_DEBUG, "FT: MDE", pos, len); if (len < sizeof(struct rsn_mdie)) return -1; parse->mdie = pos; parse->mdie_len = len; break; case WLAN_EID_FAST_BSS_TRANSITION: + wpa_hexdump(MSG_DEBUG, "FT: FTE", pos, len); + if (use_sha384) { + const struct rsn_ftie_sha384 *ftie_sha384; + + if (len < sizeof(*ftie_sha384)) + return -1; + ftie_sha384 = + (const struct rsn_ftie_sha384 *) pos; + wpa_hexdump(MSG_DEBUG, "FT: FTE-MIC Control", + ftie_sha384->mic_control, 2); + wpa_hexdump(MSG_DEBUG, "FT: FTE-MIC", + ftie_sha384->mic, + sizeof(ftie_sha384->mic)); + wpa_hexdump(MSG_DEBUG, "FT: FTE-ANonce", + ftie_sha384->anonce, + WPA_NONCE_LEN); + wpa_hexdump(MSG_DEBUG, "FT: FTE-SNonce", + ftie_sha384->snonce, + WPA_NONCE_LEN); + prot_ie_count = ftie_sha384->mic_control[1]; + if (wpa_ft_parse_ftie(pos, len, parse, 1) < 0) + return -1; + break; + } + if (len < sizeof(*ftie)) return -1; ftie = (const struct rsn_ftie *) pos; + wpa_hexdump(MSG_DEBUG, "FT: FTE-MIC Control", + ftie->mic_control, 2); + wpa_hexdump(MSG_DEBUG, "FT: FTE-MIC", + ftie->mic, sizeof(ftie->mic)); + wpa_hexdump(MSG_DEBUG, "FT: FTE-ANonce", + ftie->anonce, WPA_NONCE_LEN); + wpa_hexdump(MSG_DEBUG, "FT: FTE-SNonce", + ftie->snonce, WPA_NONCE_LEN); prot_ie_count = ftie->mic_control[1]; - if (wpa_ft_parse_ftie(pos, len, parse) < 0) + if (wpa_ft_parse_ftie(pos, len, parse, 0) < 0) return -1; break; case WLAN_EID_TIMEOUT_INTERVAL: + wpa_hexdump(MSG_DEBUG, "FT: Timeout Interval", + pos, len); if (len != 5) break; parse->tie = pos; @@ -495,6 +1122,10 @@ static int rsn_key_mgmt_to_bitfield(const u8 *s) return WPA_KEY_MGMT_FT_IEEE8021X; if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_PSK) return WPA_KEY_MGMT_FT_PSK; +#ifdef CONFIG_SHA384 + if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_802_1X_SHA384) + return WPA_KEY_MGMT_FT_IEEE8021X_SHA384; +#endif /* CONFIG_SHA384 */ #endif /* CONFIG_IEEE80211R */ #ifdef CONFIG_IEEE80211W if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_802_1X_SHA256) @@ -512,6 +1143,22 @@ static int rsn_key_mgmt_to_bitfield(const u8 *s) return WPA_KEY_MGMT_IEEE8021X_SUITE_B; if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192) return WPA_KEY_MGMT_IEEE8021X_SUITE_B_192; + if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FILS_SHA256) + return WPA_KEY_MGMT_FILS_SHA256; + if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FILS_SHA384) + return WPA_KEY_MGMT_FILS_SHA384; + if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_FILS_SHA256) + return WPA_KEY_MGMT_FT_FILS_SHA256; + if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_FILS_SHA384) + return WPA_KEY_MGMT_FT_FILS_SHA384; +#ifdef CONFIG_OWE + if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_OWE) + return WPA_KEY_MGMT_OWE; +#endif /* CONFIG_OWE */ +#ifdef CONFIG_DPP + if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_DPP) + return WPA_KEY_MGMT_DPP; +#endif /* CONFIG_DPP */ if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_OSEN) return WPA_KEY_MGMT_OSEN; return 0; @@ -581,6 +1228,9 @@ int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len, pos = rsn_ie + 6; left = rsn_ie_len - 6; + data->group_cipher = WPA_CIPHER_GTK_NOT_USED; + data->has_group = 1; + data->key_mgmt = WPA_KEY_MGMT_OSEN; data->proto = WPA_PROTO_OSEN; } else { const struct rsn_ie_hdr *hdr; @@ -601,6 +1251,7 @@ int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len, if (left >= RSN_SELECTOR_LEN) { data->group_cipher = rsn_selector_to_bitfield(pos); + data->has_group = 1; if (!wpa_cipher_valid_group(data->group_cipher)) { wpa_printf(MSG_DEBUG, "%s: invalid group cipher 0x%x (%08x)", @@ -626,6 +1277,8 @@ int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len, "count %u left %u", __func__, count, left); return -4; } + if (count) + data->has_pairwise = 1; for (i = 0; i < count; i++) { data->pairwise_cipher |= rsn_selector_to_bitfield(pos); pos += RSN_SELECTOR_LEN; @@ -844,6 +1497,15 @@ int wpa_parse_wpa_ie_wpa(const u8 *wpa_ie, size_t wpa_ie_len, } +int wpa_default_rsn_cipher(int freq) +{ + if (freq > 56160) + return WPA_CIPHER_GCMP; /* DMG */ + + return WPA_CIPHER_CCMP; +} + + #ifdef CONFIG_IEEE80211R /** @@ -851,27 +1513,39 @@ int wpa_parse_wpa_ie_wpa(const u8 *wpa_ie, size_t wpa_ie_len, * * IEEE Std 802.11r-2008 - 8.5.1.5.3 */ -void wpa_derive_pmk_r0(const u8 *xxkey, size_t xxkey_len, - const u8 *ssid, size_t ssid_len, - const u8 *mdid, const u8 *r0kh_id, size_t r0kh_id_len, - const u8 *s0kh_id, u8 *pmk_r0, u8 *pmk_r0_name) +int wpa_derive_pmk_r0(const u8 *xxkey, size_t xxkey_len, + const u8 *ssid, size_t ssid_len, + const u8 *mdid, const u8 *r0kh_id, size_t r0kh_id_len, + const u8 *s0kh_id, u8 *pmk_r0, u8 *pmk_r0_name, + int use_sha384) { u8 buf[1 + SSID_MAX_LEN + MOBILITY_DOMAIN_ID_LEN + 1 + FT_R0KH_ID_MAX_LEN + ETH_ALEN]; - u8 *pos, r0_key_data[48], hash[32]; + u8 *pos, r0_key_data[64], hash[48]; const u8 *addr[2]; size_t len[2]; + size_t q = use_sha384 ? 48 : 32; + size_t r0_key_data_len = q + 16; /* * R0-Key-Data = KDF-384(XXKey, "FT-R0", * SSIDlength || SSID || MDID || R0KHlength || * R0KH-ID || S0KH-ID) - * XXKey is either the second 256 bits of MSK or PSK. - * PMK-R0 = L(R0-Key-Data, 0, 256) - * PMK-R0Name-Salt = L(R0-Key-Data, 256, 128) + * XXKey is either the second 256 bits of MSK or PSK; or the first + * 384 bits of MSK for FT-EAP-SHA384. + * PMK-R0 = L(R0-Key-Data, 0, Q) + * PMK-R0Name-Salt = L(R0-Key-Data, Q, 128) + * Q = 384 for FT-EAP-SHA384; otherwise, 256 */ if (ssid_len > SSID_MAX_LEN || r0kh_id_len > FT_R0KH_ID_MAX_LEN) - return; + return -1; + wpa_printf(MSG_DEBUG, "FT: Derive PMK-R0 using KDF-%s", + use_sha384 ? "SHA384" : "SHA256"); + wpa_hexdump_key(MSG_DEBUG, "FT: XXKey", xxkey, xxkey_len); + wpa_hexdump_ascii(MSG_DEBUG, "FT: SSID", ssid, ssid_len); + wpa_hexdump(MSG_DEBUG, "FT: MDID", mdid, MOBILITY_DOMAIN_ID_LEN); + wpa_hexdump_ascii(MSG_DEBUG, "FT: R0KH-ID", r0kh_id, r0kh_id_len); + wpa_printf(MSG_DEBUG, "FT: S0KH-ID: " MACSTR, MAC2STR(s0kh_id)); pos = buf; *pos++ = ssid_len; os_memcpy(pos, ssid, ssid_len); @@ -884,20 +1558,51 @@ void wpa_derive_pmk_r0(const u8 *xxkey, size_t xxkey_len, os_memcpy(pos, s0kh_id, ETH_ALEN); pos += ETH_ALEN; - sha256_prf(xxkey, xxkey_len, "FT-R0", buf, pos - buf, - r0_key_data, sizeof(r0_key_data)); - os_memcpy(pmk_r0, r0_key_data, PMK_LEN); +#ifdef CONFIG_SHA384 + if (use_sha384) { + if (xxkey_len != SHA384_MAC_LEN) { + wpa_printf(MSG_ERROR, + "FT: Unexpected XXKey length %d (expected %d)", + (int) xxkey_len, SHA384_MAC_LEN); + return -1; + } + if (sha384_prf(xxkey, xxkey_len, "FT-R0", buf, pos - buf, + r0_key_data, r0_key_data_len) < 0) + return -1; + } +#endif /* CONFIG_SHA384 */ + if (!use_sha384) { + if (xxkey_len != PMK_LEN) { + wpa_printf(MSG_ERROR, + "FT: Unexpected XXKey length %d (expected %d)", + (int) xxkey_len, PMK_LEN); + return -1; + } + if (sha256_prf(xxkey, xxkey_len, "FT-R0", buf, pos - buf, + r0_key_data, r0_key_data_len) < 0) + return -1; + } + os_memcpy(pmk_r0, r0_key_data, q); + wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R0", pmk_r0, q); + wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R0Name-Salt", &r0_key_data[q], 16); /* - * PMKR0Name = Truncate-128(SHA-256("FT-R0N" || PMK-R0Name-Salt) + * PMKR0Name = Truncate-128(Hash("FT-R0N" || PMK-R0Name-Salt) */ addr[0] = (const u8 *) "FT-R0N"; len[0] = 6; - addr[1] = r0_key_data + PMK_LEN; + addr[1] = &r0_key_data[q]; len[1] = 16; - sha256_vector(2, addr, len, hash); +#ifdef CONFIG_SHA384 + if (use_sha384 && sha384_vector(2, addr, len, hash) < 0) + return -1; +#endif /* CONFIG_SHA384 */ + if (!use_sha384 && sha256_vector(2, addr, len, hash) < 0) + return -1; os_memcpy(pmk_r0_name, hash, WPA_PMK_NAME_LEN); + os_memset(r0_key_data, 0, sizeof(r0_key_data)); + return 0; } @@ -906,16 +1611,16 @@ void wpa_derive_pmk_r0(const u8 *xxkey, size_t xxkey_len, * * IEEE Std 802.11r-2008 - 8.5.1.5.4 */ -void wpa_derive_pmk_r1_name(const u8 *pmk_r0_name, const u8 *r1kh_id, - const u8 *s1kh_id, u8 *pmk_r1_name) +int wpa_derive_pmk_r1_name(const u8 *pmk_r0_name, const u8 *r1kh_id, + const u8 *s1kh_id, u8 *pmk_r1_name, int use_sha384) { - u8 hash[32]; + u8 hash[48]; const u8 *addr[4]; size_t len[4]; /* - * PMKR1Name = Truncate-128(SHA-256("FT-R1N" || PMKR0Name || - * R1KH-ID || S1KH-ID)) + * PMKR1Name = Truncate-128(Hash("FT-R1N" || PMKR0Name || + * R1KH-ID || S1KH-ID)) */ addr[0] = (const u8 *) "FT-R1N"; len[0] = 6; @@ -926,8 +1631,14 @@ void wpa_derive_pmk_r1_name(const u8 *pmk_r0_name, const u8 *r1kh_id, addr[3] = s1kh_id; len[3] = ETH_ALEN; - sha256_vector(4, addr, len, hash); +#ifdef CONFIG_SHA384 + if (use_sha384 && sha384_vector(4, addr, len, hash) < 0) + return -1; +#endif /* CONFIG_SHA384 */ + if (!use_sha384 && sha256_vector(4, addr, len, hash) < 0) + return -1; os_memcpy(pmk_r1_name, hash, WPA_PMK_NAME_LEN); + return 0; } @@ -936,23 +1647,46 @@ void wpa_derive_pmk_r1_name(const u8 *pmk_r0_name, const u8 *r1kh_id, * * IEEE Std 802.11r-2008 - 8.5.1.5.4 */ -void wpa_derive_pmk_r1(const u8 *pmk_r0, const u8 *pmk_r0_name, - const u8 *r1kh_id, const u8 *s1kh_id, - u8 *pmk_r1, u8 *pmk_r1_name) +int wpa_derive_pmk_r1(const u8 *pmk_r0, size_t pmk_r0_len, + const u8 *pmk_r0_name, + const u8 *r1kh_id, const u8 *s1kh_id, + u8 *pmk_r1, u8 *pmk_r1_name) { u8 buf[FT_R1KH_ID_LEN + ETH_ALEN]; u8 *pos; /* PMK-R1 = KDF-256(PMK-R0, "FT-R1", R1KH-ID || S1KH-ID) */ + wpa_printf(MSG_DEBUG, "FT: Derive PMK-R1 using KDF-%s", + pmk_r0_len == SHA384_MAC_LEN ? "SHA384" : "SHA256"); + wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R0", pmk_r0, pmk_r0_len); + wpa_hexdump(MSG_DEBUG, "FT: R1KH-ID", r1kh_id, FT_R1KH_ID_LEN); + wpa_printf(MSG_DEBUG, "FT: S1KH-ID: " MACSTR, MAC2STR(s1kh_id)); pos = buf; os_memcpy(pos, r1kh_id, FT_R1KH_ID_LEN); pos += FT_R1KH_ID_LEN; os_memcpy(pos, s1kh_id, ETH_ALEN); pos += ETH_ALEN; - sha256_prf(pmk_r0, PMK_LEN, "FT-R1", buf, pos - buf, pmk_r1, PMK_LEN); +#ifdef CONFIG_SHA384 + if (pmk_r0_len == SHA384_MAC_LEN && + sha384_prf(pmk_r0, pmk_r0_len, "FT-R1", + buf, pos - buf, pmk_r1, pmk_r0_len) < 0) + return -1; +#endif /* CONFIG_SHA384 */ + if (pmk_r0_len == PMK_LEN && + sha256_prf(pmk_r0, pmk_r0_len, "FT-R1", + buf, pos - buf, pmk_r1, pmk_r0_len) < 0) + return -1; + if (pmk_r0_len != SHA384_MAC_LEN && pmk_r0_len != PMK_LEN) { + wpa_printf(MSG_ERROR, "FT: Unexpected PMK-R0 length %d", + (int) pmk_r0_len); + return -1; + } + wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", pmk_r1, pmk_r0_len); - wpa_derive_pmk_r1_name(pmk_r0_name, r1kh_id, s1kh_id, pmk_r1_name); + return wpa_derive_pmk_r1_name(pmk_r0_name, r1kh_id, s1kh_id, + pmk_r1_name, + pmk_r0_len == SHA384_MAC_LEN); } @@ -961,7 +1695,8 @@ void wpa_derive_pmk_r1(const u8 *pmk_r0, const u8 *pmk_r0_name, * * IEEE Std 802.11r-2008 - 8.5.1.5.5 */ -int wpa_pmk_r1_to_ptk(const u8 *pmk_r1, const u8 *snonce, const u8 *anonce, +int wpa_pmk_r1_to_ptk(const u8 *pmk_r1, size_t pmk_r1_len, + const u8 *snonce, const u8 *anonce, const u8 *sta_addr, const u8 *bssid, const u8 *pmk_r1_name, struct wpa_ptk *ptk, u8 *ptk_name, int akmp, int cipher) @@ -970,13 +1705,21 @@ int wpa_pmk_r1_to_ptk(const u8 *pmk_r1, const u8 *snonce, const u8 *anonce, u8 *pos, hash[32]; const u8 *addr[6]; size_t len[6]; - u8 tmp[WPA_KCK_MAX_LEN + WPA_KEK_MAX_LEN + WPA_TK_MAX_LEN]; - size_t ptk_len; + u8 tmp[2 * WPA_KCK_MAX_LEN + 2 * WPA_KEK_MAX_LEN + WPA_TK_MAX_LEN]; + size_t ptk_len, offset; + int use_sha384 = wpa_key_mgmt_sha384(akmp); /* * PTK = KDF-PTKLen(PMK-R1, "FT-PTK", SNonce || ANonce || * BSSID || STA-ADDR) */ + wpa_printf(MSG_DEBUG, "FT: Derive PTK using KDF-%s", + use_sha384 ? "SHA384" : "SHA256"); + wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", pmk_r1, pmk_r1_len); + wpa_hexdump(MSG_DEBUG, "FT: SNonce", snonce, WPA_NONCE_LEN); + wpa_hexdump(MSG_DEBUG, "FT: ANonce", anonce, WPA_NONCE_LEN); + wpa_printf(MSG_DEBUG, "FT: BSSID=" MACSTR " STA-ADDR=" MACSTR, + MAC2STR(bssid), MAC2STR(sta_addr)); pos = buf; os_memcpy(pos, snonce, WPA_NONCE_LEN); pos += WPA_NONCE_LEN; @@ -987,17 +1730,45 @@ int wpa_pmk_r1_to_ptk(const u8 *pmk_r1, const u8 *snonce, const u8 *anonce, os_memcpy(pos, sta_addr, ETH_ALEN); pos += ETH_ALEN; - ptk->kck_len = wpa_kck_len(akmp); - ptk->kek_len = wpa_kek_len(akmp); + ptk->kck_len = wpa_kck_len(akmp, PMK_LEN); + ptk->kck2_len = wpa_kck2_len(akmp); + ptk->kek_len = wpa_kek_len(akmp, PMK_LEN); + ptk->kek2_len = wpa_kek2_len(akmp); ptk->tk_len = wpa_cipher_key_len(cipher); - ptk_len = ptk->kck_len + ptk->kek_len + ptk->tk_len; - - sha256_prf(pmk_r1, PMK_LEN, "FT-PTK", buf, pos - buf, tmp, ptk_len); + ptk_len = ptk->kck_len + ptk->kek_len + ptk->tk_len + + ptk->kck2_len + ptk->kek2_len; + +#ifdef CONFIG_SHA384 + if (use_sha384) { + if (pmk_r1_len != SHA384_MAC_LEN) { + wpa_printf(MSG_ERROR, + "FT: Unexpected PMK-R1 length %d (expected %d)", + (int) pmk_r1_len, SHA384_MAC_LEN); + return -1; + } + if (sha384_prf(pmk_r1, pmk_r1_len, "FT-PTK", + buf, pos - buf, tmp, ptk_len) < 0) + return -1; + } +#endif /* CONFIG_SHA384 */ + if (!use_sha384) { + if (pmk_r1_len != PMK_LEN) { + wpa_printf(MSG_ERROR, + "FT: Unexpected PMK-R1 length %d (expected %d)", + (int) pmk_r1_len, PMK_LEN); + return -1; + } + if (sha256_prf(pmk_r1, pmk_r1_len, "FT-PTK", + buf, pos - buf, tmp, ptk_len) < 0) + return -1; + } + wpa_hexdump_key(MSG_DEBUG, "FT: PTK", tmp, ptk_len); /* * PTKName = Truncate-128(SHA-256(PMKR1Name || "FT-PTKN" || SNonce || * ANonce || BSSID || STA-ADDR)) */ + wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", pmk_r1_name, WPA_PMK_NAME_LEN); addr[0] = pmk_r1_name; len[0] = WPA_PMK_NAME_LEN; addr[1] = (const u8 *) "FT-PTKN"; @@ -1011,15 +1782,28 @@ int wpa_pmk_r1_to_ptk(const u8 *pmk_r1, const u8 *snonce, const u8 *anonce, addr[5] = sta_addr; len[5] = ETH_ALEN; - sha256_vector(6, addr, len, hash); + if (sha256_vector(6, addr, len, hash) < 0) + return -1; os_memcpy(ptk_name, hash, WPA_PMK_NAME_LEN); os_memcpy(ptk->kck, tmp, ptk->kck_len); - os_memcpy(ptk->kek, tmp + ptk->kck_len, ptk->kek_len); - os_memcpy(ptk->tk, tmp + ptk->kck_len + ptk->kek_len, ptk->tk_len); + offset = ptk->kck_len; + os_memcpy(ptk->kek, tmp + offset, ptk->kek_len); + offset += ptk->kek_len; + os_memcpy(ptk->tk, tmp + offset, ptk->tk_len); + offset += ptk->tk_len; + os_memcpy(ptk->kck2, tmp + offset, ptk->kck2_len); + offset += ptk->kck2_len; + os_memcpy(ptk->kek2, tmp + offset, ptk->kek2_len); wpa_hexdump_key(MSG_DEBUG, "FT: KCK", ptk->kck, ptk->kck_len); wpa_hexdump_key(MSG_DEBUG, "FT: KEK", ptk->kek, ptk->kek_len); + if (ptk->kck2_len) + wpa_hexdump_key(MSG_DEBUG, "FT: KCK2", + ptk->kck2, ptk->kck2_len); + if (ptk->kek2_len) + wpa_hexdump_key(MSG_DEBUG, "FT: KEK2", + ptk->kek2, ptk->kek2_len); wpa_hexdump_key(MSG_DEBUG, "FT: TK", ptk->tk, ptk->tk_len); wpa_hexdump(MSG_DEBUG, "FT: PTKName", ptk_name, WPA_PMK_NAME_LEN); @@ -1038,29 +1822,48 @@ int wpa_pmk_r1_to_ptk(const u8 *pmk_r1, const u8 *snonce, const u8 *anonce, * @aa: Authenticator address * @spa: Supplicant address * @pmkid: Buffer for PMKID - * @use_sha256: Whether to use SHA256-based KDF + * @akmp: Negotiated key management protocol * - * IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy - * PMKID = HMAC-SHA1-128(PMK, "PMK Name" || AA || SPA) + * IEEE Std 802.11-2016 - 12.7.1.3 Pairwise key hierarchy + * AKM: 00-0F-AC:5, 00-0F-AC:6, 00-0F-AC:14, 00-0F-AC:16 + * PMKID = Truncate-128(HMAC-SHA-256(PMK, "PMK Name" || AA || SPA)) + * AKM: 00-0F-AC:11 + * See rsn_pmkid_suite_b() + * AKM: 00-0F-AC:12 + * See rsn_pmkid_suite_b_192() + * AKM: 00-0F-AC:13, 00-0F-AC:15, 00-0F-AC:17 + * PMKID = Truncate-128(HMAC-SHA-384(PMK, "PMK Name" || AA || SPA)) + * Otherwise: + * PMKID = Truncate-128(HMAC-SHA-1(PMK, "PMK Name" || AA || SPA)) */ void rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa, const u8 *spa, - u8 *pmkid, int use_sha256) + u8 *pmkid, int akmp) { char *title = "PMK Name"; const u8 *addr[3]; const size_t len[3] = { 8, ETH_ALEN, ETH_ALEN }; - unsigned char hash[SHA256_MAC_LEN]; + unsigned char hash[SHA384_MAC_LEN]; addr[0] = (u8 *) title; addr[1] = aa; addr[2] = spa; -#ifdef CONFIG_IEEE80211W - if (use_sha256) + if (0) { +#if defined(CONFIG_FILS) || defined(CONFIG_SHA384) + } else if (wpa_key_mgmt_sha384(akmp)) { + wpa_printf(MSG_DEBUG, "RSN: Derive PMKID using HMAC-SHA-384"); + hmac_sha384_vector(pmk, pmk_len, 3, addr, len, hash); +#endif /* CONFIG_FILS || CONFIG_SHA384 */ +#if defined(CONFIG_IEEE80211W) || defined(CONFIG_FILS) + } else if (wpa_key_mgmt_sha256(akmp)) { + wpa_printf(MSG_DEBUG, "RSN: Derive PMKID using HMAC-SHA-256"); hmac_sha256_vector(pmk, pmk_len, 3, addr, len, hash); - else -#endif /* CONFIG_IEEE80211W */ +#endif /* CONFIG_IEEE80211W || CONFIG_FILS */ + } else { + wpa_printf(MSG_DEBUG, "RSN: Derive PMKID using HMAC-SHA-1"); hmac_sha1_vector(pmk, pmk_len, 3, addr, len, hash); + } + wpa_hexdump(MSG_DEBUG, "RSN: Derived PMKID", hash, PMKID_LEN); os_memcpy(pmkid, hash, PMKID_LEN); } @@ -1157,6 +1960,14 @@ const char * wpa_cipher_txt(int cipher) return "GCMP-256"; case WPA_CIPHER_CCMP_256: return "CCMP-256"; + case WPA_CIPHER_AES_128_CMAC: + return "BIP"; + case WPA_CIPHER_BIP_GMAC_128: + return "BIP-GMAC-128"; + case WPA_CIPHER_BIP_GMAC_256: + return "BIP-GMAC-256"; + case WPA_CIPHER_BIP_CMAC_256: + return "BIP-CMAC-256"; case WPA_CIPHER_GTK_NOT_USED: return "GTK_NOT_USED"; default: @@ -1193,6 +2004,8 @@ const char * wpa_key_mgmt_txt(int key_mgmt, int proto) #ifdef CONFIG_IEEE80211R case WPA_KEY_MGMT_FT_IEEE8021X: return "FT-EAP"; + case WPA_KEY_MGMT_FT_IEEE8021X_SHA384: + return "FT-EAP-SHA384"; case WPA_KEY_MGMT_FT_PSK: return "FT-PSK"; #endif /* CONFIG_IEEE80211R */ @@ -1214,6 +2027,18 @@ const char * wpa_key_mgmt_txt(int key_mgmt, int proto) return "WPA2-EAP-SUITE-B"; case WPA_KEY_MGMT_IEEE8021X_SUITE_B_192: return "WPA2-EAP-SUITE-B-192"; + case WPA_KEY_MGMT_FILS_SHA256: + return "FILS-SHA256"; + case WPA_KEY_MGMT_FILS_SHA384: + return "FILS-SHA384"; + case WPA_KEY_MGMT_FT_FILS_SHA256: + return "FT-FILS-SHA256"; + case WPA_KEY_MGMT_FT_FILS_SHA384: + return "FT-FILS-SHA384"; + case WPA_KEY_MGMT_OWE: + return "OWE"; + case WPA_KEY_MGMT_DPP: + return "DPP"; default: return "UNKNOWN"; } @@ -1222,28 +2047,36 @@ const char * wpa_key_mgmt_txt(int key_mgmt, int proto) u32 wpa_akm_to_suite(int akm) { + if (akm & WPA_KEY_MGMT_FT_IEEE8021X_SHA384) + return RSN_AUTH_KEY_MGMT_FT_802_1X_SHA384; if (akm & WPA_KEY_MGMT_FT_IEEE8021X) - return WLAN_AKM_SUITE_FT_8021X; + return RSN_AUTH_KEY_MGMT_FT_802_1X; if (akm & WPA_KEY_MGMT_FT_PSK) - return WLAN_AKM_SUITE_FT_PSK; - if (akm & WPA_KEY_MGMT_IEEE8021X) - return WLAN_AKM_SUITE_8021X; + return RSN_AUTH_KEY_MGMT_FT_PSK; if (akm & WPA_KEY_MGMT_IEEE8021X_SHA256) - return WLAN_AKM_SUITE_8021X_SHA256; + return RSN_AUTH_KEY_MGMT_802_1X_SHA256; if (akm & WPA_KEY_MGMT_IEEE8021X) - return WLAN_AKM_SUITE_8021X; + return RSN_AUTH_KEY_MGMT_UNSPEC_802_1X; if (akm & WPA_KEY_MGMT_PSK_SHA256) - return WLAN_AKM_SUITE_PSK_SHA256; + return RSN_AUTH_KEY_MGMT_PSK_SHA256; if (akm & WPA_KEY_MGMT_PSK) - return WLAN_AKM_SUITE_PSK; + return RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X; if (akm & WPA_KEY_MGMT_CCKM) - return WLAN_AKM_SUITE_CCKM; + return RSN_AUTH_KEY_MGMT_CCKM; if (akm & WPA_KEY_MGMT_OSEN) - return WLAN_AKM_SUITE_OSEN; + return RSN_AUTH_KEY_MGMT_OSEN; if (akm & WPA_KEY_MGMT_IEEE8021X_SUITE_B) - return WLAN_AKM_SUITE_8021X_SUITE_B; + return RSN_AUTH_KEY_MGMT_802_1X_SUITE_B; if (akm & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) - return WLAN_AKM_SUITE_8021X_SUITE_B_192; + return RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192; + if (akm & WPA_KEY_MGMT_FILS_SHA256) + return RSN_AUTH_KEY_MGMT_FILS_SHA256; + if (akm & WPA_KEY_MGMT_FILS_SHA384) + return RSN_AUTH_KEY_MGMT_FILS_SHA384; + if (akm & WPA_KEY_MGMT_FT_FILS_SHA256) + return RSN_AUTH_KEY_MGMT_FT_FILS_SHA256; + if (akm & WPA_KEY_MGMT_FT_FILS_SHA384) + return RSN_AUTH_KEY_MGMT_FT_FILS_SHA384; return 0; } @@ -1285,7 +2118,7 @@ int wpa_compare_rsn_ie(int ft_initial_assoc, } -#ifdef CONFIG_IEEE80211R +#if defined(CONFIG_IEEE80211R) || defined(CONFIG_FILS) int wpa_insert_pmkid(u8 *ies, size_t *ies_len, const u8 *pmkid) { u8 *start, *end, *rpos, *rend; @@ -1384,7 +2217,7 @@ int wpa_insert_pmkid(u8 *ies, size_t *ies_len, const u8 *pmkid) return 0; } -#endif /* CONFIG_IEEE80211R */ +#endif /* CONFIG_IEEE80211R || CONFIG_FILS */ int wpa_cipher_key_len(int cipher) @@ -1423,7 +2256,7 @@ int wpa_cipher_rsc_len(int cipher) } -int wpa_cipher_to_alg(int cipher) +enum wpa_alg wpa_cipher_to_alg(int cipher) { switch (cipher) { case WPA_CIPHER_CCMP_256: @@ -1618,6 +2451,14 @@ int wpa_parse_cipher(const char *value) val |= WPA_CIPHER_NONE; else if (os_strcmp(start, "GTK_NOT_USED") == 0) val |= WPA_CIPHER_GTK_NOT_USED; + else if (os_strcmp(start, "AES-128-CMAC") == 0) + val |= WPA_CIPHER_AES_128_CMAC; + else if (os_strcmp(start, "BIP-GMAC-128") == 0) + val |= WPA_CIPHER_BIP_GMAC_128; + else if (os_strcmp(start, "BIP-GMAC-256") == 0) + val |= WPA_CIPHER_BIP_GMAC_256; + else if (os_strcmp(start, "BIP-CMAC-256") == 0) + val |= WPA_CIPHER_BIP_CMAC_256; else { os_free(buf); return -1; @@ -1673,6 +2514,34 @@ int wpa_write_ciphers(char *start, char *end, int ciphers, const char *delim) return -1; pos += ret; } + if (ciphers & WPA_CIPHER_AES_128_CMAC) { + ret = os_snprintf(pos, end - pos, "%sAES-128-CMAC", + pos == start ? "" : delim); + if (os_snprintf_error(end - pos, ret)) + return -1; + pos += ret; + } + if (ciphers & WPA_CIPHER_BIP_GMAC_128) { + ret = os_snprintf(pos, end - pos, "%sBIP-GMAC-128", + pos == start ? "" : delim); + if (os_snprintf_error(end - pos, ret)) + return -1; + pos += ret; + } + if (ciphers & WPA_CIPHER_BIP_GMAC_256) { + ret = os_snprintf(pos, end - pos, "%sBIP-GMAC-256", + pos == start ? "" : delim); + if (os_snprintf_error(end - pos, ret)) + return -1; + pos += ret; + } + if (ciphers & WPA_CIPHER_BIP_CMAC_256) { + ret = os_snprintf(pos, end - pos, "%sBIP-CMAC-256", + pos == start ? "" : delim); + if (os_snprintf_error(end - pos, ret)) + return -1; + pos += ret; + } if (ciphers & WPA_CIPHER_NONE) { ret = os_snprintf(pos, end - pos, "%sNONE", pos == start ? "" : delim); @@ -1707,3 +2576,29 @@ int wpa_select_ap_group_cipher(int wpa, int wpa_pairwise, int rsn_pairwise) return WPA_CIPHER_CCMP_256; return WPA_CIPHER_CCMP; } + + +#ifdef CONFIG_FILS +int fils_domain_name_hash(const char *domain, u8 *hash) +{ + char buf[255], *wpos = buf; + const char *pos = domain; + size_t len; + const u8 *addr[1]; + u8 mac[SHA256_MAC_LEN]; + + for (len = 0; len < sizeof(buf) && *pos; len++) { + if (isalpha(*pos) && isupper(*pos)) + *wpos++ = tolower(*pos); + else + *wpos++ = *pos; + pos++; + } + + addr[0] = (const u8 *) buf; + if (sha256_vector(1, addr, &len, mac) < 0) + return -1; + os_memcpy(hash, mac, 2); + return 0; +} +#endif /* CONFIG_FILS */ diff --git a/freebsd/contrib/wpa/src/common/wpa_common.h b/freebsd/contrib/wpa/src/common/wpa_common.h index 1021ccb0..e83d6887 100644 --- a/freebsd/contrib/wpa/src/common/wpa_common.h +++ b/freebsd/contrib/wpa/src/common/wpa_common.h @@ -1,6 +1,6 @@ /* * WPA definitions shared between hostapd and wpa_supplicant - * Copyright (c) 2002-2015, Jouni Malinen <j@w1.fi> + * Copyright (c) 2002-2018, Jouni Malinen <j@w1.fi> * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -13,13 +13,15 @@ #define PMKID_LEN 16 #define PMK_LEN 32 #define PMK_LEN_SUITE_B_192 48 -#define PMK_LEN_MAX 48 +#define PMK_LEN_MAX 64 #define WPA_REPLAY_COUNTER_LEN 8 #define WPA_NONCE_LEN 32 #define WPA_KEY_RSC_LEN 8 #define WPA_GMK_LEN 32 #define WPA_GTK_MAX_LEN 32 +#define OWE_DH_GROUP 19 + #define WPA_ALLOWED_PAIRWISE_CIPHERS \ (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP | WPA_CIPHER_TKIP | WPA_CIPHER_NONE | \ WPA_CIPHER_GCMP_256 | WPA_CIPHER_CCMP_256) @@ -27,6 +29,9 @@ WPA_CIPHER_GCMP_256 | WPA_CIPHER_CCMP_256) (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP | WPA_CIPHER_TKIP | \ WPA_CIPHER_GCMP_256 | WPA_CIPHER_CCMP_256 | \ WPA_CIPHER_GTK_NOT_USED) +#define WPA_ALLOWED_GROUP_MGMT_CIPHERS \ +(WPA_CIPHER_AES_128_CMAC | WPA_CIPHER_BIP_GMAC_128 | WPA_CIPHER_BIP_GMAC_256 | \ +WPA_CIPHER_BIP_CMAC_256) #define WPA_SELECTOR_LEN 4 #define WPA_VERSION 1 @@ -48,10 +53,8 @@ WPA_CIPHER_GTK_NOT_USED) #define RSN_AUTH_KEY_MGMT_UNSPEC_802_1X RSN_SELECTOR(0x00, 0x0f, 0xac, 1) #define RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X RSN_SELECTOR(0x00, 0x0f, 0xac, 2) -#ifdef CONFIG_IEEE80211R #define RSN_AUTH_KEY_MGMT_FT_802_1X RSN_SELECTOR(0x00, 0x0f, 0xac, 3) #define RSN_AUTH_KEY_MGMT_FT_PSK RSN_SELECTOR(0x00, 0x0f, 0xac, 4) -#endif /* CONFIG_IEEE80211R */ #define RSN_AUTH_KEY_MGMT_802_1X_SHA256 RSN_SELECTOR(0x00, 0x0f, 0xac, 5) #define RSN_AUTH_KEY_MGMT_PSK_SHA256 RSN_SELECTOR(0x00, 0x0f, 0xac, 6) #define RSN_AUTH_KEY_MGMT_TPK_HANDSHAKE RSN_SELECTOR(0x00, 0x0f, 0xac, 7) @@ -59,17 +62,24 @@ WPA_CIPHER_GTK_NOT_USED) #define RSN_AUTH_KEY_MGMT_FT_SAE RSN_SELECTOR(0x00, 0x0f, 0xac, 9) #define RSN_AUTH_KEY_MGMT_802_1X_SUITE_B RSN_SELECTOR(0x00, 0x0f, 0xac, 11) #define RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192 RSN_SELECTOR(0x00, 0x0f, 0xac, 12) -#define RSN_AUTH_KEY_MGMT_FT_802_1X_SUITE_B_192 \ -RSN_SELECTOR(0x00, 0x0f, 0xac, 13) +#define RSN_AUTH_KEY_MGMT_FT_802_1X_SHA384 RSN_SELECTOR(0x00, 0x0f, 0xac, 13) +#define RSN_AUTH_KEY_MGMT_FILS_SHA256 RSN_SELECTOR(0x00, 0x0f, 0xac, 14) +#define RSN_AUTH_KEY_MGMT_FILS_SHA384 RSN_SELECTOR(0x00, 0x0f, 0xac, 15) +#define RSN_AUTH_KEY_MGMT_FT_FILS_SHA256 RSN_SELECTOR(0x00, 0x0f, 0xac, 16) +#define RSN_AUTH_KEY_MGMT_FT_FILS_SHA384 RSN_SELECTOR(0x00, 0x0f, 0xac, 17) +#define RSN_AUTH_KEY_MGMT_OWE RSN_SELECTOR(0x00, 0x0f, 0xac, 18) #define RSN_AUTH_KEY_MGMT_CCKM RSN_SELECTOR(0x00, 0x40, 0x96, 0x00) #define RSN_AUTH_KEY_MGMT_OSEN RSN_SELECTOR(0x50, 0x6f, 0x9a, 0x01) +#define RSN_AUTH_KEY_MGMT_DPP RSN_SELECTOR(0x50, 0x6f, 0x9a, 0x02) #define RSN_CIPHER_SUITE_NONE RSN_SELECTOR(0x00, 0x0f, 0xac, 0) +#define RSN_CIPHER_SUITE_WEP40 RSN_SELECTOR(0x00, 0x0f, 0xac, 1) #define RSN_CIPHER_SUITE_TKIP RSN_SELECTOR(0x00, 0x0f, 0xac, 2) #if 0 #define RSN_CIPHER_SUITE_WRAP RSN_SELECTOR(0x00, 0x0f, 0xac, 3) #endif #define RSN_CIPHER_SUITE_CCMP RSN_SELECTOR(0x00, 0x0f, 0xac, 4) +#define RSN_CIPHER_SUITE_WEP104 RSN_SELECTOR(0x00, 0x0f, 0xac, 5) #define RSN_CIPHER_SUITE_AES_128_CMAC RSN_SELECTOR(0x00, 0x0f, 0xac, 6) #define RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED RSN_SELECTOR(0x00, 0x0f, 0xac, 7) #define RSN_CIPHER_SUITE_GCMP RSN_SELECTOR(0x00, 0x0f, 0xac, 8) @@ -78,6 +88,12 @@ RSN_SELECTOR(0x00, 0x0f, 0xac, 13) #define RSN_CIPHER_SUITE_BIP_GMAC_128 RSN_SELECTOR(0x00, 0x0f, 0xac, 11) #define RSN_CIPHER_SUITE_BIP_GMAC_256 RSN_SELECTOR(0x00, 0x0f, 0xac, 12) #define RSN_CIPHER_SUITE_BIP_CMAC_256 RSN_SELECTOR(0x00, 0x0f, 0xac, 13) +#define RSN_CIPHER_SUITE_SMS4 RSN_SELECTOR(0x00, 0x14, 0x72, 1) +#define RSN_CIPHER_SUITE_CKIP RSN_SELECTOR(0x00, 0x40, 0x96, 0) +#define RSN_CIPHER_SUITE_CKIP_CMIC RSN_SELECTOR(0x00, 0x40, 0x96, 1) +#define RSN_CIPHER_SUITE_CMIC RSN_SELECTOR(0x00, 0x40, 0x96, 2) +/* KRK is defined for nl80211 use only */ +#define RSN_CIPHER_SUITE_KRK RSN_SELECTOR(0x00, 0x40, 0x96, 255) /* EAPOL-Key Key Data Encapsulation * GroupKey and PeerKey require encryption, otherwise, encryption is optional. @@ -88,18 +104,13 @@ RSN_SELECTOR(0x00, 0x0f, 0xac, 13) #endif #define RSN_KEY_DATA_MAC_ADDR RSN_SELECTOR(0x00, 0x0f, 0xac, 3) #define RSN_KEY_DATA_PMKID RSN_SELECTOR(0x00, 0x0f, 0xac, 4) -#ifdef CONFIG_PEERKEY -#define RSN_KEY_DATA_SMK RSN_SELECTOR(0x00, 0x0f, 0xac, 5) -#define RSN_KEY_DATA_NONCE RSN_SELECTOR(0x00, 0x0f, 0xac, 6) -#define RSN_KEY_DATA_LIFETIME RSN_SELECTOR(0x00, 0x0f, 0xac, 7) -#define RSN_KEY_DATA_ERROR RSN_SELECTOR(0x00, 0x0f, 0xac, 8) -#endif /* CONFIG_PEERKEY */ #ifdef CONFIG_IEEE80211W #define RSN_KEY_DATA_IGTK RSN_SELECTOR(0x00, 0x0f, 0xac, 9) #endif /* CONFIG_IEEE80211W */ #define RSN_KEY_DATA_KEYID RSN_SELECTOR(0x00, 0x0f, 0xac, 10) #define RSN_KEY_DATA_MULTIBAND_GTK RSN_SELECTOR(0x00, 0x0f, 0xac, 11) #define RSN_KEY_DATA_MULTIBAND_KEYID RSN_SELECTOR(0x00, 0x0f, 0xac, 12) +#define RSN_KEY_DATA_OCI RSN_SELECTOR(0x00, 0x0f, 0xac, 13) #define WFA_KEY_DATA_IP_ADDR_REQ RSN_SELECTOR(0x50, 0x6f, 0x9a, 4) #define WFA_KEY_DATA_IP_ADDR_ALLOC RSN_SELECTOR(0x50, 0x6f, 0x9a, 5) @@ -138,7 +149,8 @@ RSN_SELECTOR(0x00, 0x0f, 0xac, 13) #define WPA_CAPABILITY_SPP_A_MSDU_REQUIRED BIT(11) #define WPA_CAPABILITY_PBAC BIT(12) #define WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST BIT(13) -/* B14-B15: Reserved */ +#define WPA_CAPABILITY_OCVC BIT(14) +/* B15: Reserved */ /* IEEE 802.11r */ @@ -179,30 +191,17 @@ struct wpa_eapol_key { u8 key_iv[16]; u8 key_rsc[WPA_KEY_RSC_LEN]; u8 key_id[8]; /* Reserved in IEEE 802.11i/RSN */ - u8 key_mic[16]; - u8 key_data_length[2]; /* big endian */ - /* followed by key_data_length bytes of key_data */ -} STRUCT_PACKED; - -struct wpa_eapol_key_192 { - u8 type; - /* Note: key_info, key_length, and key_data_length are unaligned */ - u8 key_info[2]; /* big endian */ - u8 key_length[2]; /* big endian */ - u8 replay_counter[WPA_REPLAY_COUNTER_LEN]; - u8 key_nonce[WPA_NONCE_LEN]; - u8 key_iv[16]; - u8 key_rsc[WPA_KEY_RSC_LEN]; - u8 key_id[8]; /* Reserved in IEEE 802.11i/RSN */ - u8 key_mic[24]; - u8 key_data_length[2]; /* big endian */ - /* followed by key_data_length bytes of key_data */ + /* variable length Key MIC field */ + /* big endian 2-octet Key Data Length field */ + /* followed by Key Data Length bytes of Key Data */ } STRUCT_PACKED; -#define WPA_EAPOL_KEY_MIC_MAX_LEN 24 -#define WPA_KCK_MAX_LEN 24 -#define WPA_KEK_MAX_LEN 32 +#define WPA_EAPOL_KEY_MIC_MAX_LEN 32 +#define WPA_KCK_MAX_LEN 32 +#define WPA_KEK_MAX_LEN 64 #define WPA_TK_MAX_LEN 32 +#define FILS_ICK_MAX_LEN 48 +#define FILS_FT_MAX_LEN 48 /** * struct wpa_ptk - WPA Pairwise Transient Key @@ -212,9 +211,13 @@ struct wpa_ptk { u8 kck[WPA_KCK_MAX_LEN]; /* EAPOL-Key Key Confirmation Key (KCK) */ u8 kek[WPA_KEK_MAX_LEN]; /* EAPOL-Key Key Encryption Key (KEK) */ u8 tk[WPA_TK_MAX_LEN]; /* Temporal Key (TK) */ + u8 kck2[WPA_KCK_MAX_LEN]; /* FT reasoc Key Confirmation Key (KCK2) */ + u8 kek2[WPA_KEK_MAX_LEN]; /* FT reassoc Key Encryption Key (KEK2) */ size_t kck_len; size_t kek_len; size_t tk_len; + size_t kck2_len; + size_t kek2_len; int installed; /* 1 if key has already been installed to driver */ }; @@ -283,22 +286,6 @@ struct rsn_ie_hdr { } STRUCT_PACKED; -#ifdef CONFIG_PEERKEY -enum { - STK_MUI_4WAY_STA_AP = 1, - STK_MUI_4WAY_STAT_STA = 2, - STK_MUI_GTK = 3, - STK_MUI_SMK = 4 -}; - -enum { - STK_ERR_STA_NR = 1, - STK_ERR_STA_NRSN = 2, - STK_ERR_CPHR_NS = 3, - STK_ERR_NO_STSL = 4 -}; -#endif /* CONFIG_PEERKEY */ - struct rsn_error_kde { be16 mui; be16 error_type; @@ -329,10 +316,19 @@ struct rsn_ftie { /* followed by optional parameters */ } STRUCT_PACKED; +struct rsn_ftie_sha384 { + u8 mic_control[2]; + u8 mic[24]; + u8 anonce[WPA_NONCE_LEN]; + u8 snonce[WPA_NONCE_LEN]; + /* followed by optional parameters */ +} STRUCT_PACKED; + #define FTIE_SUBELEM_R1KH_ID 1 #define FTIE_SUBELEM_GTK 2 #define FTIE_SUBELEM_R0KH_ID 3 #define FTIE_SUBELEM_IGTK 4 +#define FTIE_SUBELEM_OCI 5 struct rsn_rdie { u8 id; @@ -351,7 +347,24 @@ int wpa_eapol_key_mic(const u8 *key, size_t key_len, int akmp, int ver, int wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label, const u8 *addr1, const u8 *addr2, const u8 *nonce1, const u8 *nonce2, - struct wpa_ptk *ptk, int akmp, int cipher); + struct wpa_ptk *ptk, int akmp, int cipher, + const u8 *z, size_t z_len); +int fils_rmsk_to_pmk(int akmp, const u8 *rmsk, size_t rmsk_len, + const u8 *snonce, const u8 *anonce, const u8 *dh_ss, + size_t dh_ss_len, u8 *pmk, size_t *pmk_len); +int fils_pmkid_erp(int akmp, const u8 *reauth, size_t reauth_len, + u8 *pmkid); +int fils_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const u8 *spa, const u8 *aa, + const u8 *snonce, const u8 *anonce, const u8 *dhss, + size_t dhss_len, struct wpa_ptk *ptk, + u8 *ick, size_t *ick_len, int akmp, int cipher, + u8 *fils_ft, size_t *fils_ft_len); +int fils_key_auth_sk(const u8 *ick, size_t ick_len, const u8 *snonce, + const u8 *anonce, const u8 *sta_addr, const u8 *bssid, + const u8 *g_sta, size_t g_sta_len, + const u8 *g_ap, size_t g_ap_len, + int akmp, u8 *key_auth_sta, u8 *key_auth_ap, + size_t *key_auth_len); #ifdef CONFIG_IEEE80211R int wpa_ft_mic(const u8 *kck, size_t kck_len, const u8 *sta_addr, @@ -360,17 +373,19 @@ int wpa_ft_mic(const u8 *kck, size_t kck_len, const u8 *sta_addr, const u8 *ftie, size_t ftie_len, const u8 *rsnie, size_t rsnie_len, const u8 *ric, size_t ric_len, u8 *mic); -void wpa_derive_pmk_r0(const u8 *xxkey, size_t xxkey_len, - const u8 *ssid, size_t ssid_len, - const u8 *mdid, const u8 *r0kh_id, size_t r0kh_id_len, - const u8 *s0kh_id, u8 *pmk_r0, u8 *pmk_r0_name); -void wpa_derive_pmk_r1_name(const u8 *pmk_r0_name, const u8 *r1kh_id, - const u8 *s1kh_id, u8 *pmk_r1_name); -void wpa_derive_pmk_r1(const u8 *pmk_r0, const u8 *pmk_r0_name, - const u8 *r1kh_id, const u8 *s1kh_id, - u8 *pmk_r1, u8 *pmk_r1_name); -int wpa_pmk_r1_to_ptk(const u8 *pmk_r1, const u8 *snonce, const u8 *anonce, - const u8 *sta_addr, const u8 *bssid, +int wpa_derive_pmk_r0(const u8 *xxkey, size_t xxkey_len, + const u8 *ssid, size_t ssid_len, + const u8 *mdid, const u8 *r0kh_id, size_t r0kh_id_len, + const u8 *s0kh_id, u8 *pmk_r0, u8 *pmk_r0_name, + int use_sha384); +int wpa_derive_pmk_r1_name(const u8 *pmk_r0_name, const u8 *r1kh_id, + const u8 *s1kh_id, u8 *pmk_r1_name, int use_sha384); +int wpa_derive_pmk_r1(const u8 *pmk_r0, size_t pmk_r0_len, + const u8 *pmk_r0_name, + const u8 *r1kh_id, const u8 *s1kh_id, + u8 *pmk_r1, u8 *pmk_r1_name); +int wpa_pmk_r1_to_ptk(const u8 *pmk_r1, size_t pmk_r1_len, const u8 *snonce, + const u8 *anonce, const u8 *sta_addr, const u8 *bssid, const u8 *pmk_r1_name, struct wpa_ptk *ptk, u8 *ptk_name, int akmp, int cipher); #endif /* CONFIG_IEEE80211R */ @@ -378,7 +393,9 @@ int wpa_pmk_r1_to_ptk(const u8 *pmk_r1, const u8 *snonce, const u8 *anonce, struct wpa_ie_data { int proto; int pairwise_cipher; + int has_pairwise; int group_cipher; + int has_group; int key_mgmt; int capabilities; size_t num_pmkid; @@ -391,9 +408,10 @@ int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len, struct wpa_ie_data *data); int wpa_parse_wpa_ie_wpa(const u8 *wpa_ie, size_t wpa_ie_len, struct wpa_ie_data *data); +int wpa_default_rsn_cipher(int freq); void rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa, const u8 *spa, - u8 *pmkid, int use_sha256); + u8 *pmkid, int akmp); #ifdef CONFIG_SUITEB int rsn_pmkid_suite_b(const u8 *kck, size_t kck_len, const u8 *aa, const u8 *spa, u8 *pmkid); @@ -440,15 +458,22 @@ struct wpa_ft_ies { size_t tie_len; const u8 *igtk; size_t igtk_len; +#ifdef CONFIG_OCV + const u8 *oci; + size_t oci_len; +#endif /* CONFIG_OCV */ const u8 *ric; size_t ric_len; + int key_mgmt; + int pairwise_cipher; }; -int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, struct wpa_ft_ies *parse); +int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, struct wpa_ft_ies *parse, + int use_sha384); int wpa_cipher_key_len(int cipher); int wpa_cipher_rsc_len(int cipher); -int wpa_cipher_to_alg(int cipher); +enum wpa_alg wpa_cipher_to_alg(int cipher); int wpa_cipher_valid_group(int cipher); int wpa_cipher_valid_pairwise(int cipher); int wpa_cipher_valid_mgmt_group(int cipher); @@ -460,6 +485,10 @@ int wpa_pick_group_cipher(int ciphers); int wpa_parse_cipher(const char *value); int wpa_write_ciphers(char *start, char *end, int ciphers, const char *delim); int wpa_select_ap_group_cipher(int wpa, int wpa_pairwise, int rsn_pairwise); -unsigned int wpa_mic_len(int akmp); +unsigned int wpa_mic_len(int akmp, size_t pmk_len); +int wpa_use_akm_defined(int akmp); +int wpa_use_cmac(int akmp); +int wpa_use_aes_key_wrap(int akmp); +int fils_domain_name_hash(const char *domain, u8 *hash); #endif /* WPA_COMMON_H */ diff --git a/freebsd/contrib/wpa/src/common/wpa_ctrl.h b/freebsd/contrib/wpa/src/common/wpa_ctrl.h index 4dcba81d..f65077e0 100644 --- a/freebsd/contrib/wpa/src/common/wpa_ctrl.h +++ b/freebsd/contrib/wpa/src/common/wpa_ctrl.h @@ -1,6 +1,6 @@ /* * wpa_supplicant/hostapd control interface library - * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> + * Copyright (c) 2004-2017, Jouni Malinen <j@w1.fi> * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -50,10 +50,19 @@ extern "C" { #define WPA_EVENT_EAP_TLS_CERT_ERROR "CTRL-EVENT-EAP-TLS-CERT-ERROR " /** EAP status */ #define WPA_EVENT_EAP_STATUS "CTRL-EVENT-EAP-STATUS " +/** Retransmit the previous request packet */ +#define WPA_EVENT_EAP_RETRANSMIT "CTRL-EVENT-EAP-RETRANSMIT " +#define WPA_EVENT_EAP_RETRANSMIT2 "CTRL-EVENT-EAP-RETRANSMIT2 " /** EAP authentication completed successfully */ #define WPA_EVENT_EAP_SUCCESS "CTRL-EVENT-EAP-SUCCESS " +#define WPA_EVENT_EAP_SUCCESS2 "CTRL-EVENT-EAP-SUCCESS2 " /** EAP authentication failed (EAP-Failure received) */ #define WPA_EVENT_EAP_FAILURE "CTRL-EVENT-EAP-FAILURE " +#define WPA_EVENT_EAP_FAILURE2 "CTRL-EVENT-EAP-FAILURE2 " +/** EAP authentication failed due to no response received */ +#define WPA_EVENT_EAP_TIMEOUT_FAILURE "CTRL-EVENT-EAP-TIMEOUT-FAILURE " +#define WPA_EVENT_EAP_TIMEOUT_FAILURE2 "CTRL-EVENT-EAP-TIMEOUT-FAILURE2 " +#define WPA_EVENT_EAP_ERROR_CODE "EAP-ERROR-CODE " /** Network block temporarily disabled (e.g., due to authentication failure) */ #define WPA_EVENT_TEMP_DISABLED "CTRL-EVENT-SSID-TEMP-DISABLED " /** Temporarily disabled network block re-enabled */ @@ -74,10 +83,15 @@ extern "C" { #define WPA_EVENT_NETWORK_NOT_FOUND "CTRL-EVENT-NETWORK-NOT-FOUND " /** Change in the signal level was reported by the driver */ #define WPA_EVENT_SIGNAL_CHANGE "CTRL-EVENT-SIGNAL-CHANGE " +/** Beacon loss reported by the driver */ +#define WPA_EVENT_BEACON_LOSS "CTRL-EVENT-BEACON-LOSS " /** Regulatory domain channel */ #define WPA_EVENT_REGDOM_CHANGE "CTRL-EVENT-REGDOM-CHANGE " /** Channel switch (followed by freq=<MHz> and other channel parameters) */ #define WPA_EVENT_CHANNEL_SWITCH "CTRL-EVENT-CHANNEL-SWITCH " +/** SAE authentication failed due to unknown password identifier */ +#define WPA_EVENT_SAE_UNKNOWN_PASSWORD_IDENTIFIER \ + "CTRL-EVENT-SAE-UNKNOWN-PASSWORD-IDENTIFIER " /** IP subnet status change notification * @@ -141,6 +155,33 @@ extern "C" { #define WPS_EVENT_ER_AP_SETTINGS "WPS-ER-AP-SETTINGS " #define WPS_EVENT_ER_SET_SEL_REG "WPS-ER-AP-SET-SEL-REG " +/* DPP events */ +#define DPP_EVENT_AUTH_SUCCESS "DPP-AUTH-SUCCESS " +#define DPP_EVENT_AUTH_INIT_FAILED "DPP-AUTH-INIT-FAILED " +#define DPP_EVENT_NOT_COMPATIBLE "DPP-NOT-COMPATIBLE " +#define DPP_EVENT_RESPONSE_PENDING "DPP-RESPONSE-PENDING " +#define DPP_EVENT_SCAN_PEER_QR_CODE "DPP-SCAN-PEER-QR-CODE " +#define DPP_EVENT_AUTH_DIRECTION "DPP-AUTH-DIRECTION " +#define DPP_EVENT_CONF_RECEIVED "DPP-CONF-RECEIVED " +#define DPP_EVENT_CONF_SENT "DPP-CONF-SENT " +#define DPP_EVENT_CONF_FAILED "DPP-CONF-FAILED " +#define DPP_EVENT_CONFOBJ_AKM "DPP-CONFOBJ-AKM " +#define DPP_EVENT_CONFOBJ_SSID "DPP-CONFOBJ-SSID " +#define DPP_EVENT_CONFOBJ_PASS "DPP-CONFOBJ-PASS " +#define DPP_EVENT_CONFOBJ_PSK "DPP-CONFOBJ-PSK " +#define DPP_EVENT_CONNECTOR "DPP-CONNECTOR " +#define DPP_EVENT_C_SIGN_KEY "DPP-C-SIGN-KEY " +#define DPP_EVENT_NET_ACCESS_KEY "DPP-NET-ACCESS-KEY " +#define DPP_EVENT_MISSING_CONNECTOR "DPP-MISSING-CONNECTOR " +#define DPP_EVENT_NETWORK_ID "DPP-NETWORK-ID " +#define DPP_EVENT_RX "DPP-RX " +#define DPP_EVENT_TX "DPP-TX " +#define DPP_EVENT_TX_STATUS "DPP-TX-STATUS " +#define DPP_EVENT_FAIL "DPP-FAIL " +#define DPP_EVENT_PKEX_T_LIMIT "DPP-PKEX-T-LIMIT " +#define DPP_EVENT_INTRO "DPP-INTRO " +#define DPP_EVENT_CONF_REQ_RX "DPP-CONF-REQ-RX " + /* MESH events */ #define MESH_GROUP_STARTED "MESH-GROUP-STARTED " #define MESH_GROUP_REMOVED "MESH-GROUP-REMOVED " @@ -232,9 +273,14 @@ extern "C" { #define RX_HS20_ANQP "RX-HS20-ANQP " #define RX_HS20_ANQP_ICON "RX-HS20-ANQP-ICON " #define RX_HS20_ICON "RX-HS20-ICON " +#define RX_MBO_ANQP "RX-MBO-ANQP " + +/* parameters: <Venue Number> <Venue URL> */ +#define RX_VENUE_URL "RX-VENUE-URL " #define HS20_SUBSCRIPTION_REMEDIATION "HS20-SUBSCRIPTION-REMEDIATION " #define HS20_DEAUTH_IMMINENT_NOTICE "HS20-DEAUTH-IMMINENT-NOTICE " +#define HS20_T_C_ACCEPTANCE "HS20-T-C-ACCEPTANCE " #define EXT_RADIO_WORK_START "EXT-RADIO-WORK-START " #define EXT_RADIO_WORK_TIMEOUT "EXT-RADIO-WORK-TIMEOUT " @@ -258,6 +304,9 @@ extern "C" { #define AP_REJECTED_MAX_STA "AP-REJECTED-MAX-STA " #define AP_REJECTED_BLOCKED_STA "AP-REJECTED-BLOCKED-STA " +#define HS20_T_C_FILTERING_ADD "HS20-T-C-FILTERING-ADD " +#define HS20_T_C_FILTERING_REMOVE "HS20-T-C-FILTERING-REMOVE " + #define AP_EVENT_ENABLED "AP-ENABLED " #define AP_EVENT_DISABLED "AP-DISABLED " @@ -273,6 +322,7 @@ extern "C" { #define DFS_EVENT_CAC_START "DFS-CAC-START " #define DFS_EVENT_CAC_COMPLETED "DFS-CAC-COMPLETED " #define DFS_EVENT_NOP_FINISHED "DFS-NOP-FINISHED " +#define DFS_EVENT_PRE_CAC_EXPIRED "DFS-PRE-CAC-EXPIRED " #define AP_CSA_FINISHED "AP-CSA-FINISHED " @@ -282,12 +332,46 @@ extern "C" { /* BSS Transition Management Response frame received */ #define BSS_TM_RESP "BSS-TM-RESP " +/* Collocated Interference Request frame received; + * parameters: <dialog token> <automatic report enabled> <report timeout> */ +#define COLOC_INTF_REQ "COLOC-INTF-REQ " +/* Collocated Interference Report frame received; + * parameters: <STA address> <dialog token> <hexdump of report elements> */ +#define COLOC_INTF_REPORT "COLOC-INTF-REPORT " + /* MBO IE with cellular data connection preference received */ #define MBO_CELL_PREFERENCE "MBO-CELL-PREFERENCE " /* BSS Transition Management Request received with MBO transition reason */ #define MBO_TRANSITION_REASON "MBO-TRANSITION-REASON " +/* parameters: <STA address> <dialog token> <ack=0/1> */ +#define BEACON_REQ_TX_STATUS "BEACON-REQ-TX-STATUS " +/* parameters: <STA address> <dialog token> <report mode> <beacon report> */ +#define BEACON_RESP_RX "BEACON-RESP-RX " + +/* PMKSA cache entry added; parameters: <BSSID> <network_id> */ +#define PMKSA_CACHE_ADDED "PMKSA-CACHE-ADDED " +/* PMKSA cache entry removed; parameters: <BSSID> <network_id> */ +#define PMKSA_CACHE_REMOVED "PMKSA-CACHE-REMOVED " + +/* FILS HLP Container receive; parameters: dst=<addr> src=<addr> frame=<hexdump> + */ +#define FILS_HLP_RX "FILS-HLP-RX " + +/* Event to indicate Probe Request frame; + * parameters: sa=<STA MAC address> signal=<signal> */ +#define RX_PROBE_REQUEST "RX-PROBE-REQUEST " + +/* Event to indicate station's HT/VHT operation mode change information */ +#define STA_OPMODE_MAX_BW_CHANGED "STA-OPMODE-MAX-BW-CHANGED " +#define STA_OPMODE_SMPS_MODE_CHANGED "STA-OPMODE-SMPS-MODE-CHANGED " +#define STA_OPMODE_N_SS_CHANGED "STA-OPMODE-N_SS-CHANGED " + +/* New interface addition or removal for 4addr WDS SDA */ +#define WDS_STA_INTERFACE_ADDED "WDS-STA-INTERFACE-ADDED " +#define WDS_STA_INTERFACE_REMOVED "WDS-STA-INTERFACE-REMOVED " + /* BSS command information masks */ #define WPA_BSS_MASK_ALL 0xFFFDFFFF @@ -313,6 +397,9 @@ extern "C" { #define WPA_BSS_MASK_SNR BIT(19) #define WPA_BSS_MASK_EST_THROUGHPUT BIT(20) #define WPA_BSS_MASK_FST BIT(21) +#define WPA_BSS_MASK_UPDATE_IDX BIT(22) +#define WPA_BSS_MASK_BEACON_IE BIT(23) +#define WPA_BSS_MASK_FILS_INDICATION BIT(24) /* VENDOR_ELEM_* frame id values */ @@ -386,7 +473,7 @@ void wpa_ctrl_close(struct wpa_ctrl *ctrl); * * This function is used to send commands to wpa_supplicant/hostapd. Received * response will be written to reply and reply_len is set to the actual length - * of the reply. This function will block for up to two seconds while waiting + * of the reply. This function will block for up to 10 seconds while waiting * for the reply. If unsolicited messages are received, the blocking time may * be longer. * diff --git a/freebsd/contrib/wpa/src/crypto/aes-ctr.c b/freebsd/contrib/wpa/src/crypto/aes-ctr.c index f92be022..0e6a3e21 100644 --- a/freebsd/contrib/wpa/src/crypto/aes-ctr.c +++ b/freebsd/contrib/wpa/src/crypto/aes-ctr.c @@ -1,7 +1,7 @@ #include <machine/rtems-bsd-user-space.h> /* - * AES-128 CTR + * AES-128/192/256 CTR * * Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi> * @@ -16,15 +16,16 @@ #include "aes_wrap.h" /** - * aes_128_ctr_encrypt - AES-128 CTR mode encryption - * @key: Key for encryption (16 bytes) + * aes_ctr_encrypt - AES-128/192/256 CTR mode encryption + * @key: Key for encryption (key_len bytes) + * @key_len: Length of the key (16, 24, or 32 bytes) * @nonce: Nonce for counter mode (16 bytes) * @data: Data to encrypt in-place * @data_len: Length of data in bytes * Returns: 0 on success, -1 on failure */ -int aes_128_ctr_encrypt(const u8 *key, const u8 *nonce, - u8 *data, size_t data_len) +int aes_ctr_encrypt(const u8 *key, size_t key_len, const u8 *nonce, + u8 *data, size_t data_len) { void *ctx; size_t j, len, left = data_len; @@ -32,7 +33,7 @@ int aes_128_ctr_encrypt(const u8 *key, const u8 *nonce, u8 *pos = data; u8 counter[AES_BLOCK_SIZE], buf[AES_BLOCK_SIZE]; - ctx = aes_encrypt_init(key, 16); + ctx = aes_encrypt_init(key, key_len); if (ctx == NULL) return -1; os_memcpy(counter, nonce, AES_BLOCK_SIZE); @@ -55,3 +56,18 @@ int aes_128_ctr_encrypt(const u8 *key, const u8 *nonce, aes_encrypt_deinit(ctx); return 0; } + + +/** + * aes_128_ctr_encrypt - AES-128 CTR mode encryption + * @key: Key for encryption (key_len bytes) + * @nonce: Nonce for counter mode (16 bytes) + * @data: Data to encrypt in-place + * @data_len: Length of data in bytes + * Returns: 0 on success, -1 on failure + */ +int aes_128_ctr_encrypt(const u8 *key, const u8 *nonce, + u8 *data, size_t data_len) +{ + return aes_ctr_encrypt(key, 16, nonce, data, data_len); +} diff --git a/freebsd/contrib/wpa/src/crypto/aes.h b/freebsd/contrib/wpa/src/crypto/aes.h index 2de59e04..8ab3de2e 100644 --- a/freebsd/contrib/wpa/src/crypto/aes.h +++ b/freebsd/contrib/wpa/src/crypto/aes.h @@ -12,10 +12,10 @@ #define AES_BLOCK_SIZE 16 void * aes_encrypt_init(const u8 *key, size_t len); -void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt); +int aes_encrypt(void *ctx, const u8 *plain, u8 *crypt); void aes_encrypt_deinit(void *ctx); void * aes_decrypt_init(const u8 *key, size_t len); -void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain); +int aes_decrypt(void *ctx, const u8 *crypt, u8 *plain); void aes_decrypt_deinit(void *ctx); #endif /* AES_H */ diff --git a/freebsd/contrib/wpa/src/crypto/aes_siv.h b/freebsd/contrib/wpa/src/crypto/aes_siv.h new file mode 100644 index 00000000..fb05d80c --- /dev/null +++ b/freebsd/contrib/wpa/src/crypto/aes_siv.h @@ -0,0 +1,21 @@ +/* + * AES SIV (RFC 5297) + * Copyright (c) 2013 Cozybit, Inc. + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef AES_SIV_H +#define AES_SIV_H + +int aes_siv_encrypt(const u8 *key, size_t key_len, + const u8 *pw, size_t pwlen, + size_t num_elem, const u8 *addr[], const size_t *len, + u8 *out); +int aes_siv_decrypt(const u8 *key, size_t key_len, + const u8 *iv_crypt, size_t iv_c_len, + size_t num_elem, const u8 *addr[], const size_t *len, + u8 *out); + +#endif /* AES_SIV_H */ diff --git a/freebsd/contrib/wpa/src/crypto/aes_wrap.h b/freebsd/contrib/wpa/src/crypto/aes_wrap.h index 4a142093..b70b1d26 100644 --- a/freebsd/contrib/wpa/src/crypto/aes_wrap.h +++ b/freebsd/contrib/wpa/src/crypto/aes_wrap.h @@ -3,7 +3,7 @@ * * - AES Key Wrap Algorithm (RFC3394) * - One-Key CBC MAC (OMAC1) hash with AES-128 and AES-256 - * - AES-128 CTR mode encryption + * - AES-128/192/256 CTR mode encryption * - AES-128 EAX mode encryption/decryption * - AES-128 CBC * - AES-GCM @@ -33,6 +33,8 @@ int __must_check omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, int __must_check omac1_aes_256(const u8 *key, const u8 *data, size_t data_len, u8 *mac); int __must_check aes_128_encrypt_block(const u8 *key, const u8 *in, u8 *out); +int __must_check aes_ctr_encrypt(const u8 *key, size_t key_len, const u8 *nonce, + u8 *data, size_t data_len); int __must_check aes_128_ctr_encrypt(const u8 *key, const u8 *nonce, u8 *data, size_t data_len); int __must_check aes_128_eax_encrypt(const u8 *key, diff --git a/freebsd/contrib/wpa/src/crypto/crypto.h b/freebsd/contrib/wpa/src/crypto/crypto.h index bdc3ba6f..12109ce8 100644 --- a/freebsd/contrib/wpa/src/crypto/crypto.h +++ b/freebsd/contrib/wpa/src/crypto/crypto.h @@ -1,6 +1,6 @@ /* * Wrapper functions for crypto libraries - * Copyright (c) 2004-2013, Jouni Malinen <j@w1.fi> + * Copyright (c) 2004-2017, Jouni Malinen <j@w1.fi> * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -106,8 +106,9 @@ int sha512_vector(size_t num_elem, const u8 *addr[], const size_t *len, * @clear: 8 octets (in) * @key: 7 octets (in) (no parity bits included) * @cypher: 8 octets (out) + * Returns: 0 on success, -1 on failure */ -void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher); +int des_encrypt(const u8 *clear, const u8 *key, u8 *cypher); /** * aes_encrypt_init - Initialize AES for encryption @@ -122,8 +123,9 @@ void * aes_encrypt_init(const u8 *key, size_t len); * @ctx: Context pointer from aes_encrypt_init() * @plain: Plaintext data to be encrypted (16 bytes) * @crypt: Buffer for the encrypted data (16 bytes) + * Returns: 0 on success, -1 on failure */ -void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt); +int aes_encrypt(void *ctx, const u8 *plain, u8 *crypt); /** * aes_encrypt_deinit - Deinitialize AES encryption @@ -144,8 +146,9 @@ void * aes_decrypt_init(const u8 *key, size_t len); * @ctx: Context pointer from aes_encrypt_init() * @crypt: Encrypted data (16 bytes) * @plain: Buffer for the decrypted data (16 bytes) + * Returns: 0 on success, -1 on failure */ -void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain); +int aes_decrypt(void *ctx, const u8 *crypt, u8 *plain); /** * aes_decrypt_deinit - Deinitialize AES decryption @@ -414,6 +417,14 @@ int __must_check crypto_public_key_decrypt_pkcs1( struct crypto_public_key *key, const u8 *crypt, size_t crypt_len, u8 *plain, size_t *plain_len); +int crypto_dh_init(u8 generator, const u8 *prime, size_t prime_len, u8 *privkey, + u8 *pubkey); +int crypto_dh_derive_secret(u8 generator, const u8 *prime, size_t prime_len, + const u8 *order, size_t order_len, + const u8 *privkey, size_t privkey_len, + const u8 *pubkey, size_t pubkey_len, + u8 *secret, size_t *len); + /** * crypto_global_init - Initialize crypto wrapper * @@ -526,6 +537,14 @@ int crypto_bignum_to_bin(const struct crypto_bignum *a, u8 *buf, size_t buflen, size_t padlen); /** + * crypto_bignum_rand - Create a random number in range of modulus + * @r: Bignum; set to a random value + * @m: Bignum; modulus + * Returns: 0 on success, -1 on failure + */ +int crypto_bignum_rand(struct crypto_bignum *r, const struct crypto_bignum *m); + +/** * crypto_bignum_add - c = a + b * @a: Bignum * @b: Bignum @@ -607,6 +626,16 @@ int crypto_bignum_mulmod(const struct crypto_bignum *a, struct crypto_bignum *d); /** + * crypto_bignum_rshift - r = a >> n + * @a: Bignum + * @n: Number of bits + * @r: Bignum; used to store the result of a >> n + * Returns: 0 on success, -1 on failure + */ +int crypto_bignum_rshift(const struct crypto_bignum *a, int n, + struct crypto_bignum *r); + +/** * crypto_bignum_cmp - Compare two bignums * @a: Bignum * @b: Bignum @@ -637,6 +666,13 @@ int crypto_bignum_is_zero(const struct crypto_bignum *a); int crypto_bignum_is_one(const struct crypto_bignum *a); /** + * crypto_bignum_is_odd - Is the given bignum odd + * @a: Bignum + * Returns: 1 if @a is odd or 0 if not + */ +int crypto_bignum_is_odd(const struct crypto_bignum *a); + +/** * crypto_bignum_legendre - Compute the Legendre symbol (a/p) * @a: Bignum * @p: Bignum @@ -682,6 +718,13 @@ size_t crypto_ec_prime_len(struct crypto_ec *e); size_t crypto_ec_prime_len_bits(struct crypto_ec *e); /** + * crypto_ec_order_len - Get length of the order in octets + * @e: EC context from crypto_ec_init() + * Returns: Length of the order defining the group + */ +size_t crypto_ec_order_len(struct crypto_ec *e); + +/** * crypto_ec_get_prime - Get prime defining an EC group * @e: EC context from crypto_ec_init() * Returns: Prime (bignum) defining the group @@ -718,6 +761,16 @@ struct crypto_ec_point * crypto_ec_point_init(struct crypto_ec *e); void crypto_ec_point_deinit(struct crypto_ec_point *p, int clear); /** + * crypto_ec_point_x - Copies the x-ordinate point into big number + * @e: EC context from crypto_ec_init() + * @p: EC point data + * @x: Big number to set to the copy of x-ordinate + * Returns: 0 on success, -1 on failure + */ +int crypto_ec_point_x(struct crypto_ec *e, const struct crypto_ec_point *p, + struct crypto_bignum *x); + +/** * crypto_ec_point_to_bin - Write EC point value as binary data * @e: EC context from crypto_ec_init() * @p: EC point data from crypto_ec_point_init() @@ -746,7 +799,7 @@ struct crypto_ec_point * crypto_ec_point_from_bin(struct crypto_ec *e, const u8 *val); /** - * crypto_bignum_add - c = a + b + * crypto_ec_point_add - c = a + b * @e: EC context from crypto_ec_init() * @a: Bignum * @b: Bignum @@ -758,7 +811,7 @@ int crypto_ec_point_add(struct crypto_ec *e, const struct crypto_ec_point *a, struct crypto_ec_point *c); /** - * crypto_bignum_mul - res = b * p + * crypto_ec_point_mul - res = b * p * @e: EC context from crypto_ec_init() * @p: EC point * @b: Bignum @@ -829,4 +882,12 @@ int crypto_ec_point_cmp(const struct crypto_ec *e, const struct crypto_ec_point *a, const struct crypto_ec_point *b); +struct crypto_ecdh; + +struct crypto_ecdh * crypto_ecdh_init(int group); +struct wpabuf * crypto_ecdh_get_pubkey(struct crypto_ecdh *ecdh, int inc_y); +struct wpabuf * crypto_ecdh_set_peerkey(struct crypto_ecdh *ecdh, int inc_y, + const u8 *key, size_t len); +void crypto_ecdh_deinit(struct crypto_ecdh *ecdh); + #endif /* CRYPTO_H */ diff --git a/freebsd/contrib/wpa/src/crypto/crypto_openssl.c b/freebsd/contrib/wpa/src/crypto/crypto_openssl.c index ee4d55eb..5b4c41a9 100644 --- a/freebsd/contrib/wpa/src/crypto/crypto_openssl.c +++ b/freebsd/contrib/wpa/src/crypto/crypto_openssl.c @@ -2,7 +2,7 @@ /* * Wrapper functions for OpenSSL libcrypto - * Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi> + * Copyright (c) 2004-2017, Jouni Malinen <j@w1.fi> * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -26,16 +26,20 @@ #endif /* CONFIG_ECC */ #include "common.h" +#include "utils/const_time.h" #include "wpabuf.h" #include "dh_group5.h" #include "sha1.h" #include "sha256.h" #include "sha384.h" +#include "sha512.h" #include "md5.h" #include "aes_wrap.h" #include "crypto.h" -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) +#if OPENSSL_VERSION_NUMBER < 0x10100000L || \ + (defined(LIBRESSL_VERSION_NUMBER) && \ + LIBRESSL_VERSION_NUMBER < 0x20700000L) /* Compatibility wrappers for older versions. */ static HMAC_CTX * HMAC_CTX_new(void) @@ -81,7 +85,9 @@ static void EVP_MD_CTX_free(EVP_MD_CTX *ctx) static BIGNUM * get_group5_prime(void) { -#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) +#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \ + !(defined(LIBRESSL_VERSION_NUMBER) && \ + LIBRESSL_VERSION_NUMBER < 0x20700000L) return BN_get_rfc3526_prime_1536(NULL); #elif !defined(OPENSSL_IS_BORINGSSL) return get_rfc3526_prime_1536(NULL); @@ -108,9 +114,37 @@ static BIGNUM * get_group5_prime(void) #endif } + +static BIGNUM * get_group5_order(void) +{ + static const unsigned char RFC3526_ORDER_1536[] = { + 0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE4,0x87,0xED,0x51, + 0x10,0xB4,0x61,0x1A,0x62,0x63,0x31,0x45,0xC0,0x6E,0x0E,0x68, + 0x94,0x81,0x27,0x04,0x45,0x33,0xE6,0x3A,0x01,0x05,0xDF,0x53, + 0x1D,0x89,0xCD,0x91,0x28,0xA5,0x04,0x3C,0xC7,0x1A,0x02,0x6E, + 0xF7,0xCA,0x8C,0xD9,0xE6,0x9D,0x21,0x8D,0x98,0x15,0x85,0x36, + 0xF9,0x2F,0x8A,0x1B,0xA7,0xF0,0x9A,0xB6,0xB6,0xA8,0xE1,0x22, + 0xF2,0x42,0xDA,0xBB,0x31,0x2F,0x3F,0x63,0x7A,0x26,0x21,0x74, + 0xD3,0x1B,0xF6,0xB5,0x85,0xFF,0xAE,0x5B,0x7A,0x03,0x5B,0xF6, + 0xF7,0x1C,0x35,0xFD,0xAD,0x44,0xCF,0xD2,0xD7,0x4F,0x92,0x08, + 0xBE,0x25,0x8F,0xF3,0x24,0x94,0x33,0x28,0xF6,0x72,0x2D,0x9E, + 0xE1,0x00,0x3E,0x5C,0x50,0xB1,0xDF,0x82,0xCC,0x6D,0x24,0x1B, + 0x0E,0x2A,0xE9,0xCD,0x34,0x8B,0x1F,0xD4,0x7E,0x92,0x67,0xAF, + 0xC1,0xB2,0xAE,0x91,0xEE,0x51,0xD6,0xCB,0x0E,0x31,0x79,0xAB, + 0x10,0x42,0xA9,0x5D,0xCF,0x6A,0x94,0x83,0xB8,0x4B,0x4B,0x36, + 0xB3,0x86,0x1A,0xA7,0x25,0x5E,0x4C,0x02,0x78,0xBA,0x36,0x04, + 0x65,0x11,0xB9,0x93,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF + }; + return BN_bin2bn(RFC3526_ORDER_1536, sizeof(RFC3526_ORDER_1536), NULL); +} + + #ifdef OPENSSL_NO_SHA256 #define NO_SHA256_WRAPPER #endif +#ifdef OPENSSL_NO_SHA512 +#define NO_SHA384_WRAPPER +#endif static int openssl_digest_vector(const EVP_MD *type, size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) @@ -160,7 +194,7 @@ int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) #endif /* CONFIG_FIPS */ -void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher) +int des_encrypt(const u8 *clear, const u8 *key, u8 *cypher) { u8 pkey[8], next, tmp; int i; @@ -178,6 +212,7 @@ void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher) DES_set_key((DES_cblock *) &pkey, &ks); DES_ecb_encrypt((DES_cblock *) clear, (DES_cblock *) cypher, &ks, DES_ENCRYPT); + return 0; } @@ -245,15 +280,31 @@ int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len, #endif /* NO_SHA256_WRAPPER */ +#ifndef NO_SHA384_WRAPPER +int sha384_vector(size_t num_elem, const u8 *addr[], const size_t *len, + u8 *mac) +{ + return openssl_digest_vector(EVP_sha384(), num_elem, addr, len, mac); +} +#endif /* NO_SHA384_WRAPPER */ + + +#ifndef NO_SHA512_WRAPPER +int sha512_vector(size_t num_elem, const u8 *addr[], const size_t *len, + u8 *mac) +{ + return openssl_digest_vector(EVP_sha512(), num_elem, addr, len, mac); +} +#endif /* NO_SHA512_WRAPPER */ + + static const EVP_CIPHER * aes_get_evp_cipher(size_t keylen) { switch (keylen) { case 16: return EVP_aes_128_ecb(); -#ifndef OPENSSL_IS_BORINGSSL case 24: return EVP_aes_192_ecb(); -#endif /* OPENSSL_IS_BORINGSSL */ case 32: return EVP_aes_256_ecb(); } @@ -271,8 +322,11 @@ void * aes_encrypt_init(const u8 *key, size_t len) return NULL; type = aes_get_evp_cipher(len); - if (type == NULL) + if (!type) { + wpa_printf(MSG_INFO, "%s: Unsupported len=%u", + __func__, (unsigned int) len); return NULL; + } ctx = EVP_CIPHER_CTX_new(); if (ctx == NULL) @@ -286,14 +340,16 @@ void * aes_encrypt_init(const u8 *key, size_t len) } -void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt) +int aes_encrypt(void *ctx, const u8 *plain, u8 *crypt) { EVP_CIPHER_CTX *c = ctx; int clen = 16; if (EVP_EncryptUpdate(c, crypt, &clen, plain, 16) != 1) { wpa_printf(MSG_ERROR, "OpenSSL: EVP_EncryptUpdate failed: %s", ERR_error_string(ERR_get_error(), NULL)); + return -1; } + return 0; } @@ -323,8 +379,11 @@ void * aes_decrypt_init(const u8 *key, size_t len) return NULL; type = aes_get_evp_cipher(len); - if (type == NULL) + if (!type) { + wpa_printf(MSG_INFO, "%s: Unsupported len=%u", + __func__, (unsigned int) len); return NULL; + } ctx = EVP_CIPHER_CTX_new(); if (ctx == NULL) @@ -338,14 +397,16 @@ void * aes_decrypt_init(const u8 *key, size_t len) } -void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain) +int aes_decrypt(void *ctx, const u8 *crypt, u8 *plain) { EVP_CIPHER_CTX *c = ctx; int plen = 16; if (EVP_DecryptUpdate(c, plain, &plen, crypt, 16) != 1) { wpa_printf(MSG_ERROR, "OpenSSL: EVP_DecryptUpdate failed: %s", ERR_error_string(ERR_get_error(), NULL)); + return -1; } + return 0; } @@ -374,6 +435,8 @@ int aes_wrap(const u8 *kek, size_t kek_len, int n, const u8 *plain, u8 *cipher) AES_KEY actx; int res; + if (TEST_FAIL()) + return -1; if (AES_set_encrypt_key(kek, kek_len << 3, &actx)) return -1; res = AES_wrap_key(&actx, NULL, cipher, plain, n * 8); @@ -388,6 +451,8 @@ int aes_unwrap(const u8 *kek, size_t kek_len, int n, const u8 *cipher, AES_KEY actx; int res; + if (TEST_FAIL()) + return -1; if (AES_set_decrypt_key(kek, kek_len << 3, &actx)) return -1; res = AES_unwrap_key(&actx, NULL, plain, cipher, (n + 1) * 8); @@ -454,6 +519,75 @@ int aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len) } +int crypto_dh_init(u8 generator, const u8 *prime, size_t prime_len, u8 *privkey, + u8 *pubkey) +{ + size_t pubkey_len, pad; + + if (os_get_random(privkey, prime_len) < 0) + return -1; + if (os_memcmp(privkey, prime, prime_len) > 0) { + /* Make sure private value is smaller than prime */ + privkey[0] = 0; + } + + pubkey_len = prime_len; + if (crypto_mod_exp(&generator, 1, privkey, prime_len, prime, prime_len, + pubkey, &pubkey_len) < 0) + return -1; + if (pubkey_len < prime_len) { + pad = prime_len - pubkey_len; + os_memmove(pubkey + pad, pubkey, pubkey_len); + os_memset(pubkey, 0, pad); + } + + return 0; +} + + +int crypto_dh_derive_secret(u8 generator, const u8 *prime, size_t prime_len, + const u8 *order, size_t order_len, + const u8 *privkey, size_t privkey_len, + const u8 *pubkey, size_t pubkey_len, + u8 *secret, size_t *len) +{ + BIGNUM *pub, *p; + int res = -1; + + pub = BN_bin2bn(pubkey, pubkey_len, NULL); + p = BN_bin2bn(prime, prime_len, NULL); + if (!pub || !p || BN_is_zero(pub) || BN_is_one(pub) || + BN_cmp(pub, p) >= 0) + goto fail; + + if (order) { + BN_CTX *ctx; + BIGNUM *q, *tmp; + int failed; + + /* verify: pubkey^q == 1 mod p */ + q = BN_bin2bn(order, order_len, NULL); + ctx = BN_CTX_new(); + tmp = BN_new(); + failed = !q || !ctx || !tmp || + !BN_mod_exp(tmp, pub, q, p, ctx) || + !BN_is_one(tmp); + BN_clear(q); + BN_clear(tmp); + BN_CTX_free(ctx); + if (failed) + goto fail; + } + + res = crypto_mod_exp(pubkey, pubkey_len, privkey, privkey_len, + prime, prime_len, secret, len); +fail: + BN_clear(pub); + BN_clear(p); + return res; +} + + int crypto_mod_exp(const u8 *base, size_t base_len, const u8 *power, size_t power_len, const u8 *modulus, size_t modulus_len, @@ -476,7 +610,8 @@ int crypto_mod_exp(const u8 *base, size_t base_len, bn_result == NULL) goto error; - if (BN_mod_exp(bn_result, bn_base, bn_exp, bn_modulus, ctx) != 1) + if (BN_mod_exp_mont_consttime(bn_result, bn_base, bn_exp, bn_modulus, + ctx, NULL) != 1) goto error; *result_len = BN_bn2bin(bn_result, result); @@ -613,7 +748,9 @@ void crypto_cipher_deinit(struct crypto_cipher *ctx) void * dh5_init(struct wpabuf **priv, struct wpabuf **publ) { -#if OPENSSL_VERSION_NUMBER < 0x10100000L +#if OPENSSL_VERSION_NUMBER < 0x10100000L || \ + (defined(LIBRESSL_VERSION_NUMBER) && \ + LIBRESSL_VERSION_NUMBER < 0x20700000L) DH *dh; struct wpabuf *pubkey = NULL, *privkey = NULL; size_t publen, privlen; @@ -634,6 +771,10 @@ void * dh5_init(struct wpabuf **priv, struct wpabuf **publ) if (dh->p == NULL) goto err; + dh->q = get_group5_order(); + if (!dh->q) + goto err; + if (DH_generate_key(dh) != 1) goto err; @@ -662,7 +803,7 @@ err: DH *dh; struct wpabuf *pubkey = NULL, *privkey = NULL; size_t publen, privlen; - BIGNUM *p = NULL, *g; + BIGNUM *p, *g, *q; const BIGNUM *priv_key = NULL, *pub_key = NULL; *priv = NULL; @@ -675,10 +816,12 @@ err: g = BN_new(); p = get_group5_prime(); - if (!g || BN_set_word(g, 2) != 1 || !p || - DH_set0_pqg(dh, p, NULL, g) != 1) + q = get_group5_order(); + if (!g || BN_set_word(g, 2) != 1 || !p || !q || + DH_set0_pqg(dh, p, q, g) != 1) goto err; p = NULL; + q = NULL; g = NULL; if (DH_generate_key(dh) != 1) @@ -703,6 +846,7 @@ err: err: BN_free(p); + BN_free(q); BN_free(g); wpabuf_clear_free(pubkey); wpabuf_clear_free(privkey); @@ -714,7 +858,9 @@ err: void * dh5_init_fixed(const struct wpabuf *priv, const struct wpabuf *publ) { -#if OPENSSL_VERSION_NUMBER < 0x10100000L +#if OPENSSL_VERSION_NUMBER < 0x10100000L || \ + (defined(LIBRESSL_VERSION_NUMBER) && \ + LIBRESSL_VERSION_NUMBER < 0x20700000L) DH *dh; dh = DH_new(); @@ -910,6 +1056,9 @@ int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len) HMAC_CTX_free(ctx->ctx); bin_clear_free(ctx, sizeof(*ctx)); + if (TEST_FAIL()) + return -1; + if (res == 1) { *len = mdlen; return 0; @@ -1018,7 +1167,7 @@ int hmac_sha384_vector(const u8 *key, size_t key_len, size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { return openssl_hmac_vector(EVP_sha384(), key, key_len, num_elem, addr, - len, mac, 32); + len, mac, 48); } @@ -1031,6 +1180,25 @@ int hmac_sha384(const u8 *key, size_t key_len, const u8 *data, #endif /* CONFIG_SHA384 */ +#ifdef CONFIG_SHA512 + +int hmac_sha512_vector(const u8 *key, size_t key_len, size_t num_elem, + const u8 *addr[], const size_t *len, u8 *mac) +{ + return openssl_hmac_vector(EVP_sha512(), key, key_len, num_elem, addr, + len, mac, 64); +} + + +int hmac_sha512(const u8 *key, size_t key_len, const u8 *data, + size_t data_len, u8 *mac) +{ + return hmac_sha512_vector(key, key_len, 1, &data, &data_len, mac); +} + +#endif /* CONFIG_SHA512 */ + + int crypto_get_random(void *buf, size_t len) { if (RAND_bytes(buf, len) != 1) @@ -1152,6 +1320,14 @@ int crypto_bignum_to_bin(const struct crypto_bignum *a, } +int crypto_bignum_rand(struct crypto_bignum *r, const struct crypto_bignum *m) +{ + if (TEST_FAIL()) + return -1; + return BN_rand_range((BIGNUM *) r, (const BIGNUM *) m) == 1 ? 0 : -1; +} + + int crypto_bignum_add(const struct crypto_bignum *a, const struct crypto_bignum *b, struct crypto_bignum *c) @@ -1193,8 +1369,9 @@ int crypto_bignum_exptmod(const struct crypto_bignum *a, bnctx = BN_CTX_new(); if (bnctx == NULL) return -1; - res = BN_mod_exp((BIGNUM *) d, (const BIGNUM *) a, (const BIGNUM *) b, - (const BIGNUM *) c, bnctx); + res = BN_mod_exp_mont_consttime((BIGNUM *) d, (const BIGNUM *) a, + (const BIGNUM *) b, (const BIGNUM *) c, + bnctx, NULL); BN_CTX_free(bnctx); return res ? 0 : -1; @@ -1213,6 +1390,11 @@ int crypto_bignum_inverse(const struct crypto_bignum *a, bnctx = BN_CTX_new(); if (bnctx == NULL) return -1; +#ifdef OPENSSL_IS_BORINGSSL + /* TODO: use BN_mod_inverse_blinded() ? */ +#else /* OPENSSL_IS_BORINGSSL */ + BN_set_flags((BIGNUM *) a, BN_FLG_CONSTTIME); +#endif /* OPENSSL_IS_BORINGSSL */ res = BN_mod_inverse((BIGNUM *) c, (const BIGNUM *) a, (const BIGNUM *) b, bnctx); BN_CTX_free(bnctx); @@ -1246,6 +1428,9 @@ int crypto_bignum_div(const struct crypto_bignum *a, bnctx = BN_CTX_new(); if (bnctx == NULL) return -1; +#ifndef OPENSSL_IS_BORINGSSL + BN_set_flags((BIGNUM *) a, BN_FLG_CONSTTIME); +#endif /* OPENSSL_IS_BORINGSSL */ res = BN_div((BIGNUM *) c, NULL, (const BIGNUM *) a, (const BIGNUM *) b, bnctx); BN_CTX_free(bnctx); @@ -1277,6 +1462,15 @@ int crypto_bignum_mulmod(const struct crypto_bignum *a, } +int crypto_bignum_rshift(const struct crypto_bignum *a, int n, + struct crypto_bignum *r) +{ + /* Note: BN_rshift() does not modify the first argument even though it + * has not been marked const. */ + return BN_rshift((BIGNUM *) a, (BIGNUM *) r, n) == 1 ? 0 : -1; +} + + int crypto_bignum_cmp(const struct crypto_bignum *a, const struct crypto_bignum *b) { @@ -1302,12 +1496,19 @@ int crypto_bignum_is_one(const struct crypto_bignum *a) } +int crypto_bignum_is_odd(const struct crypto_bignum *a) +{ + return BN_is_odd((const BIGNUM *) a); +} + + int crypto_bignum_legendre(const struct crypto_bignum *a, const struct crypto_bignum *p) { BN_CTX *bnctx; BIGNUM *exp = NULL, *tmp = NULL; int res = -2; + unsigned int mask; if (TEST_FAIL()) return -2; @@ -1322,16 +1523,17 @@ int crypto_bignum_legendre(const struct crypto_bignum *a, /* exp = (p-1) / 2 */ !BN_sub(exp, (const BIGNUM *) p, BN_value_one()) || !BN_rshift1(exp, exp) || - !BN_mod_exp(tmp, (const BIGNUM *) a, exp, (const BIGNUM *) p, - bnctx)) + !BN_mod_exp_mont_consttime(tmp, (const BIGNUM *) a, exp, + (const BIGNUM *) p, bnctx, NULL)) goto fail; - if (BN_is_word(tmp, 1)) - res = 1; - else if (BN_is_zero(tmp)) - res = 0; - else - res = -1; + /* Return 1 if tmp == 1, 0 if tmp == 0, or -1 otherwise. Need to use + * constant time selection to avoid branches here. */ + res = -1; + mask = const_time_eq(BN_is_word(tmp, 1), 1); + res = const_time_select_int(mask, 1, res); + mask = const_time_eq(BN_is_zero(tmp), 1); + res = const_time_select_int(mask, 0, res); fail: BN_clear_free(tmp); @@ -1345,6 +1547,7 @@ fail: struct crypto_ec { EC_GROUP *group; + int nid; BN_CTX *bnctx; BIGNUM *prime; BIGNUM *order; @@ -1402,6 +1605,7 @@ struct crypto_ec * crypto_ec_init(int group) if (e == NULL) return NULL; + e->nid = nid; e->bnctx = BN_CTX_new(); e->group = EC_GROUP_new_by_curve_name(nid); e->prime = BN_new(); @@ -1456,6 +1660,12 @@ size_t crypto_ec_prime_len_bits(struct crypto_ec *e) } +size_t crypto_ec_order_len(struct crypto_ec *e) +{ + return BN_num_bytes(e->order); +} + + const struct crypto_bignum * crypto_ec_get_prime(struct crypto_ec *e) { return (const struct crypto_bignum *) e->prime; @@ -1477,6 +1687,16 @@ void crypto_ec_point_deinit(struct crypto_ec_point *p, int clear) } +int crypto_ec_point_x(struct crypto_ec *e, const struct crypto_ec_point *p, + struct crypto_bignum *x) +{ + return EC_POINT_get_affine_coordinates_GFp(e->group, + (const EC_POINT *) p, + (BIGNUM *) x, NULL, + e->bnctx) == 1 ? 0 : -1; +} + + int crypto_ec_point_to_bin(struct crypto_ec *e, const struct crypto_ec_point *point, u8 *x, u8 *y) { @@ -1642,4 +1862,228 @@ int crypto_ec_point_cmp(const struct crypto_ec *e, (const EC_POINT *) b, e->bnctx); } + +struct crypto_ecdh { + struct crypto_ec *ec; + EVP_PKEY *pkey; +}; + +struct crypto_ecdh * crypto_ecdh_init(int group) +{ + struct crypto_ecdh *ecdh; + EVP_PKEY *params = NULL; + EC_KEY *ec_params; + EVP_PKEY_CTX *kctx = NULL; + + ecdh = os_zalloc(sizeof(*ecdh)); + if (!ecdh) + goto fail; + + ecdh->ec = crypto_ec_init(group); + if (!ecdh->ec) + goto fail; + + ec_params = EC_KEY_new_by_curve_name(ecdh->ec->nid); + if (!ec_params) { + wpa_printf(MSG_ERROR, + "OpenSSL: Failed to generate EC_KEY parameters"); + goto fail; + } + EC_KEY_set_asn1_flag(ec_params, OPENSSL_EC_NAMED_CURVE); + params = EVP_PKEY_new(); + if (!params || EVP_PKEY_set1_EC_KEY(params, ec_params) != 1) { + wpa_printf(MSG_ERROR, + "OpenSSL: Failed to generate EVP_PKEY parameters"); + goto fail; + } + + kctx = EVP_PKEY_CTX_new(params, NULL); + if (!kctx) + goto fail; + + if (EVP_PKEY_keygen_init(kctx) != 1) { + wpa_printf(MSG_ERROR, + "OpenSSL: EVP_PKEY_keygen_init failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + + if (EVP_PKEY_keygen(kctx, &ecdh->pkey) != 1) { + wpa_printf(MSG_ERROR, "OpenSSL: EVP_PKEY_keygen failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + +done: + EVP_PKEY_free(params); + EVP_PKEY_CTX_free(kctx); + + return ecdh; +fail: + crypto_ecdh_deinit(ecdh); + ecdh = NULL; + goto done; +} + + +struct wpabuf * crypto_ecdh_get_pubkey(struct crypto_ecdh *ecdh, int inc_y) +{ + struct wpabuf *buf = NULL; + EC_KEY *eckey; + const EC_POINT *pubkey; + BIGNUM *x, *y = NULL; + int len = BN_num_bytes(ecdh->ec->prime); + int res; + + eckey = EVP_PKEY_get1_EC_KEY(ecdh->pkey); + if (!eckey) + return NULL; + + pubkey = EC_KEY_get0_public_key(eckey); + if (!pubkey) + return NULL; + + x = BN_new(); + if (inc_y) { + y = BN_new(); + if (!y) + goto fail; + } + buf = wpabuf_alloc(inc_y ? 2 * len : len); + if (!x || !buf) + goto fail; + + if (EC_POINT_get_affine_coordinates_GFp(ecdh->ec->group, pubkey, + x, y, ecdh->ec->bnctx) != 1) { + wpa_printf(MSG_ERROR, + "OpenSSL: EC_POINT_get_affine_coordinates_GFp failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + + res = crypto_bignum_to_bin((struct crypto_bignum *) x, + wpabuf_put(buf, len), len, len); + if (res < 0) + goto fail; + + if (inc_y) { + res = crypto_bignum_to_bin((struct crypto_bignum *) y, + wpabuf_put(buf, len), len, len); + if (res < 0) + goto fail; + } + +done: + BN_clear_free(x); + BN_clear_free(y); + EC_KEY_free(eckey); + + return buf; +fail: + wpabuf_free(buf); + buf = NULL; + goto done; +} + + +struct wpabuf * crypto_ecdh_set_peerkey(struct crypto_ecdh *ecdh, int inc_y, + const u8 *key, size_t len) +{ + BIGNUM *x, *y = NULL; + EVP_PKEY_CTX *ctx = NULL; + EVP_PKEY *peerkey = NULL; + struct wpabuf *secret = NULL; + size_t secret_len; + EC_POINT *pub; + EC_KEY *eckey = NULL; + + x = BN_bin2bn(key, inc_y ? len / 2 : len, NULL); + pub = EC_POINT_new(ecdh->ec->group); + if (!x || !pub) + goto fail; + + if (inc_y) { + y = BN_bin2bn(key + len / 2, len / 2, NULL); + if (!y) + goto fail; + if (!EC_POINT_set_affine_coordinates_GFp(ecdh->ec->group, pub, + x, y, + ecdh->ec->bnctx)) { + wpa_printf(MSG_ERROR, + "OpenSSL: EC_POINT_set_affine_coordinates_GFp failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + } else if (!EC_POINT_set_compressed_coordinates_GFp(ecdh->ec->group, + pub, x, 0, + ecdh->ec->bnctx)) { + wpa_printf(MSG_ERROR, + "OpenSSL: EC_POINT_set_compressed_coordinates_GFp failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + + if (!EC_POINT_is_on_curve(ecdh->ec->group, pub, ecdh->ec->bnctx)) { + wpa_printf(MSG_ERROR, + "OpenSSL: ECDH peer public key is not on curve"); + goto fail; + } + + eckey = EC_KEY_new_by_curve_name(ecdh->ec->nid); + if (!eckey || EC_KEY_set_public_key(eckey, pub) != 1) { + wpa_printf(MSG_ERROR, + "OpenSSL: EC_KEY_set_public_key failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + + peerkey = EVP_PKEY_new(); + if (!peerkey || EVP_PKEY_set1_EC_KEY(peerkey, eckey) != 1) + goto fail; + + ctx = EVP_PKEY_CTX_new(ecdh->pkey, NULL); + if (!ctx || EVP_PKEY_derive_init(ctx) != 1 || + EVP_PKEY_derive_set_peer(ctx, peerkey) != 1 || + EVP_PKEY_derive(ctx, NULL, &secret_len) != 1) { + wpa_printf(MSG_ERROR, + "OpenSSL: EVP_PKEY_derive(1) failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + + secret = wpabuf_alloc(secret_len); + if (!secret) + goto fail; + if (EVP_PKEY_derive(ctx, wpabuf_put(secret, secret_len), + &secret_len) != 1) { + wpa_printf(MSG_ERROR, + "OpenSSL: EVP_PKEY_derive(2) failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + +done: + BN_free(x); + BN_free(y); + EC_KEY_free(eckey); + EC_POINT_free(pub); + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(peerkey); + return secret; +fail: + wpabuf_free(secret); + secret = NULL; + goto done; +} + + +void crypto_ecdh_deinit(struct crypto_ecdh *ecdh) +{ + if (ecdh) { + crypto_ec_deinit(ecdh->ec); + EVP_PKEY_free(ecdh->pkey); + os_free(ecdh); + } +} + #endif /* CONFIG_ECC */ diff --git a/freebsd/contrib/wpa/src/crypto/ms_funcs.c b/freebsd/contrib/wpa/src/crypto/ms_funcs.c index 67e98dbf..a89a8fda 100644 --- a/freebsd/contrib/wpa/src/crypto/ms_funcs.c +++ b/freebsd/contrib/wpa/src/crypto/ms_funcs.c @@ -142,17 +142,20 @@ int hash_nt_password_hash(const u8 *password_hash, u8 *password_hash_hash) * @challenge: 8-octet Challenge (IN) * @password_hash: 16-octet PasswordHash (IN) * @response: 24-octet Response (OUT) + * Returns: 0 on success, -1 on failure */ -void challenge_response(const u8 *challenge, const u8 *password_hash, - u8 *response) +int challenge_response(const u8 *challenge, const u8 *password_hash, + u8 *response) { u8 zpwd[7]; - des_encrypt(challenge, password_hash, response); - des_encrypt(challenge, password_hash + 7, response + 8); + + if (des_encrypt(challenge, password_hash, response) < 0 || + des_encrypt(challenge, password_hash + 7, response + 8) < 0) + return -1; zpwd[0] = password_hash[14]; zpwd[1] = password_hash[15]; os_memset(zpwd + 2, 0, 5); - des_encrypt(challenge, zpwd, response + 16); + return des_encrypt(challenge, zpwd, response + 16); } @@ -177,9 +180,9 @@ int generate_nt_response(const u8 *auth_challenge, const u8 *peer_challenge, if (challenge_hash(peer_challenge, auth_challenge, username, username_len, challenge) || - nt_password_hash(password, password_len, password_hash)) + nt_password_hash(password, password_len, password_hash) || + challenge_response(challenge, password_hash, response)) return -1; - challenge_response(challenge, password_hash, response); return 0; } @@ -204,9 +207,9 @@ int generate_nt_response_pwhash(const u8 *auth_challenge, if (challenge_hash(peer_challenge, auth_challenge, username, username_len, - challenge)) + challenge) || + challenge_response(challenge, password_hash, response)) return -1; - challenge_response(challenge, password_hash, response); return 0; } @@ -306,9 +309,10 @@ int nt_challenge_response(const u8 *challenge, const u8 *password, size_t password_len, u8 *response) { u8 password_hash[16]; - if (nt_password_hash(password, password_len, password_hash)) + + if (nt_password_hash(password, password_len, password_hash) || + challenge_response(challenge, password_hash, response)) return -1; - challenge_response(challenge, password_hash, response); return 0; } @@ -489,12 +493,15 @@ int new_password_encrypted_with_old_nt_password_hash( * @password_hash: 16-octer PasswordHash (IN) * @block: 16-octet Block (IN) * @cypher: 16-octer Cypher (OUT) + * Returns: 0 on success, -1 on failure */ -void nt_password_hash_encrypted_with_block(const u8 *password_hash, - const u8 *block, u8 *cypher) +int nt_password_hash_encrypted_with_block(const u8 *password_hash, + const u8 *block, u8 *cypher) { - des_encrypt(password_hash, block, cypher); - des_encrypt(password_hash + 8, block + 7, cypher + 8); + if (des_encrypt(password_hash, block, cypher) < 0 || + des_encrypt(password_hash + 8, block + 7, cypher + 8) < 0) + return -1; + return 0; } @@ -517,10 +524,10 @@ int old_nt_password_hash_encrypted_with_new_nt_password_hash( if (nt_password_hash(old_password, old_password_len, old_password_hash) || nt_password_hash(new_password, new_password_len, - new_password_hash)) + new_password_hash) || + nt_password_hash_encrypted_with_block(old_password_hash, + new_password_hash, + encrypted_password_hash)) return -1; - nt_password_hash_encrypted_with_block(old_password_hash, - new_password_hash, - encrypted_password_hash); return 0; } diff --git a/freebsd/contrib/wpa/src/crypto/ms_funcs.h b/freebsd/contrib/wpa/src/crypto/ms_funcs.h index b5b5918e..b8d55f05 100644 --- a/freebsd/contrib/wpa/src/crypto/ms_funcs.h +++ b/freebsd/contrib/wpa/src/crypto/ms_funcs.h @@ -31,8 +31,8 @@ int generate_authenticator_response_pwhash( int nt_challenge_response(const u8 *challenge, const u8 *password, size_t password_len, u8 *response); -void challenge_response(const u8 *challenge, const u8 *password_hash, - u8 *response); +int challenge_response(const u8 *challenge, const u8 *password_hash, + u8 *response); int challenge_hash(const u8 *peer_challenge, const u8 *auth_challenge, const u8 *username, size_t username_len, u8 *challenge); int nt_password_hash(const u8 *password, size_t password_len, @@ -50,8 +50,8 @@ int __must_check new_password_encrypted_with_old_nt_password_hash( const u8 *new_password, size_t new_password_len, const u8 *old_password, size_t old_password_len, u8 *encrypted_pw_block); -void nt_password_hash_encrypted_with_block(const u8 *password_hash, - const u8 *block, u8 *cypher); +int nt_password_hash_encrypted_with_block(const u8 *password_hash, + const u8 *block, u8 *cypher); int old_nt_password_hash_encrypted_with_new_nt_password_hash( const u8 *new_password, size_t new_password_len, const u8 *old_password, size_t old_password_len, diff --git a/freebsd/contrib/wpa/src/crypto/random.c b/freebsd/contrib/wpa/src/crypto/random.c index 57880e31..8fd57a57 100644 --- a/freebsd/contrib/wpa/src/crypto/random.c +++ b/freebsd/contrib/wpa/src/crypto/random.c @@ -27,6 +27,9 @@ #include "utils/includes.h" #ifdef __linux__ #include <fcntl.h> +#ifdef CONFIG_GETRANDOM +#include <sys/random.h> +#endif /* CONFIG_GETRANDOM */ #endif /* __linux__ */ #include "utils/common.h" @@ -56,7 +59,6 @@ static int random_fd = -1; static unsigned int own_pool_ready = 0; #define RANDOM_ENTROPY_SIZE 20 static char *random_entropy_file = NULL; -static int random_entropy_file_read = 0; #define MIN_COLLECT_ENTROPY 1000 static unsigned int entropy = 0; @@ -68,6 +70,9 @@ static void random_write_entropy(void); static u32 __ROL32(u32 x, u32 y) { + if (y == 0) + return x; + return (x << (y & 31)) | (x >> (32 - (y & 31))); } @@ -228,30 +233,52 @@ int random_pool_ready(void) return 1; /* Already initialized - good to continue */ /* - * Try to fetch some more data from the kernel high quality - * /dev/random. There may not be enough data available at this point, + * Try to fetch some more data from the kernel high quality RNG. + * There may not be enough data available at this point, * so use non-blocking read to avoid blocking the application * completely. */ - fd = open("/dev/random", O_RDONLY | O_NONBLOCK); - if (fd < 0) { - wpa_printf(MSG_ERROR, "random: Cannot open /dev/random: %s", - strerror(errno)); - return -1; - } - res = read(fd, dummy_key + dummy_key_avail, - sizeof(dummy_key) - dummy_key_avail); +#ifdef CONFIG_GETRANDOM + res = getrandom(dummy_key + dummy_key_avail, + sizeof(dummy_key) - dummy_key_avail, GRND_NONBLOCK); if (res < 0) { - wpa_printf(MSG_ERROR, "random: Cannot read from /dev/random: " - "%s", strerror(errno)); - res = 0; + if (errno == ENOSYS) { + wpa_printf(MSG_DEBUG, + "random: getrandom() not supported, falling back to /dev/random"); + } else { + wpa_printf(MSG_INFO, + "random: no data from getrandom(): %s", + strerror(errno)); + res = 0; + } } - wpa_printf(MSG_DEBUG, "random: Got %u/%u bytes from " - "/dev/random", (unsigned) res, +#else /* CONFIG_GETRANDOM */ + res = -1; +#endif /* CONFIG_GETRANDOM */ + if (res < 0) { + fd = open("/dev/random", O_RDONLY | O_NONBLOCK); + if (fd < 0) { + wpa_printf(MSG_ERROR, + "random: Cannot open /dev/random: %s", + strerror(errno)); + return -1; + } + + res = read(fd, dummy_key + dummy_key_avail, + sizeof(dummy_key) - dummy_key_avail); + if (res < 0) { + wpa_printf(MSG_ERROR, + "random: Cannot read from /dev/random: %s", + strerror(errno)); + res = 0; + } + close(fd); + } + + wpa_printf(MSG_DEBUG, "random: Got %u/%u random bytes", (unsigned) res, (unsigned) (sizeof(dummy_key) - dummy_key_avail)); dummy_key_avail += res; - close(fd); if (dummy_key_avail == sizeof(dummy_key)) { if (own_pool_ready < MIN_READY_MARK) @@ -261,7 +288,7 @@ int random_pool_ready(void) } wpa_printf(MSG_INFO, "random: Only %u/%u bytes of strong " - "random data available from /dev/random", + "random data available", (unsigned) dummy_key_avail, (unsigned) sizeof(dummy_key)); if (own_pool_ready >= MIN_READY_MARK || @@ -356,7 +383,6 @@ static void random_read_entropy(void) own_pool_ready = (u8) buf[0]; random_add_randomness(buf + 1, RANDOM_ENTROPY_SIZE); - random_entropy_file_read = 1; os_free(buf); wpa_printf(MSG_DEBUG, "random: Added entropy from %s " "(own_pool_ready=%u)", @@ -414,6 +440,19 @@ void random_init(const char *entropy_file) if (random_fd >= 0) return; +#ifdef CONFIG_GETRANDOM + { + u8 dummy; + + if (getrandom(&dummy, 0, GRND_NONBLOCK) == 0 || + errno != ENOSYS) { + wpa_printf(MSG_DEBUG, + "random: getrandom() support available"); + return; + } + } +#endif /* CONFIG_GETRANDOM */ + random_fd = open("/dev/random", O_RDONLY | O_NONBLOCK); if (random_fd < 0) { wpa_printf(MSG_ERROR, "random: Cannot open /dev/random: %s", diff --git a/freebsd/contrib/wpa/src/crypto/sha256-internal.c b/freebsd/contrib/wpa/src/crypto/sha256-internal.c index 174bf3c4..8b07ab01 100644 --- a/freebsd/contrib/wpa/src/crypto/sha256-internal.c +++ b/freebsd/contrib/wpa/src/crypto/sha256-internal.c @@ -71,7 +71,7 @@ static const unsigned long K[64] = { ( ((((unsigned long) (x) & 0xFFFFFFFFUL) >> (unsigned long) ((y) & 31)) | \ ((unsigned long) (x) << (unsigned long) (32 - ((y) & 31)))) & 0xFFFFFFFFUL) #define Ch(x,y,z) (z ^ (x & (y ^ z))) -#define Maj(x,y,z) (((x | y) & z) | (x & y)) +#define Maj(x,y,z) (((x | y) & z) | (x & y)) #define S(x, n) RORc((x), (n)) #define R(x, n) (((x)&0xFFFFFFFFUL)>>(n)) #define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22)) @@ -102,7 +102,7 @@ static int sha256_compress(struct sha256_state *md, unsigned char *buf) for (i = 16; i < 64; i++) { W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16]; - } + } /* Compress */ #define RND(a,b,c,d,e,f,g,h,i) \ @@ -113,7 +113,7 @@ static int sha256_compress(struct sha256_state *md, unsigned char *buf) for (i = 0; i < 64; ++i) { RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], i); - t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4]; + t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4]; S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t; } diff --git a/freebsd/contrib/wpa/src/crypto/sha384.h b/freebsd/contrib/wpa/src/crypto/sha384.h index 3deafa59..22414253 100644 --- a/freebsd/contrib/wpa/src/crypto/sha384.h +++ b/freebsd/contrib/wpa/src/crypto/sha384.h @@ -1,6 +1,6 @@ /* * SHA384 hash implementation and interface functions - * Copyright (c) 2015, Jouni Malinen <j@w1.fi> + * Copyright (c) 2015-2017, Jouni Malinen <j@w1.fi> * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -15,10 +15,13 @@ int hmac_sha384_vector(const u8 *key, size_t key_len, size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac); int hmac_sha384(const u8 *key, size_t key_len, const u8 *data, size_t data_len, u8 *mac); -void sha384_prf(const u8 *key, size_t key_len, const char *label, - const u8 *data, size_t data_len, u8 *buf, size_t buf_len); -void sha384_prf_bits(const u8 *key, size_t key_len, const char *label, - const u8 *data, size_t data_len, u8 *buf, - size_t buf_len_bits); +int sha384_prf(const u8 *key, size_t key_len, const char *label, + const u8 *data, size_t data_len, u8 *buf, size_t buf_len); +int sha384_prf_bits(const u8 *key, size_t key_len, const char *label, + const u8 *data, size_t data_len, u8 *buf, + size_t buf_len_bits); +int hmac_sha384_kdf(const u8 *secret, size_t secret_len, + const char *label, const u8 *seed, size_t seed_len, + u8 *out, size_t outlen); #endif /* SHA384_H */ diff --git a/freebsd/contrib/wpa/src/crypto/sha512.h b/freebsd/contrib/wpa/src/crypto/sha512.h new file mode 100644 index 00000000..8e64c8b1 --- /dev/null +++ b/freebsd/contrib/wpa/src/crypto/sha512.h @@ -0,0 +1,27 @@ +/* + * SHA512 hash implementation and interface functions + * Copyright (c) 2015-2017, Jouni Malinen <j@w1.fi> + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef SHA512_H +#define SHA512_H + +#define SHA512_MAC_LEN 64 + +int hmac_sha512_vector(const u8 *key, size_t key_len, size_t num_elem, + const u8 *addr[], const size_t *len, u8 *mac); +int hmac_sha512(const u8 *key, size_t key_len, const u8 *data, + size_t data_len, u8 *mac); +int sha512_prf(const u8 *key, size_t key_len, const char *label, + const u8 *data, size_t data_len, u8 *buf, size_t buf_len); +int sha512_prf_bits(const u8 *key, size_t key_len, const char *label, + const u8 *data, size_t data_len, u8 *buf, + size_t buf_len_bits); +int hmac_sha512_kdf(const u8 *secret, size_t secret_len, + const char *label, const u8 *seed, size_t seed_len, + u8 *out, size_t outlen); + +#endif /* SHA512_H */ diff --git a/freebsd/contrib/wpa/src/crypto/tls.h b/freebsd/contrib/wpa/src/crypto/tls.h index 11d504a9..8bdb91ff 100644 --- a/freebsd/contrib/wpa/src/crypto/tls.h +++ b/freebsd/contrib/wpa/src/crypto/tls.h @@ -41,6 +41,8 @@ enum tls_fail_reason { TLS_FAIL_SERVER_CHAIN_PROBE = 8, TLS_FAIL_DOMAIN_SUFFIX_MISMATCH = 9, TLS_FAIL_DOMAIN_MISMATCH = 10, + TLS_FAIL_INSUFFICIENT_KEY_LEN = 11, + TLS_FAIL_DN_MISMATCH = 12, }; @@ -63,6 +65,7 @@ union tls_event_data { size_t hash_len; const char *altsubject[TLS_MAX_ALT_SUBJECT]; int num_altsubject; + const char *serial_num; } peer_cert; struct { @@ -80,6 +83,8 @@ struct tls_config { int cert_in_cb; const char *openssl_ciphers; unsigned int tls_session_lifetime; + unsigned int crl_reload_interval; + unsigned int tls_flags; void (*event_cb)(void *ctx, enum tls_event ev, union tls_event_data *data); @@ -97,6 +102,12 @@ struct tls_config { #define TLS_CONN_DISABLE_TLSv1_0 BIT(8) #define TLS_CONN_EXT_CERT_CHECK BIT(9) #define TLS_CONN_REQUIRE_OCSP_ALL BIT(10) +#define TLS_CONN_SUITEB BIT(11) +#define TLS_CONN_SUITEB_NO_ECDH BIT(12) +#define TLS_CONN_DISABLE_TLSv1_3 BIT(13) +#define TLS_CONN_ENABLE_TLSv1_0 BIT(14) +#define TLS_CONN_ENABLE_TLSv1_1 BIT(15) +#define TLS_CONN_ENABLE_TLSv1_2 BIT(16) /** * struct tls_connection_params - Parameters for TLS connection @@ -109,12 +120,19 @@ struct tls_config { * %NULL to allow all subjects * @altsubject_match: String to match in the alternative subject of the peer * certificate or %NULL to allow all alternative subjects - * @suffix_match: String to suffix match in the dNSName or CN of the peer - * certificate or %NULL to allow all domain names. This may allow subdomains an - * wildcard certificates. Each domain name label must have a full match. + * @suffix_match: Semicolon deliminated string of values to suffix match against + * the dNSName or CN of the peer certificate or %NULL to allow all domain names. + * This may allow subdomains and wildcard certificates. Each domain name label + * must have a full case-insensitive match. * @domain_match: String to match in the dNSName or CN of the peer * certificate or %NULL to allow all domain names. This requires a full, * case-insensitive match. + * + * More than one match string can be provided by using semicolons to + * separate the strings (e.g., example.org;example.com). When multiple + * strings are specified, a match with any one of the values is + * considered a sufficient match for the certificate, i.e., the + * conditions are ORed together. * @client_cert: File or reference name for client X.509 certificate in PEM or * DER format * @client_cert_blob: client_cert as inlined data or %NULL if not used @@ -138,12 +156,15 @@ struct tls_config { * @cert_id: the certificate's id when using engine * @ca_cert_id: the CA certificate's id when using engine * @openssl_ciphers: OpenSSL cipher configuration + * @openssl_ecdh_curves: OpenSSL ECDH curve configuration. %NULL for auto if + * supported, empty string to disable, or a colon-separated curve list. * @flags: Parameter options (TLS_CONN_*) * @ocsp_stapling_response: DER encoded file with cached OCSP stapling response * or %NULL if OCSP is not enabled * @ocsp_stapling_response_multi: DER encoded file with cached OCSP stapling * response list (OCSPResponseList for ocsp_multi in RFC 6961) or %NULL if * ocsp_multi is not enabled + * @check_cert_subject: Client certificate subject name matching string * * TLS connection parameters to be configured with tls_connection_set_params() * and tls_global_set_params(). @@ -181,10 +202,12 @@ struct tls_connection_params { const char *cert_id; const char *ca_cert_id; const char *openssl_ciphers; + const char *openssl_ecdh_curves; unsigned int flags; const char *ocsp_stapling_response; const char *ocsp_stapling_response_multi; + const char *check_cert_subject; }; @@ -248,6 +271,18 @@ void tls_connection_deinit(void *tls_ctx, struct tls_connection *conn); int tls_connection_established(void *tls_ctx, struct tls_connection *conn); /** + * tls_connection_peer_serial_num - Fetch peer certificate serial number + * @tls_ctx: TLS context data from tls_init() + * @conn: Connection context data from tls_connection_init() + * Returns: Allocated string buffer containing the peer certificate serial + * number or %NULL on error. + * + * The caller is responsible for freeing the returned buffer with os_free(). + */ +char * tls_connection_peer_serial_num(void *tls_ctx, + struct tls_connection *conn); + +/** * tls_connection_shutdown - Shutdown TLS connection * @tls_ctx: TLS context data from tls_init() * @conn: Connection context data from tls_connection_init() @@ -303,9 +338,11 @@ int __must_check tls_global_set_params( * @tls_ctx: TLS context data from tls_init() * @check_crl: 0 = do not verify CRLs, 1 = verify CRL for the user certificate, * 2 = verify CRL for all certificates + * @strict: 0 = allow CRL time errors, 1 = do not allow CRL time errors * Returns: 0 on success, -1 on failure */ -int __must_check tls_global_set_verify(void *tls_ctx, int check_crl); +int __must_check tls_global_set_verify(void *tls_ctx, int check_crl, + int strict); /** * tls_connection_set_verify - Set certificate verification options @@ -340,15 +377,21 @@ int __must_check tls_connection_get_random(void *tls_ctx, * @tls_ctx: TLS context data from tls_init() * @conn: Connection context data from tls_connection_init() * @label: Label (e.g., description of the key) for PRF + * @context: Optional extra upper-layer context (max len 2^16) + * @context_len: The length of the context value * @out: Buffer for output data from TLS-PRF * @out_len: Length of the output buffer * Returns: 0 on success, -1 on failure * - * Exports keying material using the mechanism described in RFC 5705. + * Exports keying material using the mechanism described in RFC 5705. If + * context is %NULL, context is not provided; otherwise, context is provided + * (including the case of empty context with context_len == 0). */ int __must_check tls_connection_export_key(void *tls_ctx, struct tls_connection *conn, const char *label, + const u8 *context, + size_t context_len, u8 *out, size_t out_len); /** diff --git a/freebsd/contrib/wpa/src/crypto/tls_internal.c b/freebsd/contrib/wpa/src/crypto/tls_internal.c index c6f65dc0..ff2fcb7d 100644 --- a/freebsd/contrib/wpa/src/crypto/tls_internal.c +++ b/freebsd/contrib/wpa/src/crypto/tls_internal.c @@ -2,7 +2,7 @@ /* * TLS interface functions and an internal TLS implementation - * Copyright (c) 2004-2011, Jouni Malinen <j@w1.fi> + * Copyright (c) 2004-2019, Jouni Malinen <j@w1.fi> * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -179,6 +179,14 @@ int tls_connection_established(void *tls_ctx, struct tls_connection *conn) } +char * tls_connection_peer_serial_num(void *tls_ctx, + struct tls_connection *conn) +{ + /* TODO */ + return NULL; +} + + int tls_connection_shutdown(void *tls_ctx, struct tls_connection *conn) { #ifdef CONFIG_TLS_INTERNAL_CLIENT @@ -242,6 +250,12 @@ int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn, return -1; } + if (params->openssl_ecdh_curves) { + wpa_printf(MSG_INFO, "TLS: openssl_ecdh_curves not supported"); + tlsv1_cred_free(cred); + return -1; + } + if (tlsv1_set_ca_cert(cred, params->ca_cert, params->ca_cert_blob, params->ca_cert_blob_len, params->ca_path)) { @@ -297,6 +311,9 @@ int tls_global_set_params(void *tls_ctx, struct tls_global *global = tls_ctx; struct tlsv1_credentials *cred; + if (params->check_cert_subject) + return -1; /* not yet supported */ + /* Currently, global parameters are only set when running in server * mode. */ global->server = 1; @@ -347,7 +364,7 @@ int tls_global_set_params(void *tls_ctx, } -int tls_global_set_verify(void *tls_ctx, int check_crl) +int tls_global_set_verify(void *tls_ctx, int check_crl, int strict) { struct tls_global *global = tls_ctx; global->check_crl = check_crl; @@ -397,7 +414,8 @@ static int tls_get_keyblock_size(struct tls_connection *conn) static int tls_connection_prf(void *tls_ctx, struct tls_connection *conn, - const char *label, int server_random_first, + const char *label, const u8 *context, + size_t context_len, int server_random_first, int skip_keyblock, u8 *out, size_t out_len) { int ret = -1, skip = 0; @@ -416,15 +434,15 @@ static int tls_connection_prf(void *tls_ctx, struct tls_connection *conn, #ifdef CONFIG_TLS_INTERNAL_CLIENT if (conn->client) { - ret = tlsv1_client_prf(conn->client, label, - server_random_first, + ret = tlsv1_client_prf(conn->client, label, context, + context_len, server_random_first, _out, skip + out_len); } #endif /* CONFIG_TLS_INTERNAL_CLIENT */ #ifdef CONFIG_TLS_INTERNAL_SERVER if (conn->server) { - ret = tlsv1_server_prf(conn->server, label, - server_random_first, + ret = tlsv1_server_prf(conn->server, label, context, + context_len, server_random_first, _out, skip + out_len); } #endif /* CONFIG_TLS_INTERNAL_SERVER */ @@ -437,17 +455,19 @@ static int tls_connection_prf(void *tls_ctx, struct tls_connection *conn, int tls_connection_export_key(void *tls_ctx, struct tls_connection *conn, - const char *label, u8 *out, size_t out_len) + const char *label, const u8 *context, + size_t context_len, u8 *out, size_t out_len) { - return tls_connection_prf(tls_ctx, conn, label, 0, 0, out, out_len); + return tls_connection_prf(tls_ctx, conn, label, context, context_len, + 0, 0, out, out_len); } int tls_connection_get_eap_fast_key(void *tls_ctx, struct tls_connection *conn, u8 *out, size_t out_len) { - return tls_connection_prf(tls_ctx, conn, "key expansion", 1, 1, out, - out_len); + return tls_connection_prf(tls_ctx, conn, "key expansion", NULL, 0, + 1, 1, out, out_len); } @@ -714,12 +734,20 @@ int tls_connection_client_hello_ext(void *tls_ctx, struct tls_connection *conn, int tls_connection_get_failed(void *tls_ctx, struct tls_connection *conn) { +#ifdef CONFIG_TLS_INTERNAL_SERVER + if (conn->server) + return tlsv1_server_get_failed(conn->server); +#endif /* CONFIG_TLS_INTERNAL_SERVER */ return 0; } int tls_connection_get_read_alerts(void *tls_ctx, struct tls_connection *conn) { +#ifdef CONFIG_TLS_INTERNAL_SERVER + if (conn->server) + return tlsv1_server_get_read_alerts(conn->server); +#endif /* CONFIG_TLS_INTERNAL_SERVER */ return 0; } @@ -727,6 +755,10 @@ int tls_connection_get_read_alerts(void *tls_ctx, struct tls_connection *conn) int tls_connection_get_write_alerts(void *tls_ctx, struct tls_connection *conn) { +#ifdef CONFIG_TLS_INTERNAL_SERVER + if (conn->server) + return tlsv1_server_get_write_alerts(conn->server); +#endif /* CONFIG_TLS_INTERNAL_SERVER */ return 0; } diff --git a/freebsd/contrib/wpa/src/drivers/driver.h b/freebsd/contrib/wpa/src/drivers/driver.h index a449cc93..e7c8f318 100644 --- a/freebsd/contrib/wpa/src/drivers/driver.h +++ b/freebsd/contrib/wpa/src/drivers/driver.h @@ -1,6 +1,6 @@ /* * Driver interface definition - * Copyright (c) 2003-2015, Jouni Malinen <j@w1.fi> + * Copyright (c) 2003-2017, Jouni Malinen <j@w1.fi> * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -21,6 +21,10 @@ #include "common/defs.h" #include "common/ieee802_11_defs.h" +#include "common/wpa_common.h" +#ifdef CONFIG_MACSEC +#include "pae/ieee802_1x_kay.h" +#endif /* CONFIG_MACSEC */ #include "utils/list.h" #define HOSTAPD_CHAN_DISABLED 0x00000001 @@ -54,6 +58,16 @@ #define HOSTAPD_CHAN_VHT_130_30 0x04000000 #define HOSTAPD_CHAN_VHT_150_10 0x08000000 +/* Allowed bandwidth mask */ +enum hostapd_chan_width_attr { + HOSTAPD_CHAN_WIDTH_10 = BIT(0), + HOSTAPD_CHAN_WIDTH_20 = BIT(1), + HOSTAPD_CHAN_WIDTH_40P = BIT(2), + HOSTAPD_CHAN_WIDTH_40M = BIT(3), + HOSTAPD_CHAN_WIDTH_80 = BIT(4), + HOSTAPD_CHAN_WIDTH_160 = BIT(5), +}; + /* Filter gratuitous ARP */ #define WPA_DATA_FRAME_FILTER_FLAG_ARP BIT(0) /* Filter unsolicited Neighbor Advertisement */ @@ -61,6 +75,10 @@ /* Filter unicast IP packets encrypted using the GTK */ #define WPA_DATA_FRAME_FILTER_FLAG_GTK BIT(2) +#define HOSTAPD_DFS_REGION_FCC 1 +#define HOSTAPD_DFS_REGION_ETSI 2 +#define HOSTAPD_DFS_REGION_JP 3 + /** * enum reg_change_initiator - Regulatory change initiator */ @@ -103,6 +121,13 @@ struct hostapd_channel_data { int flag; /** + * allowed_bw - Allowed channel width bitmask + * + * See enum hostapd_chan_width_attr. + */ + u32 allowed_bw; + + /** * max_tx_power - Regulatory transmit power limit in dBm */ u8 max_tx_power; @@ -133,6 +158,29 @@ struct hostapd_channel_data { unsigned int dfs_cac_ms; }; +#define HE_MAX_NUM_SS 8 +#define HE_MAX_PHY_CAPAB_SIZE 3 + +/** + * struct he_ppe_threshold - IEEE 802.11ax HE PPE Threshold + */ +struct he_ppe_threshold { + u32 numss_m1; + u32 ru_count; + u32 ppet16_ppet8_ru3_ru0[HE_MAX_NUM_SS]; +}; + +/** + * struct he_capabilities - IEEE 802.11ax HE capabilities + */ +struct he_capabilities { + u8 he_supported; + u32 phy_cap[HE_MAX_PHY_CAPAB_SIZE]; + u32 mac_cap; + u32 mcs; + struct he_ppe_threshold ppet; +}; + #define HOSTAPD_MODE_FLAG_HT_INFO_KNOWN BIT(0) #define HOSTAPD_MODE_FLAG_VHT_INFO_KNOWN BIT(1) @@ -191,6 +239,11 @@ struct hostapd_hw_modes { u8 vht_mcs_set[8]; unsigned int flags; /* HOSTAPD_MODE_FLAG_* */ + + /** + * he_capab - HE (IEEE 802.11ax) capabilities + */ + struct he_capabilities he_capab; }; @@ -233,6 +286,9 @@ struct hostapd_hw_modes { * @est_throughput: Estimated throughput in kbps (this is calculated during * scan result processing if left zero by the driver wrapper) * @snr: Signal-to-noise ratio in dB (calculated during scan result processing) + * @parent_tsf: Time when the Beacon/Probe Response frame was received in terms + * of TSF of the BSS specified by %tsf_bssid. + * @tsf_bssid: The BSS that %parent_tsf TSF time refers to. * @ie_len: length of the following IE field in octets * @beacon_ie_len: length of the following Beacon IE field in octets * @@ -263,6 +319,8 @@ struct wpa_scan_res { unsigned int age; unsigned int est_throughput; int snr; + u64 parent_tsf; + u8 tsf_bssid[ETH_ALEN]; size_t ie_len; size_t beacon_ie_len; /* Followed by ie_len + beacon_ie_len octets of IE data */ @@ -447,6 +505,15 @@ struct wpa_driver_scan_params { unsigned int sched_scan_plans_num; /** + * sched_scan_start_delay - Delay to use before starting the first scan + * + * Delay (in seconds) before scheduling first scan plan cycle. The + * driver may ignore this parameter and start immediately (or at any + * other time), if this feature is not supported. + */ + u32 sched_scan_start_delay; + + /** * bssid - Specific BSSID to scan for * * This optional parameter can be used to replace the default wildcard @@ -455,6 +522,80 @@ struct wpa_driver_scan_params { */ const u8 *bssid; + /** + * scan_cookie - Unique identification representing the scan request + * + * This scan_cookie carries a unique identification representing the + * scan request if the host driver/kernel supports concurrent scan + * requests. This cookie is returned from the corresponding driver + * interface. + * + * Note: Unlike other parameters in this structure, scan_cookie is used + * only to return information instead of setting parameters for the + * scan. + */ + u64 scan_cookie; + + /** + * duration - Dwell time on each channel + * + * This optional parameter can be used to set the dwell time on each + * channel. In TUs. + */ + u16 duration; + + /** + * duration_mandatory - Whether the specified duration is mandatory + * + * If this is set, the duration specified by the %duration field is + * mandatory (and the driver should reject the scan request if it is + * unable to comply with the specified duration), otherwise it is the + * maximum duration and the actual duration may be shorter. + */ + unsigned int duration_mandatory:1; + + /** + * relative_rssi_set - Whether relative RSSI parameters are set + */ + unsigned int relative_rssi_set:1; + + /** + * relative_rssi - Relative RSSI for reporting better BSSs + * + * Amount of RSSI by which a BSS should be better than the current + * connected BSS to report the new BSS to user space. + */ + s8 relative_rssi; + + /** + * relative_adjust_band - Band to which RSSI should be adjusted + * + * The relative_adjust_rssi should be added to the band specified + * by relative_adjust_band. + */ + enum set_band relative_adjust_band; + + /** + * relative_adjust_rssi - RSSI to be added to relative_adjust_band + * + * An amount of relative_band_rssi should be added to the BSSs that + * belong to the band specified by relative_adjust_band while comparing + * with other bands for BSS reporting. + */ + s8 relative_adjust_rssi; + + /** + * oce_scan + * + * Enable the following OCE scan features: (WFA OCE TechSpec v1.0) + * - Accept broadcast Probe Response frame. + * - Probe Request frame deferral and suppression. + * - Max Channel Time - driver fills FILS request params IE with + * Maximum Channel Time. + * - Send 1st Probe Request frame in rate of minimum 5.5 Mbps. + */ + unsigned int oce_scan:1; + /* * NOTE: Whenever adding new parameters here, please make sure * wpa_scan_clone_params() and wpa_scan_free_params() get updated with @@ -485,17 +626,18 @@ struct wpa_driver_auth_params { int p2p; /** - * sae_data - SAE elements for Authentication frame + * auth_data - Additional elements for Authentication frame * * This buffer starts with the Authentication transaction sequence - * number field. If SAE is not used, this pointer is %NULL. + * number field. If no special handling of such elements is needed, this + * pointer is %NULL. This is used with SAE and FILS. */ - const u8 *sae_data; + const u8 *auth_data; /** - * sae_data_len - Length of sae_data buffer in octets + * auth_data_len - Length of auth_data buffer in octets */ - size_t sae_data_len; + size_t auth_data_len; }; /** @@ -577,6 +719,68 @@ struct hostapd_freq_params { }; /** + * struct wpa_driver_sta_auth_params - Authentication parameters + * Data for struct wpa_driver_ops::sta_auth(). + */ +struct wpa_driver_sta_auth_params { + + /** + * own_addr - Source address and BSSID for authentication frame + */ + const u8 *own_addr; + + /** + * addr - MAC address of the station to associate + */ + const u8 *addr; + + /** + * seq - authentication sequence number + */ + u16 seq; + + /** + * status - authentication response status code + */ + u16 status; + + /** + * ie - authentication frame ie buffer + */ + const u8 *ie; + + /** + * len - ie buffer length + */ + size_t len; + + /** + * fils_auth - Indicates whether FILS authentication is being performed + */ + int fils_auth; + + /** + * fils_anonce - ANonce (required for FILS) + */ + u8 fils_anonce[WPA_NONCE_LEN]; + + /** + * fils_snonce - SNonce (required for FILS) + */ + u8 fils_snonce[WPA_NONCE_LEN]; + + /** + * fils_kek - key for encryption (required for FILS) + */ + u8 fils_kek[WPA_KEK_MAX_LEN]; + + /** + * fils_kek_len - Length of the fils_kek in octets (required for FILS) + */ + size_t fils_kek_len; +}; + +/** * struct wpa_driver_associate_params - Association parameters * Data for struct wpa_driver_ops::associate(). */ @@ -639,7 +843,7 @@ struct wpa_driver_associate_params { * WPA information element to be included in (Re)Association * Request (including information element id and length). Use * of this WPA IE is optional. If the driver generates the WPA - * IE, it can use pairwise_suite, group_suite, and + * IE, it can use pairwise_suite, group_suite, group_mgmt_suite, and * key_mgmt_suite to select proper algorithms. In this case, * the driver has to notify wpa_supplicant about the used WPA * IE by generating an event that the interface code will @@ -679,6 +883,13 @@ struct wpa_driver_associate_params { unsigned int group_suite; /** + * mgmt_group_suite - Selected group management cipher suite (WPA_CIPHER_*) + * + * This is usually ignored if @wpa_ie is used. + */ + unsigned int mgmt_group_suite; + + /** * key_mgmt_suite - Selected key management suite (WPA_KEY_MGMT_*) * * This is usually ignored if @wpa_ie is used. @@ -717,50 +928,13 @@ struct wpa_driver_associate_params { enum mfp_options mgmt_frame_protection; /** - * ft_ies - IEEE 802.11r / FT information elements - * If the supplicant is using IEEE 802.11r (FT) and has the needed keys - * for fast transition, this parameter is set to include the IEs that - * are to be sent in the next FT Authentication Request message. - * update_ft_ies() handler is called to update the IEs for further - * FT messages in the sequence. - * - * The driver should use these IEs only if the target AP is advertising - * the same mobility domain as the one included in the MDIE here. - * - * In ap_scan=2 mode, the driver can use these IEs when moving to a new - * AP after the initial association. These IEs can only be used if the - * target AP is advertising support for FT and is using the same MDIE - * and SSID as the current AP. - * - * The driver is responsible for reporting the FT IEs received from the - * AP's response using wpa_supplicant_event() with EVENT_FT_RESPONSE - * type. update_ft_ies() handler will then be called with the FT IEs to - * include in the next frame in the authentication sequence. - */ - const u8 *ft_ies; - - /** - * ft_ies_len - Length of ft_ies in bytes - */ - size_t ft_ies_len; - - /** - * ft_md - FT Mobility domain (6 octets) (also included inside ft_ies) - * - * This value is provided to allow the driver interface easier access - * to the current mobility domain. This value is set to %NULL if no - * mobility domain is currently active. - */ - const u8 *ft_md; - - /** * passphrase - RSN passphrase for PSK * * This value is made available only for WPA/WPA2-Personal (PSK) and - * only for drivers that set WPA_DRIVER_FLAGS_4WAY_HANDSHAKE. This is - * the 8..63 character ASCII passphrase, if available. Please note that - * this can be %NULL if passphrase was not used to generate the PSK. In - * that case, the psk field must be used to fetch the PSK. + * only for drivers that set WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK. This + * is the 8..63 character ASCII passphrase, if available. Please note + * that this can be %NULL if passphrase was not used to generate the + * PSK. In that case, the psk field must be used to fetch the PSK. */ const char *passphrase; @@ -768,9 +942,9 @@ struct wpa_driver_associate_params { * psk - RSN PSK (alternative for passphrase for PSK) * * This value is made available only for WPA/WPA2-Personal (PSK) and - * only for drivers that set WPA_DRIVER_FLAGS_4WAY_HANDSHAKE. This is - * the 32-octet (256-bit) PSK, if available. The driver wrapper should - * be prepared to handle %NULL value as an error. + * only for drivers that set WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK. This + * is the 32-octet (256-bit) PSK, if available. The driver wrapper + * should be prepared to handle %NULL value as an error. */ const u8 *psk; @@ -882,6 +1056,64 @@ struct wpa_driver_associate_params { * AP as usual. Valid for DMG network only. */ int pbss; + + /** + * fils_kek - KEK for FILS association frame protection (AES-SIV) + */ + const u8 *fils_kek; + + /** + * fils_kek_len: Length of fils_kek in bytes + */ + size_t fils_kek_len; + + /** + * fils_nonces - Nonces for FILS association frame protection + * (AES-SIV AAD) + */ + const u8 *fils_nonces; + + /** + * fils_nonces_len: Length of fils_nonce in bytes + */ + size_t fils_nonces_len; + + /** + * fils_erp_username - Username part of keyName-NAI + */ + const u8 *fils_erp_username; + + /** + * fils_erp_username_len - Length of fils_erp_username in bytes + */ + size_t fils_erp_username_len; + + /** + * fils_erp_realm - Realm/domain name to use in FILS ERP + */ + const u8 *fils_erp_realm; + + /** + * fils_erp_realm_len - Length of fils_erp_realm in bytes + */ + size_t fils_erp_realm_len; + + /** + * fils_erp_next_seq_num - The next sequence number to use in FILS ERP + * messages + */ + u16 fils_erp_next_seq_num; + + /** + * fils_erp_rrk - Re-authentication root key (rRK) for the keyName-NAI + * specified by fils_erp_username@fils_erp_realm. + */ + const u8 *fils_erp_rrk; + + /** + * fils_erp_rrk_len - Length of fils_erp_rrk in bytes + */ + size_t fils_erp_rrk_len; }; enum hide_ssid { @@ -940,6 +1172,22 @@ struct wpa_driver_ap_params { int *basic_rates; /** + * beacon_rate: Beacon frame data rate + * + * This parameter can be used to set a specific Beacon frame data rate + * for the BSS. The interpretation of this value depends on the + * rate_type (legacy: in 100 kbps units, HT: HT-MCS, VHT: VHT-MCS). If + * beacon_rate == 0 and rate_type == 0 (BEACON_RATE_LEGACY), the default + * Beacon frame data rate is used. + */ + unsigned int beacon_rate; + + /** + * beacon_rate_type: Beacon data rate type (legacy/HT/VHT) + */ + enum beacon_rate_type rate_type; + + /** * proberesp - Probe Response template * * This is used by drivers that reply to Probe Requests internally in @@ -1115,6 +1363,44 @@ struct wpa_driver_ap_params { * infrastructure BSS. Valid only for DMG network. */ int pbss; + + /** + * multicast_to_unicast - Whether to use multicast_to_unicast + * + * If this is non-zero, the AP is requested to perform multicast to + * unicast conversion for ARP, IPv4, and IPv6 frames (possibly within + * 802.1Q). If enabled, such frames are to be sent to each station + * separately, with the DA replaced by their own MAC address rather + * than the group address. + * + * Note that this may break certain expectations of the receiver, such + * as the ability to drop unicast IP packets received within multicast + * L2 frames, or the ability to not send ICMP destination unreachable + * messages for packets received in L2 multicast (which is required, + * but the receiver can't tell the difference if this new option is + * enabled.) + * + * This also doesn't implement the 802.11 DMS (directed multicast + * service). + */ + int multicast_to_unicast; + + /** + * ftm_responder - Whether FTM responder is enabled + */ + int ftm_responder; + + /** + * lci - Binary data, the content of an LCI report IE with type 8 as + * defined in IEEE Std 802.11-2016, 9.4.2.22.10 + */ + const struct wpabuf *lci; + + /** + * civic - Binary data, the content of a measurement report IE with + * type 11 as defined in IEEE Std 802.11-2016, 9.4.2.22.13 + */ + const struct wpabuf *civic; }; struct wpa_driver_mesh_bss_params { @@ -1122,6 +1408,7 @@ struct wpa_driver_mesh_bss_params { #define WPA_DRIVER_MESH_CONF_FLAG_PEER_LINK_TIMEOUT 0x00000002 #define WPA_DRIVER_MESH_CONF_FLAG_MAX_PEER_LINKS 0x00000004 #define WPA_DRIVER_MESH_CONF_FLAG_HT_OP_MODE 0x00000008 +#define WPA_DRIVER_MESH_CONF_FLAG_RSSI_THRESHOLD 0x00000010 /* * TODO: Other mesh configuration parameters would go here. * See NL80211_MESHCONF_* for all the mesh config parameters. @@ -1130,6 +1417,7 @@ struct wpa_driver_mesh_bss_params { int auto_plinks; int peer_link_timeout; int max_peer_links; + int rssi_threshold; u16 ht_opmode; }; @@ -1164,6 +1452,13 @@ struct wpa_driver_capa { #define WPA_DRIVER_CAPA_KEY_MGMT_WAPI_PSK 0x00000080 #define WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B 0x00000100 #define WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B_192 0x00000200 +#define WPA_DRIVER_CAPA_KEY_MGMT_OWE 0x00000400 +#define WPA_DRIVER_CAPA_KEY_MGMT_DPP 0x00000800 +#define WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA256 0x00001000 +#define WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384 0x00002000 +#define WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA256 0x00004000 +#define WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA384 0x00008000 +#define WPA_DRIVER_CAPA_KEY_MGMT_SAE 0x00010000 /** Bitfield of supported key management suites */ unsigned int key_mgmt; @@ -1197,7 +1492,7 @@ struct wpa_driver_capa { #define WPA_DRIVER_FLAGS_DFS_OFFLOAD 0x00000004 /** Driver takes care of RSN 4-way handshake internally; PMK is configured with * struct wpa_driver_ops::set_key using alg = WPA_ALG_PMK */ -#define WPA_DRIVER_FLAGS_4WAY_HANDSHAKE 0x00000008 +#define WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X 0x00000008 /** Driver is for a wired Ethernet interface */ #define WPA_DRIVER_FLAGS_WIRED 0x00000010 /** Driver provides separate commands for authentication and association (SME in @@ -1286,6 +1581,43 @@ struct wpa_driver_capa { #define WPA_DRIVER_FLAGS_FULL_AP_CLIENT_STATE 0x0000010000000000ULL /** Driver supports P2P Listen offload */ #define WPA_DRIVER_FLAGS_P2P_LISTEN_OFFLOAD 0x0000020000000000ULL +/** Driver supports FILS */ +#define WPA_DRIVER_FLAGS_SUPPORT_FILS 0x0000040000000000ULL +/** Driver supports Beacon frame TX rate configuration (legacy rates) */ +#define WPA_DRIVER_FLAGS_BEACON_RATE_LEGACY 0x0000080000000000ULL +/** Driver supports Beacon frame TX rate configuration (HT rates) */ +#define WPA_DRIVER_FLAGS_BEACON_RATE_HT 0x0000100000000000ULL +/** Driver supports Beacon frame TX rate configuration (VHT rates) */ +#define WPA_DRIVER_FLAGS_BEACON_RATE_VHT 0x0000200000000000ULL +/** Driver supports mgmt_tx with random TX address in non-connected state */ +#define WPA_DRIVER_FLAGS_MGMT_TX_RANDOM_TA 0x0000400000000000ULL +/** Driver supports mgmt_tx with random TX addr in connected state */ +#define WPA_DRIVER_FLAGS_MGMT_TX_RANDOM_TA_CONNECTED 0x0000800000000000ULL +/** Driver supports better BSS reporting with sched_scan in connected mode */ +#define WPA_DRIVER_FLAGS_SCHED_SCAN_RELATIVE_RSSI 0x0001000000000000ULL +/** Driver supports HE capabilities */ +#define WPA_DRIVER_FLAGS_HE_CAPABILITIES 0x0002000000000000ULL +/** Driver supports FILS shared key offload */ +#define WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD 0x0004000000000000ULL +/** Driver supports all OCE STA specific mandatory features */ +#define WPA_DRIVER_FLAGS_OCE_STA 0x0008000000000000ULL +/** Driver supports all OCE AP specific mandatory features */ +#define WPA_DRIVER_FLAGS_OCE_AP 0x0010000000000000ULL +/** + * Driver supports all OCE STA-CFON specific mandatory features only. + * If a driver sets this bit but not the %WPA_DRIVER_FLAGS_OCE_AP, the + * userspace shall assume that this driver may not support all OCE AP + * functionality but can support only OCE STA-CFON functionality. + */ +#define WPA_DRIVER_FLAGS_OCE_STA_CFON 0x0020000000000000ULL +/** Driver supports MFP-optional in the connect command */ +#define WPA_DRIVER_FLAGS_MFP_OPTIONAL 0x0040000000000000ULL +/** Driver is a self-managed regulatory device */ +#define WPA_DRIVER_FLAGS_SELF_MANAGED_REGULATORY 0x0080000000000000ULL +/** Driver supports FTM responder functionality */ +#define WPA_DRIVER_FLAGS_FTM_RESPONDER 0x0100000000000000ULL +/** Driver support 4-way handshake offload for WPA-Personal */ +#define WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK 0x0200000000000000ULL u64 flags; #define FULL_AP_CLIENT_STATE_SUPP(drv_flags) \ @@ -1386,6 +1718,11 @@ struct wpa_driver_capa { */ #define WPA_DRIVER_FLAGS_SUPPORT_RRM 0x00000010 +/** Driver supports setting the scan dwell time */ +#define WPA_DRIVER_FLAGS_SUPPORT_SET_SCAN_DWELL 0x00000020 +/** Driver supports Beacon Report Measurement */ +#define WPA_DRIVER_FLAGS_SUPPORT_BEACON_REPORT 0x00000040 + u32 rrm_flags; /* Driver concurrency capabilities */ @@ -1402,18 +1739,35 @@ struct wpa_driver_capa { struct hostapd_data; +#define STA_DRV_DATA_TX_MCS BIT(0) +#define STA_DRV_DATA_RX_MCS BIT(1) +#define STA_DRV_DATA_TX_VHT_MCS BIT(2) +#define STA_DRV_DATA_RX_VHT_MCS BIT(3) +#define STA_DRV_DATA_TX_VHT_NSS BIT(4) +#define STA_DRV_DATA_RX_VHT_NSS BIT(5) +#define STA_DRV_DATA_TX_SHORT_GI BIT(6) +#define STA_DRV_DATA_RX_SHORT_GI BIT(7) +#define STA_DRV_DATA_LAST_ACK_RSSI BIT(8) + struct hostap_sta_driver_data { unsigned long rx_packets, tx_packets; unsigned long long rx_bytes, tx_bytes; int bytes_64bit; /* whether 64-bit byte counters are supported */ unsigned long current_tx_rate; + unsigned long current_rx_rate; unsigned long inactive_msec; - unsigned long flags; + unsigned long flags; /* bitfield of STA_DRV_DATA_* */ unsigned long num_ps_buf_frames; unsigned long tx_retry_failed; unsigned long tx_retry_count; - int last_rssi; - int last_ack_rssi; + s8 last_ack_rssi; + s8 signal; + u8 rx_vhtmcs; + u8 tx_vhtmcs; + u8 rx_mcs; + u8 tx_mcs; + u8 rx_vht_nss; + u8 tx_vht_nss; }; struct hostapd_sta_add_params { @@ -1576,19 +1930,32 @@ enum wnm_oper { WNM_SLEEP_TFS_IE_DEL /* AP delete the TFS IE */ }; -/* enum chan_width - Channel width definitions */ -enum chan_width { - CHAN_WIDTH_20_NOHT, - CHAN_WIDTH_20, - CHAN_WIDTH_40, - CHAN_WIDTH_80, - CHAN_WIDTH_80P80, - CHAN_WIDTH_160, - CHAN_WIDTH_UNKNOWN +/* enum smps_mode - SMPS mode definitions */ +enum smps_mode { + SMPS_AUTOMATIC, + SMPS_OFF, + SMPS_DYNAMIC, + SMPS_STATIC, + + /* Keep last */ + SMPS_INVALID, }; +#define WPA_INVALID_NOISE 9999 + /** * struct wpa_signal_info - Information about channel signal quality + * @frequency: control frequency + * @above_threshold: true if the above threshold was crossed + * (relevant for a CQM event) + * @current_signal: in dBm + * @avg_signal: in dBm + * @avg_beacon_signal: in dBm + * @current_noise: %WPA_INVALID_NOISE if not supported + * @current_txrate: current TX rate + * @chanwidth: channel width + * @center_frq1: center frequency for the first segment + * @center_frq2: center frequency for the second segment (if relevant) */ struct wpa_signal_info { u32 frequency; @@ -1604,6 +1971,26 @@ struct wpa_signal_info { }; /** + * struct wpa_channel_info - Information about the current channel + * @frequency: Center frequency of the primary 20 MHz channel + * @chanwidth: Width of the current operating channel + * @sec_channel: Location of the secondary 20 MHz channel (either +1 or -1). + * This field is only filled in when using a 40 MHz channel. + * @center_frq1: Center frequency of frequency segment 0 + * @center_frq2: Center frequency of frequency segment 1 (for 80+80 channels) + * @seg1_idx: Frequency segment 1 index when using a 80+80 channel. This is + * derived from center_frq2 for convenience. + */ +struct wpa_channel_info { + u32 frequency; + enum chan_width chanwidth; + int sec_channel; + int center_frq1; + int center_frq2; + u8 seg1_idx; +}; + +/** * struct beacon_data - Beacon data * @head: Head portion of Beacon frame (before TIM IE) * @tail: Tail portion of Beacon frame (after TIM IE) @@ -1720,6 +2107,69 @@ struct drv_acs_params { const int *freq_list; }; +struct wpa_bss_trans_info { + u8 mbo_transition_reason; + u8 n_candidates; + u8 *bssid; +}; + +struct wpa_bss_candidate_info { + u8 num; + struct candidate_list { + u8 bssid[ETH_ALEN]; + u8 is_accept; + u32 reject_reason; + } *candidates; +}; + +struct wpa_pmkid_params { + const u8 *bssid; + const u8 *ssid; + size_t ssid_len; + const u8 *fils_cache_id; + const u8 *pmkid; + const u8 *pmk; + size_t pmk_len; +}; + +/* Mask used to specify which connection parameters have to be updated */ +enum wpa_drv_update_connect_params_mask { + WPA_DRV_UPDATE_ASSOC_IES = BIT(0), + WPA_DRV_UPDATE_FILS_ERP_INFO = BIT(1), + WPA_DRV_UPDATE_AUTH_TYPE = BIT(2), +}; + +/** + * struct external_auth - External authentication trigger parameters + * + * These are used across the external authentication request and event + * interfaces. + * @action: Action type / trigger for external authentication. Only significant + * for the event interface. + * @bssid: BSSID of the peer with which the authentication has to happen. Used + * by both the request and event interface. + * @ssid: SSID of the AP. Used by both the request and event interface. + * @ssid_len: SSID length in octets. + * @key_mgmt_suite: AKM suite of the respective authentication. Optional for + * the request interface. + * @status: Status code, %WLAN_STATUS_SUCCESS for successful authentication, + * use %WLAN_STATUS_UNSPECIFIED_FAILURE if wpa_supplicant cannot give + * the real status code for failures. Used only for the request interface + * from user space to the driver. + * @pmkid: Generated PMKID as part of external auth exchange (e.g., SAE). + */ +struct external_auth { + enum { + EXT_AUTH_START, + EXT_AUTH_ABORT, + } action; + const u8 *bssid; + const u8 *ssid; + size_t ssid_len; + unsigned int key_mgmt_suite; + u16 status; + const u8 *pmkid; +}; /** * struct wpa_driver_ops - Driver interface API definition @@ -1902,13 +2352,14 @@ struct wpa_driver_ops { /** * add_pmkid - Add PMKSA cache entry to the driver * @priv: private driver interface data - * @bssid: BSSID for the PMKSA cache entry - * @pmkid: PMKID for the PMKSA cache entry + * @params: PMKSA parameters * * Returns: 0 on success, -1 on failure * * This function is called when a new PMK is received, as a result of - * either normal authentication or RSN pre-authentication. + * either normal authentication or RSN pre-authentication. The PMKSA + * parameters are either a set of bssid, pmkid, and pmk; or a set of + * ssid, fils_cache_id, pmkid, and pmk. * * If the driver generates RSN IE, i.e., it does not use wpa_ie in * associate(), add_pmkid() can be used to add new PMKSA cache entries @@ -1916,18 +2367,18 @@ struct wpa_driver_ops { * driver_ops function does not need to be implemented. Likewise, if * the driver does not support WPA, this function is not needed. */ - int (*add_pmkid)(void *priv, const u8 *bssid, const u8 *pmkid); + int (*add_pmkid)(void *priv, struct wpa_pmkid_params *params); /** * remove_pmkid - Remove PMKSA cache entry to the driver * @priv: private driver interface data - * @bssid: BSSID for the PMKSA cache entry - * @pmkid: PMKID for the PMKSA cache entry + * @params: PMKSA parameters * * Returns: 0 on success, -1 on failure * * This function is called when the supplicant drops a PMKSA cache - * entry for any reason. + * entry for any reason. The PMKSA parameters are either a set of + * bssid and pmkid; or a set of ssid, fils_cache_id, and pmkid. * * If the driver generates RSN IE, i.e., it does not use wpa_ie in * associate(), remove_pmkid() can be used to synchronize PMKSA caches @@ -1936,7 +2387,7 @@ struct wpa_driver_ops { * implemented. Likewise, if the driver does not support WPA, this * function is not needed. */ - int (*remove_pmkid)(void *priv, const u8 *bssid, const u8 *pmkid); + int (*remove_pmkid)(void *priv, struct wpa_pmkid_params *params); /** * flush_pmkid - Flush PMKSA cache @@ -2051,12 +2502,13 @@ struct wpa_driver_ops { * @priv: Private driver interface data * @num_modes: Variable for returning the number of returned modes * flags: Variable for returning hardware feature flags + * @dfs: Variable for returning DFS region (HOSTAPD_DFS_REGION_*) * Returns: Pointer to allocated hardware data on success or %NULL on * failure. Caller is responsible for freeing this. */ struct hostapd_hw_modes * (*get_hw_feature_data)(void *priv, u16 *num_modes, - u16 *flags); + u16 *flags, u8 *dfs); /** * send_mlme - Send management frame from MLME @@ -2673,6 +3125,9 @@ struct wpa_driver_ops { * transmitted on that channel; alternatively the frame may be sent on * the current operational channel (if in associated state in station * mode or while operating as an AP.) + * + * If @src differs from the device MAC address, use of a random + * transmitter address is requested for this message exchange. */ int (*send_action)(void *priv, unsigned int freq, unsigned int wait, const u8 *dst, const u8 *src, const u8 *bssid, @@ -2973,6 +3428,14 @@ struct wpa_driver_ops { int (*signal_poll)(void *priv, struct wpa_signal_info *signal_info); /** + * channel_info - Get parameters of the current operating channel + * @priv: Private driver interface data + * @channel_info: Channel info structure + * Returns: 0 on success, negative (<0) on failure + */ + int (*channel_info)(void *priv, struct wpa_channel_info *channel_info); + + /** * set_authmode - Set authentication algorithm(s) for static WEP * @priv: Private driver interface data * @authmode: 1=Open System, 2=Shared Key, 3=both @@ -3058,19 +3521,13 @@ struct wpa_driver_ops { /** * sta_auth - Station authentication indication - * @priv: Private driver interface data - * @own_addr: Source address and BSSID for authentication frame - * @addr: MAC address of the station to associate - * @seq: authentication sequence number - * @status: authentication response status code - * @ie: authentication frame ie buffer - * @len: ie buffer length + * @priv: private driver interface data + * @params: Station authentication parameters * - * This function indicates the driver to send Authentication frame - * to the station. + * Returns: 0 on success, -1 on failure */ - int (*sta_auth)(void *priv, const u8 *own_addr, const u8 *addr, - u16 seq, u16 status, const u8 *ie, size_t len); + int (*sta_auth)(void *priv, + struct wpa_driver_sta_auth_params *params); /** * add_tspec - Add traffic stream @@ -3259,7 +3716,7 @@ struct wpa_driver_ops { /** * status - Get driver interface status information * @priv: Private driver interface data - * @buf: Buffer for printing tou the status information + * @buf: Buffer for printing the status information * @buflen: Maximum length of the buffer * Returns: Length of written status information or -1 on failure */ @@ -3282,6 +3739,17 @@ struct wpa_driver_ops { int (*roaming)(void *priv, int allowed, const u8 *bssid); /** + * disable_fils - Enable/disable FILS feature + * @priv: Private driver interface data + * @disable: 0-enable and 1-disable FILS feature + * Returns: 0 on success, -1 on failure + * + * This callback can be used to configure driver and below layers to + * enable/disable all FILS features. + */ + int (*disable_fils)(void *priv, int disable); + + /** * set_mac_addr - Set MAC address * @priv: Private driver interface data * @addr: MAC address to use or %NULL for setting back to permanent @@ -3295,6 +3763,14 @@ struct wpa_driver_ops { int (*macsec_deinit)(void *priv); /** + * macsec_get_capability - Inform MKA of this driver's capability + * @priv: Private driver interface data + * @cap: Driver's capability + * Returns: 0 on success, -1 on failure + */ + int (*macsec_get_capability)(void *priv, enum macsec_cap *cap); + + /** * enable_protect_frames - Set protect frames status * @priv: Private driver interface data * @enabled: TRUE = protect frames enabled @@ -3304,6 +3780,15 @@ struct wpa_driver_ops { int (*enable_protect_frames)(void *priv, Boolean enabled); /** + * enable_encrypt - Set encryption status + * @priv: Private driver interface data + * @enabled: TRUE = encrypt outgoing traffic + * FALSE = integrity-only protection on outgoing traffic + * Returns: 0 on success, -1 on failure (or if not supported) + */ + int (*enable_encrypt)(void *priv, Boolean enabled); + + /** * set_replay_protect - Set replay protect status and window size * @priv: Private driver interface data * @enabled: TRUE = replay protect enabled @@ -3333,155 +3818,137 @@ struct wpa_driver_ops { /** * get_receive_lowest_pn - Get receive lowest pn * @priv: Private driver interface data - * @channel: secure channel - * @an: association number - * @lowest_pn: lowest accept pn + * @sa: secure association * Returns: 0 on success, -1 on failure (or if not supported) */ - int (*get_receive_lowest_pn)(void *priv, u32 channel, u8 an, - u32 *lowest_pn); + int (*get_receive_lowest_pn)(void *priv, struct receive_sa *sa); /** * get_transmit_next_pn - Get transmit next pn * @priv: Private driver interface data - * @channel: secure channel - * @an: association number - * @next_pn: next pn + * @sa: secure association * Returns: 0 on success, -1 on failure (or if not supported) */ - int (*get_transmit_next_pn)(void *priv, u32 channel, u8 an, - u32 *next_pn); + int (*get_transmit_next_pn)(void *priv, struct transmit_sa *sa); /** * set_transmit_next_pn - Set transmit next pn * @priv: Private driver interface data - * @channel: secure channel - * @an: association number - * @next_pn: next pn + * @sa: secure association * Returns: 0 on success, -1 on failure (or if not supported) */ - int (*set_transmit_next_pn)(void *priv, u32 channel, u8 an, - u32 next_pn); + int (*set_transmit_next_pn)(void *priv, struct transmit_sa *sa); /** - * get_available_receive_sc - get available receive channel + * set_receive_lowest_pn - Set receive lowest PN * @priv: Private driver interface data - * @channel: secure channel + * @sa: secure association * Returns: 0 on success, -1 on failure (or if not supported) */ - int (*get_available_receive_sc)(void *priv, u32 *channel); + int (*set_receive_lowest_pn)(void *priv, struct receive_sa *sa); /** * create_receive_sc - create secure channel for receiving * @priv: Private driver interface data - * @channel: secure channel - * @sci_addr: secure channel identifier - address - * @sci_port: secure channel identifier - port + * @sc: secure channel * @conf_offset: confidentiality offset (0, 30, or 50) * @validation: frame validation policy (0 = Disabled, 1 = Checked, * 2 = Strict) * Returns: 0 on success, -1 on failure (or if not supported) */ - int (*create_receive_sc)(void *priv, u32 channel, const u8 *sci_addr, - u16 sci_port, unsigned int conf_offset, + int (*create_receive_sc)(void *priv, struct receive_sc *sc, + unsigned int conf_offset, int validation); /** * delete_receive_sc - delete secure connection for receiving * @priv: private driver interface data from init() - * @channel: secure channel + * @sc: secure channel * Returns: 0 on success, -1 on failure */ - int (*delete_receive_sc)(void *priv, u32 channel); + int (*delete_receive_sc)(void *priv, struct receive_sc *sc); /** * create_receive_sa - create secure association for receive * @priv: private driver interface data from init() - * @channel: secure channel - * @an: association number - * @lowest_pn: the lowest packet number can be received - * @sak: the secure association key + * @sa: secure association * Returns: 0 on success, -1 on failure */ - int (*create_receive_sa)(void *priv, u32 channel, u8 an, - u32 lowest_pn, const u8 *sak); + int (*create_receive_sa)(void *priv, struct receive_sa *sa); /** - * enable_receive_sa - enable the SA for receive - * @priv: private driver interface data from init() - * @channel: secure channel - * @an: association number + * delete_receive_sa - Delete secure association for receive + * @priv: Private driver interface data from init() + * @sa: Secure association * Returns: 0 on success, -1 on failure */ - int (*enable_receive_sa)(void *priv, u32 channel, u8 an); + int (*delete_receive_sa)(void *priv, struct receive_sa *sa); /** - * disable_receive_sa - disable SA for receive + * enable_receive_sa - enable the SA for receive * @priv: private driver interface data from init() - * @channel: secure channel index - * @an: association number + * @sa: secure association * Returns: 0 on success, -1 on failure */ - int (*disable_receive_sa)(void *priv, u32 channel, u8 an); + int (*enable_receive_sa)(void *priv, struct receive_sa *sa); /** - * get_available_transmit_sc - get available transmit channel - * @priv: Private driver interface data - * @channel: secure channel - * Returns: 0 on success, -1 on failure (or if not supported) + * disable_receive_sa - disable SA for receive + * @priv: private driver interface data from init() + * @sa: secure association + * Returns: 0 on success, -1 on failure */ - int (*get_available_transmit_sc)(void *priv, u32 *channel); + int (*disable_receive_sa)(void *priv, struct receive_sa *sa); /** * create_transmit_sc - create secure connection for transmit * @priv: private driver interface data from init() - * @channel: secure channel - * @sci_addr: secure channel identifier - address - * @sci_port: secure channel identifier - port + * @sc: secure channel + * @conf_offset: confidentiality offset (0, 30, or 50) * Returns: 0 on success, -1 on failure */ - int (*create_transmit_sc)(void *priv, u32 channel, const u8 *sci_addr, - u16 sci_port, unsigned int conf_offset); + int (*create_transmit_sc)(void *priv, struct transmit_sc *sc, + unsigned int conf_offset); /** * delete_transmit_sc - delete secure connection for transmit * @priv: private driver interface data from init() - * @channel: secure channel + * @sc: secure channel * Returns: 0 on success, -1 on failure */ - int (*delete_transmit_sc)(void *priv, u32 channel); + int (*delete_transmit_sc)(void *priv, struct transmit_sc *sc); /** * create_transmit_sa - create secure association for transmit * @priv: private driver interface data from init() - * @channel: secure channel index - * @an: association number - * @next_pn: the packet number used as next transmit packet - * @confidentiality: True if the SA is to provide confidentiality - * as well as integrity - * @sak: the secure association key + * @sa: secure association * Returns: 0 on success, -1 on failure */ - int (*create_transmit_sa)(void *priv, u32 channel, u8 an, u32 next_pn, - Boolean confidentiality, const u8 *sak); + int (*create_transmit_sa)(void *priv, struct transmit_sa *sa); + + /** + * delete_transmit_sa - Delete secure association for transmit + * @priv: Private driver interface data from init() + * @sa: Secure association + * Returns: 0 on success, -1 on failure + */ + int (*delete_transmit_sa)(void *priv, struct transmit_sa *sa); /** * enable_transmit_sa - enable SA for transmit * @priv: private driver interface data from init() - * @channel: secure channel - * @an: association number + * @sa: secure association * Returns: 0 on success, -1 on failure */ - int (*enable_transmit_sa)(void *priv, u32 channel, u8 an); + int (*enable_transmit_sa)(void *priv, struct transmit_sa *sa); /** * disable_transmit_sa - disable SA for transmit * @priv: private driver interface data from init() - * @channel: secure channel - * @an: association number + * @sa: secure association * Returns: 0 on success, -1 on failure */ - int (*disable_transmit_sa)(void *priv, u32 channel, u8 an); + int (*disable_transmit_sa)(void *priv, struct transmit_sa *sa); #endif /* CONFIG_MACSEC */ /** @@ -3555,9 +4022,12 @@ struct wpa_driver_ops { /** * abort_scan - Request the driver to abort an ongoing scan * @priv: Private driver interface data + * @scan_cookie: Cookie identifying the scan request. This is used only + * when the vendor interface QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN + * was used to trigger scan. Otherwise, 0 is used. * Returns 0 on success, -1 on failure */ - int (*abort_scan)(void *priv); + int (*abort_scan)(void *priv, u64 scan_cookie); /** * configure_data_frame_filters - Request to configure frame filters @@ -3623,8 +4093,81 @@ struct wpa_driver_ops { */ int (*set_default_scan_ies)(void *priv, const u8 *ies, size_t ies_len); -}; + /** + * set_tdls_mode - Set TDLS trigger mode to the host driver + * @priv: Private driver interface data + * @tdls_external_control: Represents if TDLS external trigger control + * mode is enabled/disabled. + * + * This optional callback can be used to configure the TDLS external + * trigger control mode to the host driver. + */ + int (*set_tdls_mode)(void *priv, int tdls_external_control); + /** + * get_bss_transition_status - Get candidate BSS's transition status + * @priv: Private driver interface data + * @params: Candidate BSS list + * + * Get the accept or reject reason code for a list of BSS transition + * candidates. + */ + struct wpa_bss_candidate_info * + (*get_bss_transition_status)(void *priv, + struct wpa_bss_trans_info *params); + /** + * ignore_assoc_disallow - Configure driver to ignore assoc_disallow + * @priv: Private driver interface data + * @ignore_disallow: 0 to not ignore, 1 to ignore + * Returns: 0 on success, -1 on failure + */ + int (*ignore_assoc_disallow)(void *priv, int ignore_disallow); + + /** + * set_bssid_blacklist - Set blacklist of BSSIDs to the driver + * @priv: Private driver interface data + * @num_bssid: Number of blacklist BSSIDs + * @bssids: List of blacklisted BSSIDs + */ + int (*set_bssid_blacklist)(void *priv, unsigned int num_bssid, + const u8 *bssid); + + /** + * update_connect_params - Update the connection parameters + * @priv: Private driver interface data + * @params: Association parameters + * @mask: Bit mask indicating which parameters in @params have to be + * updated + * Returns: 0 on success, -1 on failure + * + * Update the connection parameters when in connected state so that the + * driver uses the updated parameters for subsequent roaming. This is + * used only with drivers that implement internal BSS selection and + * roaming. + */ + int (*update_connect_params)( + void *priv, struct wpa_driver_associate_params *params, + enum wpa_drv_update_connect_params_mask mask); + + /** + * send_external_auth_status - Indicate the status of external + * authentication processing to the host driver. + * @priv: Private driver interface data + * @params: Status of authentication processing. + * Returns: 0 on success, -1 on failure + */ + int (*send_external_auth_status)(void *priv, + struct external_auth *params); + + /** + * set_4addr_mode - Set 4-address mode + * @priv: Private driver interface data + * @bridge_ifname: Bridge interface name + * @val: 0 - disable 4addr mode, 1 - enable 4addr mode + * Returns: 0 on success, < 0 on failure + */ + int (*set_4addr_mode)(void *priv, const char *bridge_ifname, int val); +}; /** * enum wpa_event_type - Event type for wpa_supplicant_event() calls @@ -3734,17 +4277,6 @@ enum wpa_event_type { EVENT_PMKID_CANDIDATE, /** - * EVENT_STKSTART - Request STK handshake (MLME-STKSTART.request) - * - * This event can be used to inform wpa_supplicant about desire to set - * up secure direct link connection between two stations as defined in - * IEEE 802.11e with a new PeerKey mechanism that replaced the original - * STAKey negotiation. The caller will need to set peer address for the - * event. - */ - EVENT_STKSTART, - - /** * EVENT_TDLS - Request TDLS operation * * This event can be used to request a TDLS operation to be performed. @@ -4043,7 +4575,7 @@ enum wpa_event_type { * EVENT_DFS_CAC_ABORTED - Notify that channel availability check has been aborted * * The CAC was not successful, and the channel remains in the previous - * state. This may happen due to a radar beeing detected or other + * state. This may happen due to a radar being detected or other * external influences. */ EVENT_DFS_CAC_ABORTED, @@ -4112,6 +4644,65 @@ enum wpa_event_type { * EVENT_P2P_LO_STOP - Notify that P2P listen offload is stopped */ EVENT_P2P_LO_STOP, + + /** + * EVENT_BEACON_LOSS - Beacon loss detected + * + * This event indicates that no Beacon frames has been received from + * the current AP. This may indicate that the AP is not anymore in + * range. + */ + EVENT_BEACON_LOSS, + + /** + * EVENT_DFS_PRE_CAC_EXPIRED - Notify that channel availability check + * done previously (Pre-CAC) on the channel has expired. This would + * normally be on a non-ETSI DFS regulatory domain. DFS state of the + * channel will be moved from available to usable. A new CAC has to be + * performed before start operating on this channel. + */ + EVENT_DFS_PRE_CAC_EXPIRED, + + /** + * EVENT_EXTERNAL_AUTH - This event interface is used by host drivers + * that do not define separate commands for authentication and + * association (~WPA_DRIVER_FLAGS_SME) but offload the 802.11 + * authentication to wpa_supplicant. This event carries all the + * necessary information from the host driver for the authentication to + * happen. + */ + EVENT_EXTERNAL_AUTH, + + /** + * EVENT_PORT_AUTHORIZED - Notification that a connection is authorized + * + * This event should be indicated when the driver completes the 4-way + * handshake. This event should be preceded by an EVENT_ASSOC that + * indicates the completion of IEEE 802.11 association. + */ + EVENT_PORT_AUTHORIZED, + + /** + * EVENT_STATION_OPMODE_CHANGED - Notify STA's HT/VHT operation mode + * change event. + */ + EVENT_STATION_OPMODE_CHANGED, + + /** + * EVENT_INTERFACE_MAC_CHANGED - Notify that interface MAC changed + * + * This event is emitted when the MAC changes while the interface is + * enabled. When an interface was disabled and becomes enabled, it + * must be always assumed that the MAC possibly changed. + */ + EVENT_INTERFACE_MAC_CHANGED, + + /** + * EVENT_WDS_STA_INTERFACE_STATUS - Notify WDS STA interface status + * + * This event is emitted when an interface is added/removed for WDS STA. + */ + EVENT_WDS_STA_INTERFACE_STATUS, }; @@ -4204,6 +4795,16 @@ union wpa_event_data { size_t resp_ies_len; /** + * resp_frame - (Re)Association Response frame + */ + const u8 *resp_frame; + + /** + * resp_frame_len - (Re)Association Response frame length + */ + size_t resp_frame_len; + + /** * beacon_ies - Beacon or Probe Response IEs * * Optional Beacon/ProbeResp data: IEs included in Beacon or @@ -4280,6 +4881,8 @@ union wpa_event_data { /** * ptk_kek - The derived PTK KEK + * This is used in key management offload and also in FILS SK + * offload. */ const u8 *ptk_kek; @@ -4293,6 +4896,36 @@ union wpa_event_data { * 0 = unknown, 1 = unchanged, 2 = changed */ u8 subnet_status; + + /** + * The following information is used in FILS SK offload + * @fils_erp_next_seq_num + * @fils_pmk + * @fils_pmk_len + * @fils_pmkid + */ + + /** + * fils_erp_next_seq_num - The next sequence number to use in + * FILS ERP messages + */ + u16 fils_erp_next_seq_num; + + /** + * fils_pmk - A new PMK if generated in case of FILS + * authentication + */ + const u8 *fils_pmk; + + /** + * fils_pmk_len - Length of fils_pmk + */ + size_t fils_pmk_len; + + /** + * fils_pmkid - PMKID used or generated in FILS authentication + */ + const u8 *fils_pmkid; } assoc_info; /** @@ -4389,13 +5022,6 @@ union wpa_event_data { } pmkid_candidate; /** - * struct stkstart - Data for EVENT_STKSTART - */ - struct stkstart { - u8 peer[ETH_ALEN]; - } stkstart; - - /** * struct tdls - Data for EVENT_TDLS */ struct tdls { @@ -4503,6 +5129,17 @@ union wpa_event_data { * than explicit rejection response from the AP. */ int timed_out; + + /** + * timeout_reason - Reason for the timeout + */ + const char *timeout_reason; + + /** + * fils_erp_next_seq_num - The next sequence number to use in + * FILS ERP messages + */ + u16 fils_erp_next_seq_num; } assoc_reject; struct timeout_event { @@ -4586,6 +5223,11 @@ union wpa_event_data { * @external_scan: Whether the scan info is for an external scan * @nl_scan_event: 1 if the source of this scan event is a normal scan, * 0 if the source of the scan event is a vendor scan + * @scan_start_tsf: Time when the scan started in terms of TSF of the + * BSS that the interface that requested the scan is connected to + * (if available). + * @scan_start_tsf_bssid: The BSSID according to which %scan_start_tsf + * is set. */ struct scan_info { int aborted; @@ -4595,6 +5237,8 @@ union wpa_event_data { size_t num_ssids; int external_scan; int nl_scan_event; + u64 scan_start_tsf; + u8 scan_start_tsf_bssid[ETH_ALEN]; } scan_info; /** @@ -4684,9 +5328,12 @@ union wpa_event_data { /** * struct low_ack - Data for EVENT_STATION_LOW_ACK events * @addr: station address + * @num_packets: Number of packets lost (consecutive packets not + * acknowledged) */ struct low_ack { u8 addr[ETH_ALEN]; + u32 num_packets; } low_ack; /** @@ -4858,6 +5505,37 @@ union wpa_event_data { P2P_LO_STOPPED_REASON_NOT_SUPPORTED, } reason_code; } p2p_lo_stop; + + /* For EVENT_EXTERNAL_AUTH */ + struct external_auth external_auth; + + /** + * struct sta_opmode - Station's operation mode change event + * @addr: The station MAC address + * @smps_mode: SMPS mode of the station + * @chan_width: Channel width of the station + * @rx_nss: RX_NSS of the station + * + * This is used as data with EVENT_STATION_OPMODE_CHANGED. + */ + struct sta_opmode { + const u8 *addr; + enum smps_mode smps_mode; + enum chan_width chan_width; + u8 rx_nss; + } sta_opmode; + + /** + * struct wds_sta_interface - Data for EVENT_WDS_STA_INTERFACE_STATUS. + */ + struct wds_sta_interface { + const u8 *sta_addr; + const char *ifname; + enum { + INTERFACE_ADDED, + INTERFACE_REMOVED + } istatus; + } wds_sta_interface; }; /** @@ -4931,6 +5609,8 @@ const char * event_to_string(enum wpa_event_type event); /* Convert chan_width to a string for logging and control interfaces */ const char * channel_width_to_string(enum chan_width width); +int channel_width_to_int(enum chan_width width); + int ht_supported(const struct hostapd_hw_modes *mode); int vht_supported(const struct hostapd_hw_modes *mode); @@ -4973,6 +5653,10 @@ extern const struct wpa_driver_ops wpa_driver_wired_ops; /* driver_wired.c */ /* driver_macsec_qca.c */ extern const struct wpa_driver_ops wpa_driver_macsec_qca_ops; #endif /* CONFIG_DRIVER_MACSEC_QCA */ +#ifdef CONFIG_DRIVER_MACSEC_LINUX +/* driver_macsec_linux.c */ +extern const struct wpa_driver_ops wpa_driver_macsec_linux_ops; +#endif /* CONFIG_DRIVER_MACSEC_LINUX */ #ifdef CONFIG_DRIVER_ROBOSWITCH /* driver_roboswitch.c */ extern const struct wpa_driver_ops wpa_driver_roboswitch_ops; diff --git a/freebsd/contrib/wpa/src/drivers/driver_bsd.c b/freebsd/contrib/wpa/src/drivers/driver_bsd.c index c1679806..3ef49fd7 100644 --- a/freebsd/contrib/wpa/src/drivers/driver_bsd.c +++ b/freebsd/contrib/wpa/src/drivers/driver_bsd.c @@ -144,7 +144,7 @@ bsd_get80211(void *priv, struct ieee80211req *ireq, int op, void *arg, ireq->i_data = arg; if (ioctl(drv->global->sock, SIOCG80211, ireq) < 0) { - wpa_printf(MSG_ERROR, "ioctl[SIOCS80211, op=%u, " + wpa_printf(MSG_ERROR, "ioctl[SIOCG80211, op=%u, " "arg_len=%u]: %s", op, arg_len, strerror(errno)); return -1; } diff --git a/freebsd/contrib/wpa/src/drivers/driver_common.c b/freebsd/contrib/wpa/src/drivers/driver_common.c index 139829e4..be9ff3f6 100644 --- a/freebsd/contrib/wpa/src/drivers/driver_common.c +++ b/freebsd/contrib/wpa/src/drivers/driver_common.c @@ -2,7 +2,7 @@ /* * Common driver-related functions - * Copyright (c) 2003-2011, Jouni Malinen <j@w1.fi> + * Copyright (c) 2003-2017, Jouni Malinen <j@w1.fi> * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -37,7 +37,6 @@ const char * event_to_string(enum wpa_event_type event) E2S(ASSOCINFO); E2S(INTERFACE_STATUS); E2S(PMKID_CANDIDATE); - E2S(STKSTART); E2S(TDLS); E2S(FT_RESPONSE); E2S(IBSS_RSN_START); @@ -83,6 +82,13 @@ const char * event_to_string(enum wpa_event_type event) E2S(ACS_CHANNEL_SELECTED); E2S(DFS_CAC_STARTED); E2S(P2P_LO_STOP); + E2S(BEACON_LOSS); + E2S(DFS_PRE_CAC_EXPIRED); + E2S(EXTERNAL_AUTH); + E2S(PORT_AUTHORIZED); + E2S(STATION_OPMODE_CHANGED); + E2S(INTERFACE_MAC_CHANGED); + E2S(WDS_STA_INTERFACE_STATUS); } return "UNKNOWN"; @@ -111,6 +117,25 @@ const char * channel_width_to_string(enum chan_width width) } +int channel_width_to_int(enum chan_width width) +{ + switch (width) { + case CHAN_WIDTH_20_NOHT: + case CHAN_WIDTH_20: + return 20; + case CHAN_WIDTH_40: + return 40; + case CHAN_WIDTH_80: + return 80; + case CHAN_WIDTH_80P80: + case CHAN_WIDTH_160: + return 160; + default: + return 0; + } +} + + int ht_supported(const struct hostapd_hw_modes *mode) { if (!(mode->flags & HOSTAPD_MODE_FLAG_HT_INFO_KNOWN)) { @@ -230,7 +255,8 @@ const char * driver_flag_to_string(u64 flag) DF2S(DRIVER_IE); DF2S(SET_KEYS_AFTER_ASSOC); DF2S(DFS_OFFLOAD); - DF2S(4WAY_HANDSHAKE); + DF2S(4WAY_HANDSHAKE_PSK); + DF2S(4WAY_HANDSHAKE_8021X); DF2S(WIRED); DF2S(SME); DF2S(AP); @@ -269,6 +295,19 @@ const char * driver_flag_to_string(u64 flag) DF2S(OFFCHANNEL_SIMULTANEOUS); DF2S(FULL_AP_CLIENT_STATE); DF2S(P2P_LISTEN_OFFLOAD); + DF2S(SUPPORT_FILS); + DF2S(BEACON_RATE_LEGACY); + DF2S(BEACON_RATE_HT); + DF2S(BEACON_RATE_VHT); + DF2S(MGMT_TX_RANDOM_TA); + DF2S(MGMT_TX_RANDOM_TA_CONNECTED); + DF2S(SCHED_SCAN_RELATIVE_RSSI); + DF2S(HE_CAPABILITIES); + DF2S(FILS_SK_OFFLOAD); + DF2S(OCE_STA); + DF2S(OCE_AP); + DF2S(OCE_STA_CFON); + DF2S(MFP_OPTIONAL); } return "UNKNOWN"; #undef DF2S diff --git a/freebsd/contrib/wpa/src/drivers/driver_ndis.c b/freebsd/contrib/wpa/src/drivers/driver_ndis.c index 98aa48ba..7e0db265 100644 --- a/freebsd/contrib/wpa/src/drivers/driver_ndis.c +++ b/freebsd/contrib/wpa/src/drivers/driver_ndis.c @@ -1223,12 +1223,16 @@ static int wpa_driver_ndis_set_pmkid(struct wpa_driver_ndis_data *drv) } -static int wpa_driver_ndis_add_pmkid(void *priv, const u8 *bssid, - const u8 *pmkid) +static int wpa_driver_ndis_add_pmkid(void *priv, + struct wpa_pmkid_params *params) { struct wpa_driver_ndis_data *drv = priv; struct ndis_pmkid_entry *entry, *prev; + const u8 *bssid = params->bssid; + const u8 *pmkid = params->pmkid; + if (!bssid || !pmkid) + return -1; if (drv->no_of_pmkid == 0) return 0; @@ -1264,12 +1268,16 @@ static int wpa_driver_ndis_add_pmkid(void *priv, const u8 *bssid, } -static int wpa_driver_ndis_remove_pmkid(void *priv, const u8 *bssid, - const u8 *pmkid) +static int wpa_driver_ndis_remove_pmkid(void *priv, + struct wpa_pmkid_params *params) { struct wpa_driver_ndis_data *drv = priv; struct ndis_pmkid_entry *entry, *prev; + const u8 *bssid = params->bssid; + const u8 *pmkid = params->pmkid; + if (!bssid || !pmkid) + return -1; if (drv->no_of_pmkid == 0) return 0; diff --git a/freebsd/contrib/wpa/src/drivers/driver_nl80211.h b/freebsd/contrib/wpa/src/drivers/driver_nl80211.h index d0ec48c9..1e7fe7a9 100644 --- a/freebsd/contrib/wpa/src/drivers/driver_nl80211.h +++ b/freebsd/contrib/wpa/src/drivers/driver_nl80211.h @@ -60,11 +60,13 @@ struct i802_bss { char brname[IFNAMSIZ]; unsigned int beacon_set:1; unsigned int added_if_into_bridge:1; + unsigned int already_in_bridge:1; unsigned int added_bridge:1; unsigned int in_deinit:1; unsigned int wdev_id_set:1; unsigned int added_if:1; unsigned int static_ap:1; + unsigned int use_nl_connect:1; u8 addr[ETH_ALEN]; @@ -73,11 +75,12 @@ struct i802_bss { int if_dynamic; void *ctx; - struct nl_handle *nl_preq, *nl_mgmt; + struct nl_handle *nl_preq, *nl_mgmt, *nl_connect; struct nl_cb *nl_cb; struct nl80211_wiphy_data *wiphy_data; struct dl_list wiphy_list; + u8 rand_addr[ETH_ALEN]; }; struct wpa_driver_nl80211_data { @@ -160,6 +163,10 @@ struct wpa_driver_nl80211_data { unsigned int scan_vendor_cmd_avail:1; unsigned int connect_reassoc:1; unsigned int set_wifi_conf_vendor_cmd_avail:1; + unsigned int he_capab_vendor_cmd_avail:1; + unsigned int fetch_bss_trans_status:1; + unsigned int roam_vendor_cmd_avail:1; + unsigned int get_supported_akm_suites_avail:1; u64 vendor_scan_cookie; u64 remain_on_chan_cookie; @@ -208,6 +215,8 @@ struct wpa_driver_nl80211_data { * (NL80211_CMD_VENDOR). 0 if no pending scan request. */ int last_scan_cmd; + + struct he_capabilities he_capab; }; struct nl_msg; @@ -228,6 +237,7 @@ int nl80211_create_iface(struct wpa_driver_nl80211_data *drv, void *arg, int use_existing); void nl80211_remove_iface(struct wpa_driver_nl80211_data *drv, int ifidx); unsigned int nl80211_get_assoc_freq(struct wpa_driver_nl80211_data *drv); +int nl80211_get_assoc_ssid(struct wpa_driver_nl80211_data *drv, u8 *ssid); enum chan_width convert2width(int width); void nl80211_mark_disconnected(struct wpa_driver_nl80211_data *drv); struct i802_bss * get_bss_ifindex(struct wpa_driver_nl80211_data *drv, @@ -244,7 +254,8 @@ int wpa_driver_nl80211_set_mode(struct i802_bss *bss, enum nl80211_iftype nlmode); int wpa_driver_nl80211_mlme(struct wpa_driver_nl80211_data *drv, const u8 *addr, int cmd, u16 reason_code, - int local_state_change); + int local_state_change, + struct nl_handle *nl_connect); int nl80211_create_monitor_interface(struct wpa_driver_nl80211_data *drv); void nl80211_remove_monitor_interface(struct wpa_driver_nl80211_data *drv); @@ -254,7 +265,8 @@ int nl80211_send_monitor(struct wpa_driver_nl80211_data *drv, int wpa_driver_nl80211_capa(struct wpa_driver_nl80211_data *drv); struct hostapd_hw_modes * -nl80211_get_hw_feature_data(void *priv, u16 *num_modes, u16 *flags); +nl80211_get_hw_feature_data(void *priv, u16 *num_modes, u16 *flags, + u8 *dfs_domain); int process_global_event(struct nl_msg *msg, void *arg); int process_bss_event(struct nl_msg *msg, void *arg); @@ -282,15 +294,6 @@ int wpa_driver_set_ap_wps_p2p_ie(void *priv, const struct wpabuf *beacon, /* driver_nl80211_scan.c */ -struct nl80211_bss_info_arg { - struct wpa_driver_nl80211_data *drv; - struct wpa_scan_results *res; - unsigned int assoc_freq; - unsigned int ibss_freq; - u8 assoc_bssid[ETH_ALEN]; -}; - -int bss_info_handler(struct nl_msg *msg, void *arg); void wpa_driver_nl80211_scan_timeout(void *eloop_ctx, void *timeout_ctx); int wpa_driver_nl80211_scan(struct i802_bss *bss, struct wpa_driver_scan_params *params); @@ -299,7 +302,7 @@ int wpa_driver_nl80211_sched_scan(void *priv, int wpa_driver_nl80211_stop_sched_scan(void *priv); struct wpa_scan_results * wpa_driver_nl80211_get_scan_results(void *priv); void nl80211_dump_scan(struct wpa_driver_nl80211_data *drv); -int wpa_driver_nl80211_abort_scan(void *priv); +int wpa_driver_nl80211_abort_scan(void *priv, u64 scan_cookie); int wpa_driver_nl80211_vendor_scan(struct i802_bss *bss, struct wpa_driver_scan_params *params); int nl80211_set_default_scan_ies(void *priv, const u8 *ies, size_t ies_len); diff --git a/freebsd/contrib/wpa/src/drivers/driver_wired.c b/freebsd/contrib/wpa/src/drivers/driver_wired.c index 372bf791..0972df92 100644 --- a/freebsd/contrib/wpa/src/drivers/driver_wired.c +++ b/freebsd/contrib/wpa/src/drivers/driver_wired.c @@ -14,6 +14,7 @@ #include "common.h" #include "eloop.h" #include "driver.h" +#include "driver_wired_common.h" #include <sys/ioctl.h> #undef IFNAMSIZ @@ -44,20 +45,12 @@ struct ieee8023_hdr { #pragma pack(pop) #endif /* _MSC_VER */ -static const u8 pae_group_addr[ETH_ALEN] = -{ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03 }; - struct wpa_driver_wired_data { - char ifname[IFNAMSIZ + 1]; - void *ctx; + struct driver_wired_common_data common; - int sock; /* raw packet socket for driver access */ int dhcp_sock; /* socket for dhcp packets */ int use_pae_group_addr; - - int pf_sock; - int membership, multi, iff_allmulti, iff_up; }; @@ -85,34 +78,6 @@ struct dhcp_message { }; -static int wired_multicast_membership(int sock, int ifindex, - const u8 *addr, int add) -{ -#ifdef __linux__ - struct packet_mreq mreq; - - if (sock < 0) - return -1; - - os_memset(&mreq, 0, sizeof(mreq)); - mreq.mr_ifindex = ifindex; - mreq.mr_type = PACKET_MR_MULTICAST; - mreq.mr_alen = ETH_ALEN; - os_memcpy(mreq.mr_address, addr, ETH_ALEN); - - if (setsockopt(sock, SOL_PACKET, - add ? PACKET_ADD_MEMBERSHIP : PACKET_DROP_MEMBERSHIP, - &mreq, sizeof(mreq)) < 0) { - wpa_printf(MSG_ERROR, "setsockopt: %s", strerror(errno)); - return -1; - } - return 0; -#else /* __linux__ */ - return -1; -#endif /* __linux__ */ -} - - #ifdef __linux__ static void handle_data(void *ctx, unsigned char *buf, size_t len) { @@ -133,16 +98,16 @@ static void handle_data(void *ctx, unsigned char *buf, size_t len) hdr = (struct ieee8023_hdr *) buf; switch (ntohs(hdr->ethertype)) { - case ETH_P_PAE: - wpa_printf(MSG_MSGDUMP, "Received EAPOL packet"); - sa = hdr->src; - os_memset(&event, 0, sizeof(event)); - event.new_sta.addr = sa; - wpa_supplicant_event(ctx, EVENT_NEW_STA, &event); - - pos = (u8 *) (hdr + 1); - left = len - sizeof(*hdr); - drv_event_eapol_rx(ctx, sa, pos, left); + case ETH_P_PAE: + wpa_printf(MSG_MSGDUMP, "Received EAPOL packet"); + sa = hdr->src; + os_memset(&event, 0, sizeof(event)); + event.new_sta.addr = sa; + wpa_supplicant_event(ctx, EVENT_NEW_STA, &event); + + pos = (u8 *) (hdr + 1); + left = len - sizeof(*hdr); + drv_event_eapol_rx(ctx, sa, pos, left); break; default: @@ -210,21 +175,22 @@ static int wired_init_sockets(struct wpa_driver_wired_data *drv, u8 *own_addr) struct sockaddr_in addr2; int n = 1; - drv->sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_PAE)); - if (drv->sock < 0) { + drv->common.sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_PAE)); + if (drv->common.sock < 0) { wpa_printf(MSG_ERROR, "socket[PF_PACKET,SOCK_RAW]: %s", strerror(errno)); return -1; } - if (eloop_register_read_sock(drv->sock, handle_read, drv->ctx, NULL)) { + if (eloop_register_read_sock(drv->common.sock, handle_read, + drv->common.ctx, NULL)) { wpa_printf(MSG_INFO, "Could not register read socket"); return -1; } os_memset(&ifr, 0, sizeof(ifr)); - os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name)); - if (ioctl(drv->sock, SIOCGIFINDEX, &ifr) != 0) { + os_strlcpy(ifr.ifr_name, drv->common.ifname, sizeof(ifr.ifr_name)); + if (ioctl(drv->common.sock, SIOCGIFINDEX, &ifr) != 0) { wpa_printf(MSG_ERROR, "ioctl(SIOCGIFINDEX): %s", strerror(errno)); return -1; @@ -236,13 +202,14 @@ static int wired_init_sockets(struct wpa_driver_wired_data *drv, u8 *own_addr) wpa_printf(MSG_DEBUG, "Opening raw packet socket for ifindex %d", addr.sll_ifindex); - if (bind(drv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { + if (bind(drv->common.sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) + { wpa_printf(MSG_ERROR, "bind: %s", strerror(errno)); return -1; } /* filter multicast address */ - if (wired_multicast_membership(drv->sock, ifr.ifr_ifindex, + if (wired_multicast_membership(drv->common.sock, ifr.ifr_ifindex, pae_group_addr, 1) < 0) { wpa_printf(MSG_ERROR, "wired: Failed to add multicast group " "membership"); @@ -250,8 +217,8 @@ static int wired_init_sockets(struct wpa_driver_wired_data *drv, u8 *own_addr) } os_memset(&ifr, 0, sizeof(ifr)); - os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name)); - if (ioctl(drv->sock, SIOCGIFHWADDR, &ifr) != 0) { + os_strlcpy(ifr.ifr_name, drv->common.ifname, sizeof(ifr.ifr_name)); + if (ioctl(drv->common.sock, SIOCGIFHWADDR, &ifr) != 0) { wpa_printf(MSG_ERROR, "ioctl(SIOCGIFHWADDR): %s", strerror(errno)); return -1; @@ -271,8 +238,8 @@ static int wired_init_sockets(struct wpa_driver_wired_data *drv, u8 *own_addr) return -1; } - if (eloop_register_read_sock(drv->dhcp_sock, handle_dhcp, drv->ctx, - NULL)) { + if (eloop_register_read_sock(drv->dhcp_sock, handle_dhcp, + drv->common.ctx, NULL)) { wpa_printf(MSG_INFO, "Could not register read socket"); return -1; } @@ -296,7 +263,7 @@ static int wired_init_sockets(struct wpa_driver_wired_data *drv, u8 *own_addr) } os_memset(&ifr, 0, sizeof(ifr)); - os_strlcpy(ifr.ifr_ifrn.ifrn_name, drv->ifname, IFNAMSIZ); + os_strlcpy(ifr.ifr_ifrn.ifrn_name, drv->common.ifname, IFNAMSIZ); if (setsockopt(drv->dhcp_sock, SOL_SOCKET, SO_BINDTODEVICE, (char *) &ifr, sizeof(ifr)) < 0) { wpa_printf(MSG_ERROR, @@ -345,7 +312,7 @@ static int wired_send_eapol(void *priv, const u8 *addr, pos = (u8 *) (hdr + 1); os_memcpy(pos, data, data_len); - res = send(drv->sock, (u8 *) hdr, len, 0); + res = send(drv->common.sock, (u8 *) hdr, len, 0); os_free(hdr); if (res < 0) { @@ -370,8 +337,9 @@ static void * wired_driver_hapd_init(struct hostapd_data *hapd, return NULL; } - drv->ctx = hapd; - os_strlcpy(drv->ifname, params->ifname, sizeof(drv->ifname)); + drv->common.ctx = hapd; + os_strlcpy(drv->common.ifname, params->ifname, + sizeof(drv->common.ifname)); drv->use_pae_group_addr = params->use_pae_group_addr; if (wired_init_sockets(drv, params->own_addr)) { @@ -387,9 +355,9 @@ static void wired_driver_hapd_deinit(void *priv) { struct wpa_driver_wired_data *drv = priv; - if (drv->sock >= 0) { - eloop_unregister_read_sock(drv->sock); - close(drv->sock); + if (drv->common.sock >= 0) { + eloop_unregister_read_sock(drv->common.sock); + close(drv->common.sock); } if (drv->dhcp_sock >= 0) { @@ -401,227 +369,18 @@ static void wired_driver_hapd_deinit(void *priv) } -static int wpa_driver_wired_get_ssid(void *priv, u8 *ssid) -{ - ssid[0] = 0; - return 0; -} - - -static int wpa_driver_wired_get_bssid(void *priv, u8 *bssid) -{ - /* Report PAE group address as the "BSSID" for wired connection. */ - os_memcpy(bssid, pae_group_addr, ETH_ALEN); - return 0; -} - - -static int wpa_driver_wired_get_capa(void *priv, struct wpa_driver_capa *capa) -{ - os_memset(capa, 0, sizeof(*capa)); - capa->flags = WPA_DRIVER_FLAGS_WIRED; - return 0; -} - - -static int wpa_driver_wired_get_ifflags(const char *ifname, int *flags) -{ - struct ifreq ifr; - int s; - - s = socket(PF_INET, SOCK_DGRAM, 0); - if (s < 0) { - wpa_printf(MSG_ERROR, "socket: %s", strerror(errno)); - return -1; - } - - os_memset(&ifr, 0, sizeof(ifr)); - os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ); - if (ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) { - wpa_printf(MSG_ERROR, "ioctl[SIOCGIFFLAGS]: %s", - strerror(errno)); - close(s); - return -1; - } - close(s); - *flags = ifr.ifr_flags & 0xffff; - return 0; -} - - -static int wpa_driver_wired_set_ifflags(const char *ifname, int flags) -{ - struct ifreq ifr; - int s; - - s = socket(PF_INET, SOCK_DGRAM, 0); - if (s < 0) { - wpa_printf(MSG_ERROR, "socket: %s", strerror(errno)); - return -1; - } - - os_memset(&ifr, 0, sizeof(ifr)); - os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ); - ifr.ifr_flags = flags & 0xffff; - if (ioctl(s, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) { - wpa_printf(MSG_ERROR, "ioctl[SIOCSIFFLAGS]: %s", - strerror(errno)); - close(s); - return -1; - } - close(s); - return 0; -} - - -#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__) -static int wpa_driver_wired_get_ifstatus(const char *ifname, int *status) -{ - struct ifmediareq ifmr; - int s; - - s = socket(PF_INET, SOCK_DGRAM, 0); - if (s < 0) { - wpa_printf(MSG_ERROR, "socket: %s", strerror(errno)); - return -1; - } - - os_memset(&ifmr, 0, sizeof(ifmr)); - os_strlcpy(ifmr.ifm_name, ifname, IFNAMSIZ); - if (ioctl(s, SIOCGIFMEDIA, (caddr_t) &ifmr) < 0) { - wpa_printf(MSG_ERROR, "ioctl[SIOCGIFMEDIA]: %s", - strerror(errno)); - close(s); - return -1; - } - close(s); - *status = (ifmr.ifm_status & (IFM_ACTIVE | IFM_AVALID)) == - (IFM_ACTIVE | IFM_AVALID); - - return 0; -} -#endif /* defined(__FreeBSD__) || defined(__DragonFly__) || defined(FreeBSD_kernel__) */ - - -static int wpa_driver_wired_multi(const char *ifname, const u8 *addr, int add) -{ - struct ifreq ifr; - int s; - -#ifdef __sun__ - return -1; -#endif /* __sun__ */ - - s = socket(PF_INET, SOCK_DGRAM, 0); - if (s < 0) { - wpa_printf(MSG_ERROR, "socket: %s", strerror(errno)); - return -1; - } - - os_memset(&ifr, 0, sizeof(ifr)); - os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ); -#ifdef __linux__ - ifr.ifr_hwaddr.sa_family = AF_UNSPEC; - os_memcpy(ifr.ifr_hwaddr.sa_data, addr, ETH_ALEN); -#endif /* __linux__ */ -#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__) - { - struct sockaddr_dl *dlp; - dlp = (struct sockaddr_dl *) &ifr.ifr_addr; - dlp->sdl_len = sizeof(struct sockaddr_dl); - dlp->sdl_family = AF_LINK; - dlp->sdl_index = 0; - dlp->sdl_nlen = 0; - dlp->sdl_alen = ETH_ALEN; - dlp->sdl_slen = 0; - os_memcpy(LLADDR(dlp), addr, ETH_ALEN); - } -#endif /* defined(__FreeBSD__) || defined(__DragonFly__) || defined(FreeBSD_kernel__) */ -#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__) - { - struct sockaddr *sap; - sap = (struct sockaddr *) &ifr.ifr_addr; - sap->sa_len = sizeof(struct sockaddr); - sap->sa_family = AF_UNSPEC; - os_memcpy(sap->sa_data, addr, ETH_ALEN); - } -#endif /* defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__) */ - - if (ioctl(s, add ? SIOCADDMULTI : SIOCDELMULTI, (caddr_t) &ifr) < 0) { - wpa_printf(MSG_ERROR, "ioctl[SIOC{ADD/DEL}MULTI]: %s", - strerror(errno)); - close(s); - return -1; - } - close(s); - return 0; -} - - static void * wpa_driver_wired_init(void *ctx, const char *ifname) { struct wpa_driver_wired_data *drv; - int flags; drv = os_zalloc(sizeof(*drv)); if (drv == NULL) return NULL; - os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname)); - drv->ctx = ctx; - -#ifdef __linux__ - drv->pf_sock = socket(PF_PACKET, SOCK_DGRAM, 0); - if (drv->pf_sock < 0) - wpa_printf(MSG_ERROR, "socket(PF_PACKET): %s", strerror(errno)); -#else /* __linux__ */ - drv->pf_sock = -1; -#endif /* __linux__ */ - if (wpa_driver_wired_get_ifflags(ifname, &flags) == 0 && - !(flags & IFF_UP) && - wpa_driver_wired_set_ifflags(ifname, flags | IFF_UP) == 0) { - drv->iff_up = 1; - } - - if (wired_multicast_membership(drv->pf_sock, - if_nametoindex(drv->ifname), - pae_group_addr, 1) == 0) { - wpa_printf(MSG_DEBUG, "%s: Added multicast membership with " - "packet socket", __func__); - drv->membership = 1; - } else if (wpa_driver_wired_multi(ifname, pae_group_addr, 1) == 0) { - wpa_printf(MSG_DEBUG, "%s: Added multicast membership with " - "SIOCADDMULTI", __func__); - drv->multi = 1; - } else if (wpa_driver_wired_get_ifflags(ifname, &flags) < 0) { - wpa_printf(MSG_INFO, "%s: Could not get interface " - "flags", __func__); - os_free(drv); - return NULL; - } else if (flags & IFF_ALLMULTI) { - wpa_printf(MSG_DEBUG, "%s: Interface is already configured " - "for multicast", __func__); - } else if (wpa_driver_wired_set_ifflags(ifname, - flags | IFF_ALLMULTI) < 0) { - wpa_printf(MSG_INFO, "%s: Failed to enable allmulti", - __func__); + if (driver_wired_init_common(&drv->common, ifname, ctx) < 0) { os_free(drv); return NULL; - } else { - wpa_printf(MSG_DEBUG, "%s: Enabled allmulti mode", - __func__); - drv->iff_allmulti = 1; } -#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__) - { - int status; - wpa_printf(MSG_DEBUG, "%s: waiting for link to become active", - __func__); - while (wpa_driver_wired_get_ifstatus(ifname, &status) == 0 && - status == 0) - sleep(1); - } -#endif /* defined(__FreeBSD__) || defined(__DragonFly__) || defined(FreeBSD_kernel__) */ return drv; } @@ -630,41 +389,8 @@ static void * wpa_driver_wired_init(void *ctx, const char *ifname) static void wpa_driver_wired_deinit(void *priv) { struct wpa_driver_wired_data *drv = priv; - int flags; - - if (drv->membership && - wired_multicast_membership(drv->pf_sock, - if_nametoindex(drv->ifname), - pae_group_addr, 0) < 0) { - wpa_printf(MSG_DEBUG, "%s: Failed to remove PAE multicast " - "group (PACKET)", __func__); - } - - if (drv->multi && - wpa_driver_wired_multi(drv->ifname, pae_group_addr, 0) < 0) { - wpa_printf(MSG_DEBUG, "%s: Failed to remove PAE multicast " - "group (SIOCDELMULTI)", __func__); - } - - if (drv->iff_allmulti && - (wpa_driver_wired_get_ifflags(drv->ifname, &flags) < 0 || - wpa_driver_wired_set_ifflags(drv->ifname, - flags & ~IFF_ALLMULTI) < 0)) { - wpa_printf(MSG_DEBUG, "%s: Failed to disable allmulti mode", - __func__); - } - - if (drv->iff_up && - wpa_driver_wired_get_ifflags(drv->ifname, &flags) == 0 && - (flags & IFF_UP) && - wpa_driver_wired_set_ifflags(drv->ifname, flags & ~IFF_UP) < 0) { - wpa_printf(MSG_DEBUG, "%s: Failed to set the interface down", - __func__); - } - - if (drv->pf_sock != -1) - close(drv->pf_sock); + driver_wired_deinit_common(&drv->common); os_free(drv); } @@ -675,9 +401,9 @@ const struct wpa_driver_ops wpa_driver_wired_ops = { .hapd_init = wired_driver_hapd_init, .hapd_deinit = wired_driver_hapd_deinit, .hapd_send_eapol = wired_send_eapol, - .get_ssid = wpa_driver_wired_get_ssid, - .get_bssid = wpa_driver_wired_get_bssid, - .get_capa = wpa_driver_wired_get_capa, + .get_ssid = driver_wired_get_ssid, + .get_bssid = driver_wired_get_bssid, + .get_capa = driver_wired_get_capa, .init = wpa_driver_wired_init, .deinit = wpa_driver_wired_deinit, }; diff --git a/freebsd/contrib/wpa/src/drivers/driver_wired_common.c b/freebsd/contrib/wpa/src/drivers/driver_wired_common.c new file mode 100644 index 00000000..e9aab5df --- /dev/null +++ b/freebsd/contrib/wpa/src/drivers/driver_wired_common.c @@ -0,0 +1,324 @@ +#include <machine/rtems-bsd-user-space.h> + +/* + * Common functions for Wired Ethernet driver interfaces + * Copyright (c) 2005-2009, Jouni Malinen <j@w1.fi> + * Copyright (c) 2004, Gunter Burchardt <tira@isx.de> + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "includes.h" + +#include "common.h" +#include "eloop.h" +#include "driver.h" +#include "driver_wired_common.h" + +#include <sys/ioctl.h> +#include <net/if.h> +#ifdef __linux__ +#include <netpacket/packet.h> +#include <net/if_arp.h> +#include <net/if.h> +#endif /* __linux__ */ +#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__) +#include <net/if_dl.h> +#include <net/if_media.h> +#endif /* defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__) */ +#ifdef __sun__ +#include <sys/sockio.h> +#endif /* __sun__ */ + + +static int driver_wired_get_ifflags(const char *ifname, int *flags) +{ + struct ifreq ifr; + int s; + + s = socket(PF_INET, SOCK_DGRAM, 0); + if (s < 0) { + wpa_printf(MSG_ERROR, "socket: %s", strerror(errno)); + return -1; + } + + os_memset(&ifr, 0, sizeof(ifr)); + os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ); + if (ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) { + wpa_printf(MSG_ERROR, "ioctl[SIOCGIFFLAGS]: %s", + strerror(errno)); + close(s); + return -1; + } + close(s); + *flags = ifr.ifr_flags & 0xffff; + return 0; +} + + +static int driver_wired_set_ifflags(const char *ifname, int flags) +{ + struct ifreq ifr; + int s; + + s = socket(PF_INET, SOCK_DGRAM, 0); + if (s < 0) { + wpa_printf(MSG_ERROR, "socket: %s", strerror(errno)); + return -1; + } + + os_memset(&ifr, 0, sizeof(ifr)); + os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ); + ifr.ifr_flags = flags & 0xffff; + if (ioctl(s, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) { + wpa_printf(MSG_ERROR, "ioctl[SIOCSIFFLAGS]: %s", + strerror(errno)); + close(s); + return -1; + } + close(s); + return 0; +} + + +static int driver_wired_multi(const char *ifname, const u8 *addr, int add) +{ + struct ifreq ifr; + int s; + +#ifdef __sun__ + return -1; +#endif /* __sun__ */ + + s = socket(PF_INET, SOCK_DGRAM, 0); + if (s < 0) { + wpa_printf(MSG_ERROR, "socket: %s", strerror(errno)); + return -1; + } + + os_memset(&ifr, 0, sizeof(ifr)); + os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ); +#ifdef __linux__ + ifr.ifr_hwaddr.sa_family = AF_UNSPEC; + os_memcpy(ifr.ifr_hwaddr.sa_data, addr, ETH_ALEN); +#endif /* __linux__ */ +#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__) + { + struct sockaddr_dl *dlp; + + dlp = (struct sockaddr_dl *) &ifr.ifr_addr; + dlp->sdl_len = sizeof(struct sockaddr_dl); + dlp->sdl_family = AF_LINK; + dlp->sdl_index = 0; + dlp->sdl_nlen = 0; + dlp->sdl_alen = ETH_ALEN; + dlp->sdl_slen = 0; + os_memcpy(LLADDR(dlp), addr, ETH_ALEN); + } +#endif /* defined(__FreeBSD__) || defined(__DragonFly__) || defined(FreeBSD_kernel__) */ +#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__) + { + struct sockaddr *sap; + + sap = (struct sockaddr *) &ifr.ifr_addr; + sap->sa_len = sizeof(struct sockaddr); + sap->sa_family = AF_UNSPEC; + os_memcpy(sap->sa_data, addr, ETH_ALEN); + } +#endif /* defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__) */ + + if (ioctl(s, add ? SIOCADDMULTI : SIOCDELMULTI, (caddr_t) &ifr) < 0) { + wpa_printf(MSG_ERROR, "ioctl[SIOC{ADD/DEL}MULTI]: %s", + strerror(errno)); + close(s); + return -1; + } + close(s); + return 0; +} + + +int wired_multicast_membership(int sock, int ifindex, const u8 *addr, int add) +{ +#ifdef __linux__ + struct packet_mreq mreq; + + if (sock < 0) + return -1; + + os_memset(&mreq, 0, sizeof(mreq)); + mreq.mr_ifindex = ifindex; + mreq.mr_type = PACKET_MR_MULTICAST; + mreq.mr_alen = ETH_ALEN; + os_memcpy(mreq.mr_address, addr, ETH_ALEN); + + if (setsockopt(sock, SOL_PACKET, + add ? PACKET_ADD_MEMBERSHIP : PACKET_DROP_MEMBERSHIP, + &mreq, sizeof(mreq)) < 0) { + wpa_printf(MSG_ERROR, "setsockopt: %s", strerror(errno)); + return -1; + } + return 0; +#else /* __linux__ */ + return -1; +#endif /* __linux__ */ +} + + +int driver_wired_get_ssid(void *priv, u8 *ssid) +{ + ssid[0] = 0; + return 0; +} + + +int driver_wired_get_bssid(void *priv, u8 *bssid) +{ + /* Report PAE group address as the "BSSID" for wired connection. */ + os_memcpy(bssid, pae_group_addr, ETH_ALEN); + return 0; +} + + +int driver_wired_get_capa(void *priv, struct wpa_driver_capa *capa) +{ + os_memset(capa, 0, sizeof(*capa)); + capa->flags = WPA_DRIVER_FLAGS_WIRED; + return 0; +} + + +#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__) +static int driver_wired_get_ifstatus(const char *ifname, int *status) +{ + struct ifmediareq ifmr; + int s; + + s = socket(PF_INET, SOCK_DGRAM, 0); + if (s < 0) { + wpa_printf(MSG_ERROR, "socket: %s", strerror(errno)); + return -1; + } + + os_memset(&ifmr, 0, sizeof(ifmr)); + os_strlcpy(ifmr.ifm_name, ifname, IFNAMSIZ); + if (ioctl(s, SIOCGIFMEDIA, (caddr_t) &ifmr) < 0) { + wpa_printf(MSG_ERROR, "ioctl[SIOCGIFMEDIA]: %s", + strerror(errno)); + close(s); + return -1; + } + close(s); + *status = (ifmr.ifm_status & (IFM_ACTIVE | IFM_AVALID)) == + (IFM_ACTIVE | IFM_AVALID); + + return 0; +} +#endif /* defined(__FreeBSD__) || defined(__DragonFly__) || defined(FreeBSD_kernel__) */ + + +int driver_wired_init_common(struct driver_wired_common_data *common, + const char *ifname, void *ctx) +{ + int flags; + + os_strlcpy(common->ifname, ifname, sizeof(common->ifname)); + common->ctx = ctx; + +#ifdef __linux__ + common->pf_sock = socket(PF_PACKET, SOCK_DGRAM, 0); + if (common->pf_sock < 0) + wpa_printf(MSG_ERROR, "socket(PF_PACKET): %s", strerror(errno)); +#else /* __linux__ */ + common->pf_sock = -1; +#endif /* __linux__ */ + + if (driver_wired_get_ifflags(ifname, &flags) == 0 && + !(flags & IFF_UP) && + driver_wired_set_ifflags(ifname, flags | IFF_UP) == 0) + common->iff_up = 1; + + if (wired_multicast_membership(common->pf_sock, + if_nametoindex(common->ifname), + pae_group_addr, 1) == 0) { + wpa_printf(MSG_DEBUG, + "%s: Added multicast membership with packet socket", + __func__); + common->membership = 1; + } else if (driver_wired_multi(ifname, pae_group_addr, 1) == 0) { + wpa_printf(MSG_DEBUG, + "%s: Added multicast membership with SIOCADDMULTI", + __func__); + common->multi = 1; + } else if (driver_wired_get_ifflags(ifname, &flags) < 0) { + wpa_printf(MSG_INFO, "%s: Could not get interface flags", + __func__); + return -1; + } else if (flags & IFF_ALLMULTI) { + wpa_printf(MSG_DEBUG, + "%s: Interface is already configured for multicast", + __func__); + } else if (driver_wired_set_ifflags(ifname, + flags | IFF_ALLMULTI) < 0) { + wpa_printf(MSG_INFO, "%s: Failed to enable allmulti", __func__); + return -1; + } else { + wpa_printf(MSG_DEBUG, "%s: Enabled allmulti mode", __func__); + common->iff_allmulti = 1; + } +#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__) + { + int status; + + wpa_printf(MSG_DEBUG, "%s: waiting for link to become active", + __func__); + while (driver_wired_get_ifstatus(ifname, &status) == 0 && + status == 0) + sleep(1); + } +#endif /* defined(__FreeBSD__) || defined(__DragonFly__) || defined(FreeBSD_kernel__) */ + + return 0; +} + + +void driver_wired_deinit_common(struct driver_wired_common_data *common) +{ + int flags; + + if (common->membership && + wired_multicast_membership(common->pf_sock, + if_nametoindex(common->ifname), + pae_group_addr, 0) < 0) { + wpa_printf(MSG_DEBUG, + "%s: Failed to remove PAE multicast group (PACKET)", + __func__); + } + + if (common->multi && + driver_wired_multi(common->ifname, pae_group_addr, 0) < 0) { + wpa_printf(MSG_DEBUG, + "%s: Failed to remove PAE multicast group (SIOCDELMULTI)", + __func__); + } + + if (common->iff_allmulti && + (driver_wired_get_ifflags(common->ifname, &flags) < 0 || + driver_wired_set_ifflags(common->ifname, + flags & ~IFF_ALLMULTI) < 0)) { + wpa_printf(MSG_DEBUG, "%s: Failed to disable allmulti mode", + __func__); + } + + if (common->iff_up && + driver_wired_get_ifflags(common->ifname, &flags) == 0 && + (flags & IFF_UP) && + driver_wired_set_ifflags(common->ifname, flags & ~IFF_UP) < 0) { + wpa_printf(MSG_DEBUG, "%s: Failed to set the interface down", + __func__); + } + + if (common->pf_sock != -1) + close(common->pf_sock); +} diff --git a/freebsd/contrib/wpa/src/drivers/driver_wired_common.h b/freebsd/contrib/wpa/src/drivers/driver_wired_common.h new file mode 100644 index 00000000..2bb0710b --- /dev/null +++ b/freebsd/contrib/wpa/src/drivers/driver_wired_common.h @@ -0,0 +1,34 @@ +/* + * Common definitions for Wired Ethernet driver interfaces + * Copyright (c) 2005-2009, Jouni Malinen <j@w1.fi> + * Copyright (c) 2004, Gunter Burchardt <tira@isx.de> + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef DRIVER_WIRED_COMMON_H +#define DRIVER_WIRED_COMMON_H + +struct driver_wired_common_data { + char ifname[IFNAMSIZ + 1]; + void *ctx; + + int sock; /* raw packet socket for driver access */ + int pf_sock; + int membership, multi, iff_allmulti, iff_up; +}; + +static const u8 pae_group_addr[ETH_ALEN] = +{ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03 }; + +int wired_multicast_membership(int sock, int ifindex, const u8 *addr, int add); +int driver_wired_get_ssid(void *priv, u8 *ssid); +int driver_wired_get_bssid(void *priv, u8 *bssid); +int driver_wired_get_capa(void *priv, struct wpa_driver_capa *capa); + +int driver_wired_init_common(struct driver_wired_common_data *common, + const char *ifname, void *ctx); +void driver_wired_deinit_common(struct driver_wired_common_data *common); + +#endif /* DRIVER_WIRED_COMMON_H */ diff --git a/freebsd/contrib/wpa/src/drivers/drivers.c b/freebsd/contrib/wpa/src/drivers/drivers.c index ac83600e..0b9f3998 100644 --- a/freebsd/contrib/wpa/src/drivers/drivers.c +++ b/freebsd/contrib/wpa/src/drivers/drivers.c @@ -36,6 +36,9 @@ const struct wpa_driver_ops *const wpa_drivers[] = #ifdef CONFIG_DRIVER_WIRED &wpa_driver_wired_ops, #endif /* CONFIG_DRIVER_WIRED */ +#ifdef CONFIG_DRIVER_MACSEC_LINUX + &wpa_driver_macsec_linux_ops, +#endif /* CONFIG_DRIVER_MACSEC_LINUX */ #ifdef CONFIG_DRIVER_MACSEC_QCA &wpa_driver_macsec_qca_ops, #endif /* CONFIG_DRIVER_MACSEC_QCA */ diff --git a/freebsd/contrib/wpa/src/eap_peer/eap.c b/freebsd/contrib/wpa/src/eap_peer/eap.c index 6a183071..c682b063 100644 --- a/freebsd/contrib/wpa/src/eap_peer/eap.c +++ b/freebsd/contrib/wpa/src/eap_peer/eap.c @@ -97,6 +97,14 @@ static void eap_notify_status(struct eap_sm *sm, const char *status, } +static void eap_report_error(struct eap_sm *sm, int error_code) +{ + wpa_printf(MSG_DEBUG, "EAP: Error notification: %d", error_code); + if (sm->eapol_cb->notify_eap_error) + sm->eapol_cb->notify_eap_error(sm->eapol_ctx, error_code); +} + + static void eap_sm_free_key(struct eap_sm *sm) { if (sm->eapKeyData) { @@ -123,15 +131,17 @@ static void eap_deinit_prev_method(struct eap_sm *sm, const char *txt) /** - * eap_allowed_method - Check whether EAP method is allowed + * eap_config_allowed_method - Check whether EAP method is allowed * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() + * @config: EAP configuration * @vendor: Vendor-Id for expanded types or 0 = IETF for legacy types * @method: EAP type * Returns: 1 = allowed EAP method, 0 = not allowed */ -int eap_allowed_method(struct eap_sm *sm, int vendor, u32 method) +static int eap_config_allowed_method(struct eap_sm *sm, + struct eap_peer_config *config, + int vendor, u32 method) { - struct eap_peer_config *config = eap_get_config(sm); int i; struct eap_method_type *m; @@ -148,6 +158,57 @@ int eap_allowed_method(struct eap_sm *sm, int vendor, u32 method) } +/** + * eap_allowed_method - Check whether EAP method is allowed + * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() + * @vendor: Vendor-Id for expanded types or 0 = IETF for legacy types + * @method: EAP type + * Returns: 1 = allowed EAP method, 0 = not allowed + */ +int eap_allowed_method(struct eap_sm *sm, int vendor, u32 method) +{ + return eap_config_allowed_method(sm, eap_get_config(sm), vendor, + method); +} + + +#if defined(PCSC_FUNCS) || defined(CONFIG_EAP_PROXY) +static int eap_sm_append_3gpp_realm(struct eap_sm *sm, char *imsi, + size_t max_len, size_t *imsi_len, + int mnc_len) +{ + char *pos, mnc[4]; + + if (*imsi_len + 36 > max_len) { + wpa_printf(MSG_WARNING, "No room for realm in IMSI buffer"); + return -1; + } + + if (mnc_len != 2 && mnc_len != 3) + mnc_len = 3; + + if (mnc_len == 2) { + mnc[0] = '0'; + mnc[1] = imsi[3]; + mnc[2] = imsi[4]; + } else if (mnc_len == 3) { + mnc[0] = imsi[3]; + mnc[1] = imsi[4]; + mnc[2] = imsi[5]; + } + mnc[3] = '\0'; + + pos = imsi + *imsi_len; + pos += os_snprintf(pos, imsi + max_len - pos, + "@wlan.mnc%s.mcc%c%c%c.3gppnetwork.org", + mnc, imsi[0], imsi[1], imsi[2]); + *imsi_len = pos - imsi; + + return 0; +} +#endif /* PCSC_FUNCS || CONFIG_EAP_PROXY */ + + /* * This state initializes state machine variables when the machine is * activated (portEnabled = TRUE). This is also used when re-starting @@ -373,9 +434,8 @@ nak: #ifdef CONFIG_ERP -static char * eap_home_realm(struct eap_sm *sm) +static char * eap_get_realm(struct eap_sm *sm, struct eap_peer_config *config) { - struct eap_peer_config *config = eap_get_config(sm); char *realm; size_t i, realm_len; @@ -415,7 +475,51 @@ static char * eap_home_realm(struct eap_sm *sm) } } - return os_strdup(""); +#ifdef CONFIG_EAP_PROXY + /* When identity is not provided in the config, build the realm from + * IMSI for eap_proxy based methods. + */ + if (!config->identity && !config->anonymous_identity && + sm->eapol_cb->get_imsi && + (eap_config_allowed_method(sm, config, EAP_VENDOR_IETF, + EAP_TYPE_SIM) || + eap_config_allowed_method(sm, config, EAP_VENDOR_IETF, + EAP_TYPE_AKA) || + eap_config_allowed_method(sm, config, EAP_VENDOR_IETF, + EAP_TYPE_AKA_PRIME))) { + char imsi[100]; + size_t imsi_len; + int mnc_len, pos; + + wpa_printf(MSG_DEBUG, "EAP: Build realm from IMSI (eap_proxy)"); + mnc_len = sm->eapol_cb->get_imsi(sm->eapol_ctx, config->sim_num, + imsi, &imsi_len); + if (mnc_len < 0) + return NULL; + + pos = imsi_len + 1; /* points to the beginning of the realm */ + if (eap_sm_append_3gpp_realm(sm, imsi, sizeof(imsi), &imsi_len, + mnc_len) < 0) { + wpa_printf(MSG_WARNING, "Could not append realm"); + return NULL; + } + + realm = os_strdup(&imsi[pos]); + if (!realm) + return NULL; + + wpa_printf(MSG_DEBUG, "EAP: Generated realm '%s'", realm); + return realm; + } +#endif /* CONFIG_EAP_PROXY */ + + return NULL; +} + + +static char * eap_home_realm(struct eap_sm *sm) +{ + return eap_get_realm(sm, eap_get_config(sm)); } @@ -471,6 +575,89 @@ static void eap_erp_remove_keys_realm(struct eap_sm *sm, const char *realm) } } + +int eap_peer_update_erp_next_seq_num(struct eap_sm *sm, u16 next_seq_num) +{ + struct eap_erp_key *erp; + char *home_realm; + + home_realm = eap_home_realm(sm); + if (!home_realm || os_strlen(home_realm) == 0) { + os_free(home_realm); + return -1; + } + + erp = eap_erp_get_key(sm, home_realm); + if (!erp) { + wpa_printf(MSG_DEBUG, + "EAP: Failed to find ERP key for realm: %s", + home_realm); + os_free(home_realm); + return -1; + } + + if ((u32) next_seq_num < erp->next_seq) { + /* Sequence number has wrapped around, clear this ERP + * info and do a full auth next time. + */ + eap_peer_erp_free_key(erp); + } else { + erp->next_seq = (u32) next_seq_num; + } + + os_free(home_realm); + return 0; +} + + +int eap_peer_get_erp_info(struct eap_sm *sm, struct eap_peer_config *config, + const u8 **username, size_t *username_len, + const u8 **realm, size_t *realm_len, + u16 *erp_next_seq_num, const u8 **rrk, + size_t *rrk_len) +{ + struct eap_erp_key *erp; + char *home_realm; + char *pos; + + if (config) + home_realm = eap_get_realm(sm, config); + else + home_realm = eap_home_realm(sm); + if (!home_realm || os_strlen(home_realm) == 0) { + os_free(home_realm); + return -1; + } + + erp = eap_erp_get_key(sm, home_realm); + os_free(home_realm); + if (!erp) + return -1; + + if (erp->next_seq >= 65536) + return -1; /* SEQ has range of 0..65535 */ + + pos = os_strchr(erp->keyname_nai, '@'); + if (!pos) + return -1; /* this cannot really happen */ + *username_len = pos - erp->keyname_nai; + *username = (u8 *) erp->keyname_nai; + + pos++; + *realm_len = os_strlen(pos); + *realm = (u8 *) pos; + + *erp_next_seq_num = (u16) erp->next_seq; + + *rrk_len = erp->rRK_len; + *rrk = erp->rRK; + + if (*username_len == 0 || *realm_len == 0 || *rrk_len == 0) + return -1; + + return 0; +} + #endif /* CONFIG_ERP */ @@ -485,13 +672,20 @@ void eap_peer_erp_free_keys(struct eap_sm *sm) } -static void eap_peer_erp_init(struct eap_sm *sm) +/* Note: If ext_session and/or ext_emsk are passed to this function, they are + * expected to point to allocated memory and those allocations will be freed + * unconditionally. */ +void eap_peer_erp_init(struct eap_sm *sm, u8 *ext_session_id, + size_t ext_session_id_len, u8 *ext_emsk, + size_t ext_emsk_len) { #ifdef CONFIG_ERP u8 *emsk = NULL; size_t emsk_len = 0; + u8 *session_id = NULL; + size_t session_id_len = 0; u8 EMSKname[EAP_EMSK_NAME_LEN]; - u8 len[2]; + u8 len[2], ctx[3]; char *realm; size_t realm_len, nai_buf_len; struct eap_erp_key *erp = NULL; @@ -499,7 +693,7 @@ static void eap_peer_erp_init(struct eap_sm *sm) realm = eap_home_realm(sm); if (!realm) - return; + goto fail; realm_len = os_strlen(realm); wpa_printf(MSG_DEBUG, "EAP: Realm for ERP keyName-NAI: %s", realm); eap_erp_remove_keys_realm(sm, realm); @@ -519,7 +713,13 @@ static void eap_peer_erp_init(struct eap_sm *sm) if (erp == NULL) goto fail; - emsk = sm->m->get_emsk(sm, sm->eap_method_priv, &emsk_len); + if (ext_emsk) { + emsk = ext_emsk; + emsk_len = ext_emsk_len; + } else { + emsk = sm->m->get_emsk(sm, sm->eap_method_priv, &emsk_len); + } + if (!emsk || emsk_len == 0 || emsk_len > ERP_MAX_KEY_LEN) { wpa_printf(MSG_DEBUG, "EAP: No suitable EMSK available for ERP"); @@ -528,10 +728,23 @@ static void eap_peer_erp_init(struct eap_sm *sm) wpa_hexdump_key(MSG_DEBUG, "EAP: EMSK", emsk, emsk_len); - WPA_PUT_BE16(len, 8); - if (hmac_sha256_kdf(sm->eapSessionId, sm->eapSessionIdLen, "EMSK", - len, sizeof(len), - EMSKname, EAP_EMSK_NAME_LEN) < 0) { + if (ext_session_id) { + session_id = ext_session_id; + session_id_len = ext_session_id_len; + } else { + session_id = sm->eapSessionId; + session_id_len = sm->eapSessionIdLen; + } + + if (!session_id || session_id_len == 0) { + wpa_printf(MSG_DEBUG, + "EAP: No suitable session id available for ERP"); + goto fail; + } + + WPA_PUT_BE16(len, EAP_EMSK_NAME_LEN); + if (hmac_sha256_kdf(session_id, session_id_len, "EMSK", len, + sizeof(len), EMSKname, EAP_EMSK_NAME_LEN) < 0) { wpa_printf(MSG_DEBUG, "EAP: Could not derive EMSKname"); goto fail; } @@ -552,9 +765,11 @@ static void eap_peer_erp_init(struct eap_sm *sm) erp->rRK_len = emsk_len; wpa_hexdump_key(MSG_DEBUG, "EAP: ERP rRK", erp->rRK, erp->rRK_len); + ctx[0] = EAP_ERP_CS_HMAC_SHA256_128; + WPA_PUT_BE16(&ctx[1], erp->rRK_len); if (hmac_sha256_kdf(erp->rRK, erp->rRK_len, - "EAP Re-authentication Integrity Key@ietf.org", - len, sizeof(len), erp->rIK, erp->rRK_len) < 0) { + "Re-authentication Integrity Key@ietf.org", + ctx, sizeof(ctx), erp->rIK, erp->rRK_len) < 0) { wpa_printf(MSG_DEBUG, "EAP: Could not derive rIK for ERP"); goto fail; } @@ -565,7 +780,11 @@ static void eap_peer_erp_init(struct eap_sm *sm) dl_list_add(&sm->erp_keys, &erp->list); erp = NULL; fail: - bin_clear_free(emsk, emsk_len); + if (ext_emsk) + bin_clear_free(ext_emsk, ext_emsk_len); + else + bin_clear_free(emsk, emsk_len); + bin_clear_free(ext_session_id, ext_session_id_len); bin_clear_free(erp, sizeof(*erp)); os_free(realm); #endif /* CONFIG_ERP */ @@ -573,8 +792,7 @@ fail: #ifdef CONFIG_ERP -static int eap_peer_erp_reauth_start(struct eap_sm *sm, - const struct eap_hdr *hdr, size_t len) +struct wpabuf * eap_peer_build_erp_reauth_start(struct eap_sm *sm, u8 eap_id) { char *realm; struct eap_erp_key *erp; @@ -583,16 +801,16 @@ static int eap_peer_erp_reauth_start(struct eap_sm *sm, realm = eap_home_realm(sm); if (!realm) - return -1; + return NULL; erp = eap_erp_get_key(sm, realm); os_free(realm); realm = NULL; if (!erp) - return -1; + return NULL; if (erp->next_seq >= 65536) - return -1; /* SEQ has range of 0..65535 */ + return NULL; /* SEQ has range of 0..65535 */ /* TODO: check rRK lifetime expiration */ @@ -601,9 +819,9 @@ static int eap_peer_erp_reauth_start(struct eap_sm *sm, msg = eap_msg_alloc(EAP_VENDOR_IETF, (EapType) EAP_ERP_TYPE_REAUTH, 1 + 2 + 2 + os_strlen(erp->keyname_nai) + 1 + 16, - EAP_CODE_INITIATE, hdr->identifier); + EAP_CODE_INITIATE, eap_id); if (msg == NULL) - return -1; + return NULL; wpabuf_put_u8(msg, 0x20); /* Flags: R=0 B=0 L=1 */ wpabuf_put_be16(msg, erp->next_seq); @@ -617,13 +835,28 @@ static int eap_peer_erp_reauth_start(struct eap_sm *sm, if (hmac_sha256(erp->rIK, erp->rIK_len, wpabuf_head(msg), wpabuf_len(msg), hash) < 0) { wpabuf_free(msg); - return -1; + return NULL; } wpabuf_put_data(msg, hash, 16); - wpa_printf(MSG_DEBUG, "EAP: Sending EAP-Initiate/Re-auth"); sm->erp_seq = erp->next_seq; erp->next_seq++; + + wpa_hexdump_buf(MSG_DEBUG, "ERP: EAP-Initiate/Re-auth", msg); + + return msg; +} + + +static int eap_peer_erp_reauth_start(struct eap_sm *sm, u8 eap_id) +{ + struct wpabuf *msg; + + msg = eap_peer_build_erp_reauth_start(sm, eap_id); + if (!msg) + return -1; + + wpa_printf(MSG_DEBUG, "EAP: Sending EAP-Initiate/Re-auth"); wpabuf_free(sm->eapRespData); sm->eapRespData = msg; sm->reauthInit = TRUE; @@ -693,8 +926,6 @@ SM_STATE(EAP, METHOD) if (sm->m->isKeyAvailable && sm->m->getKey && sm->m->isKeyAvailable(sm, sm->eap_method_priv)) { - struct eap_peer_config *config = eap_get_config(sm); - eap_sm_free_key(sm); sm->eapKeyData = sm->m->getKey(sm, sm->eap_method_priv, &sm->eapKeyDataLen); @@ -707,8 +938,6 @@ SM_STATE(EAP, METHOD) wpa_hexdump(MSG_DEBUG, "EAP: Session-Id", sm->eapSessionId, sm->eapSessionIdLen); } - if (config->erp && sm->m->get_emsk && sm->eapSessionId) - eap_peer_erp_init(sm); } } @@ -806,6 +1035,8 @@ SM_STATE(EAP, RETRANSMIT) */ SM_STATE(EAP, SUCCESS) { + struct eap_peer_config *config = eap_get_config(sm); + SM_ENTRY(EAP, SUCCESS); if (sm->eapKeyData != NULL) sm->eapKeyAvailable = TRUE; @@ -828,6 +1059,11 @@ SM_STATE(EAP, SUCCESS) wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_SUCCESS "EAP authentication completed successfully"); + + if (config->erp && sm->m->get_emsk && sm->eapSessionId && + sm->m->isKeyAvailable && + sm->m->isKeyAvailable(sm, sm->eap_method_priv)) + eap_peer_erp_init(sm, NULL, 0, NULL, 0); } @@ -1278,48 +1514,6 @@ static int mnc_len_from_imsi(const char *imsi) } -static int eap_sm_append_3gpp_realm(struct eap_sm *sm, char *imsi, - size_t max_len, size_t *imsi_len) -{ - int mnc_len; - char *pos, mnc[4]; - - if (*imsi_len + 36 > max_len) { - wpa_printf(MSG_WARNING, "No room for realm in IMSI buffer"); - return -1; - } - - /* MNC (2 or 3 digits) */ - mnc_len = scard_get_mnc_len(sm->scard_ctx); - if (mnc_len < 0) - mnc_len = mnc_len_from_imsi(imsi); - if (mnc_len < 0) { - wpa_printf(MSG_INFO, "Failed to get MNC length from (U)SIM " - "assuming 3"); - mnc_len = 3; - } - - if (mnc_len == 2) { - mnc[0] = '0'; - mnc[1] = imsi[3]; - mnc[2] = imsi[4]; - } else if (mnc_len == 3) { - mnc[0] = imsi[3]; - mnc[1] = imsi[4]; - mnc[2] = imsi[5]; - } - mnc[3] = '\0'; - - pos = imsi + *imsi_len; - pos += os_snprintf(pos, imsi + max_len - pos, - "@wlan.mnc%s.mcc%c%c%c.3gppnetwork.org", - mnc, imsi[0], imsi[1], imsi[2]); - *imsi_len = pos - imsi; - - return 0; -} - - static int eap_sm_imsi_identity(struct eap_sm *sm, struct eap_peer_config *conf) { @@ -1327,7 +1521,7 @@ static int eap_sm_imsi_identity(struct eap_sm *sm, char imsi[100]; size_t imsi_len; struct eap_method_type *m = conf->eap_methods; - int i; + int i, mnc_len; imsi_len = sizeof(imsi); if (scard_get_imsi(sm->scard_ctx, imsi, &imsi_len)) { @@ -1342,7 +1536,18 @@ static int eap_sm_imsi_identity(struct eap_sm *sm, return -1; } - if (eap_sm_append_3gpp_realm(sm, imsi, sizeof(imsi), &imsi_len) < 0) { + /* MNC (2 or 3 digits) */ + mnc_len = scard_get_mnc_len(sm->scard_ctx); + if (mnc_len < 0) + mnc_len = mnc_len_from_imsi(imsi); + if (mnc_len < 0) { + wpa_printf(MSG_INFO, "Failed to get MNC length from (U)SIM " + "assuming 3"); + mnc_len = 3; + } + + if (eap_sm_append_3gpp_realm(sm, imsi, sizeof(imsi), &imsi_len, + mnc_len) < 0) { wpa_printf(MSG_WARNING, "Could not add realm to SIM identity"); return -1; } @@ -1568,7 +1773,7 @@ static void eap_peer_initiate(struct eap_sm *sm, const struct eap_hdr *hdr, /* TODO: Derivation of domain specific keys for local ER */ } - if (eap_peer_erp_reauth_start(sm, hdr, len) == 0) + if (eap_peer_erp_reauth_start(sm, hdr->identifier) == 0) return; invalid: @@ -1579,8 +1784,7 @@ invalid: } -static void eap_peer_finish(struct eap_sm *sm, const struct eap_hdr *hdr, - size_t len) +void eap_peer_finish(struct eap_sm *sm, const struct eap_hdr *hdr, size_t len) { #ifdef CONFIG_ERP const u8 *pos = (const u8 *) (hdr + 1); @@ -1830,6 +2034,15 @@ static void eap_sm_parseEapReq(struct eap_sm *sm, const struct wpabuf *req) case EAP_CODE_FAILURE: wpa_printf(MSG_DEBUG, "EAP: Received EAP-Failure"); eap_notify_status(sm, "completion", "failure"); + + /* Get the error code from method */ + if (sm->m && sm->m->get_error_code) { + int error_code; + + error_code = sm->m->get_error_code(sm->eap_method_priv); + if (error_code != NO_EAP_METHOD_ERROR) + eap_report_error(sm, error_code); + } sm->rxFailure = TRUE; break; case EAP_CODE_INITIATE: @@ -2233,6 +2446,7 @@ static void eap_sm_request(struct eap_sm *sm, enum wpa_ctrl_req_type field, config->pending_req_passphrase++; break; case WPA_CTRL_REQ_SIM: + config->pending_req_sim++; txt = msg; break; case WPA_CTRL_REQ_EXT_CERT_CHECK: diff --git a/freebsd/contrib/wpa/src/eap_peer/eap.h b/freebsd/contrib/wpa/src/eap_peer/eap.h index 1a645af8..d0837e37 100644 --- a/freebsd/contrib/wpa/src/eap_peer/eap.h +++ b/freebsd/contrib/wpa/src/eap_peer/eap.h @@ -246,12 +246,37 @@ struct eapol_callbacks { void (*notify_status)(void *ctx, const char *status, const char *parameter); + /** + * notify_eap_error - Report EAP method error code + * @ctx: eapol_ctx from eap_peer_sm_init() call + * @error_code: Error code from the used EAP method + */ + void (*notify_eap_error)(void *ctx, int error_code); + #ifdef CONFIG_EAP_PROXY /** * eap_proxy_cb - Callback signifying any updates from eap_proxy * @ctx: eapol_ctx from eap_peer_sm_init() call */ void (*eap_proxy_cb)(void *ctx); + + /** + * eap_proxy_notify_sim_status - Notification of SIM status change + * @ctx: eapol_ctx from eap_peer_sm_init() call + * @sim_state: One of enum value from sim_state + */ + void (*eap_proxy_notify_sim_status)(void *ctx, + enum eap_proxy_sim_state sim_state); + + /** + * get_imsi - Get the IMSI value from eap_proxy + * @ctx: eapol_ctx from eap_peer_sm_init() call + * @sim_num: SIM/USIM number to get the IMSI value for + * @imsi: Buffer for IMSI value + * @len: Buffer for returning IMSI length in octets + * Returns: MNC length (2 or 3) or -1 on error + */ + int (*get_imsi)(void *ctx, int sim_num, char *imsi, size_t *len); #endif /* CONFIG_EAP_PROXY */ /** @@ -348,6 +373,16 @@ void eap_sm_set_ext_pw_ctx(struct eap_sm *sm, struct ext_password_data *ext); void eap_set_anon_id(struct eap_sm *sm, const u8 *id, size_t len); int eap_peer_was_failure_expected(struct eap_sm *sm); void eap_peer_erp_free_keys(struct eap_sm *sm); +struct wpabuf * eap_peer_build_erp_reauth_start(struct eap_sm *sm, u8 eap_id); +void eap_peer_finish(struct eap_sm *sm, const struct eap_hdr *hdr, size_t len); +int eap_peer_get_erp_info(struct eap_sm *sm, struct eap_peer_config *config, + const u8 **username, size_t *username_len, + const u8 **realm, size_t *realm_len, u16 *erp_seq_num, + const u8 **rrk, size_t *rrk_len); +int eap_peer_update_erp_next_seq_num(struct eap_sm *sm, u16 seq_num); +void eap_peer_erp_init(struct eap_sm *sm, u8 *ext_session_id, + size_t ext_session_id_len, u8 *ext_emsk, + size_t ext_emsk_len); #endif /* IEEE8021X_EAPOL */ diff --git a/freebsd/contrib/wpa/src/eap_peer/eap_config.h b/freebsd/contrib/wpa/src/eap_peer/eap_config.h index f9800726..3a88f2ab 100644 --- a/freebsd/contrib/wpa/src/eap_peer/eap_config.h +++ b/freebsd/contrib/wpa/src/eap_peer/eap_config.h @@ -46,6 +46,9 @@ struct eap_peer_config { */ size_t anonymous_identity_len; + u8 *imsi_identity; + size_t imsi_identity_len; + /** * password - Password string for EAP * @@ -98,7 +101,7 @@ struct eap_peer_config { * certificate store (My user account) is used, whereas computer store * (Computer account) is used when running wpasvc as a service. */ - u8 *ca_cert; + char *ca_cert; /** * ca_path - Directory path for CA certificate files (PEM) @@ -109,7 +112,7 @@ struct eap_peer_config { * these certificates are added to the list of trusted CAs. ca_cert * may also be included in that case, but it is not required. */ - u8 *ca_path; + char *ca_path; /** * client_cert - File path to client certificate file (PEM/DER) @@ -123,7 +126,7 @@ struct eap_peer_config { * Alternatively, a named configuration blob can be used by setting * this to blob://blob_name. */ - u8 *client_cert; + char *client_cert; /** * private_key - File path to client private key file (PEM/DER/PFX) @@ -150,7 +153,7 @@ struct eap_peer_config { * Alternatively, a named configuration blob can be used by setting * this to blob://blob_name. */ - u8 *private_key; + char *private_key; /** * private_key_passwd - Password for private key file @@ -175,7 +178,7 @@ struct eap_peer_config { * Alternatively, a named configuration blob can be used by setting * this to blob://blob_name. */ - u8 *dh_file; + char *dh_file; /** * subject_match - Constraint for server certificate subject @@ -191,7 +194,49 @@ struct eap_peer_config { * to do a suffix match against a possible domain name in the CN entry. * For such a use case, domain_suffix_match should be used instead. */ - u8 *subject_match; + char *subject_match; + + /** + * check_cert_subject - Constraint for server certificate subject fields + * + * If check_cert_subject is set, the value of every field will be + * checked against the DN of the subject in the authentication server + * certificate. If the values do not match, the certificate verification + * will fail, rejecting the server. This option allows wpa_supplicant to + * match every individual field in the right order against the DN of the + * subject in the server certificate. + * + * For example, check_cert_subject=C=US/O=XX/OU=ABC/OU=XYZ/CN=1234 will + * check every individual DN field of the subject in the server + * certificate. If OU=XYZ comes first in terms of the order in the + * server certificate (DN field of server certificate + * C=US/O=XX/OU=XYZ/OU=ABC/CN=1234), wpa_supplicant will reject the + * server because the order of 'OU' is not matching the specified string + * in check_cert_subject. + * + * This option also allows '*' as a wildcard. This option has some + * limitation. + * It can only be used as per the following example. + * + * For example, check_cert_subject=C=US/O=XX/OU=Production* and we have + * two servers and DN of the subject in the first server certificate is + * (C=US/O=XX/OU=Production Unit) and DN of the subject in the second + * server is (C=US/O=XX/OU=Production Factory). In this case, + * wpa_supplicant will allow both servers because the value of 'OU' + * field in both server certificates matches 'OU' value in + * 'check_cert_subject' up to 'wildcard'. + * + * (Allow all servers, e.g., check_cert_subject=*) + */ + char *check_cert_subject; + + /** + * check_cert_subject2 - Constraint for server certificate subject fields + * + * This field is like check_cert_subject, but used for phase 2 (inside + * EAP-TTLS/PEAP/FAST tunnel) authentication. + */ + char *check_cert_subject2; /** * altsubject_match - Constraint for server certificate alt. subject @@ -209,23 +254,26 @@ struct eap_peer_config { * * Following types are supported: EMAIL, DNS, URI */ - u8 *altsubject_match; + char *altsubject_match; /** * domain_suffix_match - Constraint for server domain name * - * If set, this FQDN is used as a suffix match requirement for the - * server certificate in SubjectAltName dNSName element(s). If a - * matching dNSName is found, this constraint is met. If no dNSName - * values are present, this constraint is matched against SubjectName CN - * using same suffix match comparison. Suffix match here means that the - * host/domain name is compared one label at a time starting from the - * top-level domain and all the labels in domain_suffix_match shall be - * included in the certificate. The certificate may include additional - * sub-level labels in addition to the required labels. + * If set, this semicolon deliminated list of FQDNs is used as suffix + * match requirements for the server certificate in SubjectAltName + * dNSName element(s). If a matching dNSName is found against any of the + * specified values, this constraint is met. If no dNSName values are + * present, this constraint is matched against SubjectName CN using same + * suffix match comparison. Suffix match here means that the host/domain + * name is compared case-insentively one label at a time starting from + * the top-level domain and all the labels in domain_suffix_match shall + * be included in the certificate. The certificate may include + * additional sub-level labels in addition to the required labels. * * For example, domain_suffix_match=example.com would match - * test.example.com but would not match test-example.com. + * test.example.com but would not match test-example.com. Multiple + * match options can be specified in following manner: + * example.org;example.com. */ char *domain_suffix_match; @@ -241,6 +289,12 @@ struct eap_peer_config { * no subdomains or wildcard matches are allowed. Case-insensitive * comparison is used, so "Example.com" matches "example.com", but would * not match "test.Example.com". + * + * More than one match string can be provided by using semicolons to + * separate the strings (e.g., example.org;example.com). When multiple + * strings are specified, a match with any one of the values is + * considered a sufficient match for the certificate, i.e., the + * conditions are ORed together. */ char *domain_match; @@ -260,7 +314,7 @@ struct eap_peer_config { * Alternatively, a named configuration blob can be used by setting * this to blob://blob_name. */ - u8 *ca_cert2; + char *ca_cert2; /** * ca_path2 - Directory path for CA certificate files (PEM) (Phase 2) @@ -274,7 +328,7 @@ struct eap_peer_config { * This field is like ca_path, but used for phase 2 (inside * EAP-TTLS/PEAP/FAST tunnel) authentication. */ - u8 *ca_path2; + char *ca_path2; /** * client_cert2 - File path to client certificate file @@ -287,7 +341,7 @@ struct eap_peer_config { * Alternatively, a named configuration blob can be used by setting * this to blob://blob_name. */ - u8 *client_cert2; + char *client_cert2; /** * private_key2 - File path to client private key file @@ -300,7 +354,7 @@ struct eap_peer_config { * Alternatively, a named configuration blob can be used by setting * this to blob://blob_name. */ - u8 *private_key2; + char *private_key2; /** * private_key2_passwd - Password for private key file @@ -321,7 +375,7 @@ struct eap_peer_config { * Alternatively, a named configuration blob can be used by setting * this to blob://blob_name. */ - u8 *dh_file2; + char *dh_file2; /** * subject_match2 - Constraint for server certificate subject @@ -329,7 +383,7 @@ struct eap_peer_config { * This field is like subject_match, but used for phase 2 (inside * EAP-TTLS/PEAP/FAST tunnel) authentication. */ - u8 *subject_match2; + char *subject_match2; /** * altsubject_match2 - Constraint for server certificate alt. subject @@ -337,7 +391,7 @@ struct eap_peer_config { * This field is like altsubject_match, but used for phase 2 (inside * EAP-TTLS/PEAP/FAST tunnel) authentication. */ - u8 *altsubject_match2; + char *altsubject_match2; /** * domain_suffix_match2 - Constraint for server domain name @@ -628,6 +682,15 @@ struct eap_peer_config { int pending_req_passphrase; /** + * pending_req_sim - Pending SIM request + * + * This field should not be set in configuration step. It is only used + * internally when control interface is used to request needed + * information. + */ + int pending_req_sim; + + /** * pending_req_otp - Whether there is a pending OTP request * * This field should not be set in configuration step. It is only used diff --git a/freebsd/contrib/wpa/src/eap_peer/eap_i.h b/freebsd/contrib/wpa/src/eap_peer/eap_i.h index 6ab24834..096f0f28 100644 --- a/freebsd/contrib/wpa/src/eap_peer/eap_i.h +++ b/freebsd/contrib/wpa/src/eap_peer/eap_i.h @@ -14,6 +14,8 @@ #include "eap_peer/eap.h" #include "eap_common/eap_common.h" +#define NO_EAP_METHOD_ERROR (-1) + /* RFC 4137 - EAP Peer state machine */ typedef enum { @@ -206,6 +208,17 @@ struct eap_method { const u8 * (*get_identity)(struct eap_sm *sm, void *priv, size_t *len); /** + * get_error_code - Get the latest EAP method error code + * @priv: Pointer to private EAP method data from eap_method::init() + * Returns: An int for the EAP method specific error code if exists or + * NO_EAP_METHOD_ERROR otherwise. + * + * This method is an optional handler that only EAP methods that need to + * report their error code need to implement. + */ + int (*get_error_code)(void *priv); + + /** * free - Free EAP method data * @method: Pointer to the method data registered with * eap_peer_method_register(). diff --git a/freebsd/contrib/wpa/src/eap_peer/eap_leap.c b/freebsd/contrib/wpa/src/eap_peer/eap_leap.c index af63bf88..5f087bf5 100644 --- a/freebsd/contrib/wpa/src/eap_peer/eap_leap.c +++ b/freebsd/contrib/wpa/src/eap_peer/eap_leap.c @@ -117,10 +117,14 @@ static struct wpabuf * eap_leap_process_request(struct eap_sm *sm, void *priv, wpabuf_put_u8(resp, 0); /* unused */ wpabuf_put_u8(resp, LEAP_RESPONSE_LEN); rpos = wpabuf_put(resp, LEAP_RESPONSE_LEN); - if (pwhash) - challenge_response(challenge, password, rpos); - else - nt_challenge_response(challenge, password, password_len, rpos); + if ((pwhash && challenge_response(challenge, password, rpos)) || + (!pwhash && + nt_challenge_response(challenge, password, password_len, rpos))) { + wpa_printf(MSG_DEBUG, "EAP-LEAP: Failed to derive response"); + ret->ignore = TRUE; + wpabuf_free(resp); + return NULL; + } os_memcpy(data->peer_response, rpos, LEAP_RESPONSE_LEN); wpa_hexdump(MSG_MSGDUMP, "EAP-LEAP: Response", rpos, LEAP_RESPONSE_LEN); @@ -241,7 +245,10 @@ static struct wpabuf * eap_leap_process_response(struct eap_sm *sm, void *priv, return NULL; } } - challenge_response(data->ap_challenge, pw_hash_hash, expected); + if (challenge_response(data->ap_challenge, pw_hash_hash, expected)) { + ret->ignore = TRUE; + return NULL; + } ret->methodState = METHOD_DONE; ret->allowNotifications = FALSE; diff --git a/freebsd/contrib/wpa/src/eap_peer/eap_mschapv2.c b/freebsd/contrib/wpa/src/eap_peer/eap_mschapv2.c index 9193a772..25ead777 100644 --- a/freebsd/contrib/wpa/src/eap_peer/eap_mschapv2.c +++ b/freebsd/contrib/wpa/src/eap_peer/eap_mschapv2.c @@ -111,23 +111,21 @@ static void * eap_mschapv2_init(struct eap_sm *sm) return NULL; if (sm->peer_challenge) { - data->peer_challenge = os_malloc(MSCHAPV2_CHAL_LEN); + data->peer_challenge = os_memdup(sm->peer_challenge, + MSCHAPV2_CHAL_LEN); if (data->peer_challenge == NULL) { eap_mschapv2_deinit(sm, data); return NULL; } - os_memcpy(data->peer_challenge, sm->peer_challenge, - MSCHAPV2_CHAL_LEN); } if (sm->auth_challenge) { - data->auth_challenge = os_malloc(MSCHAPV2_CHAL_LEN); + data->auth_challenge = os_memdup(sm->auth_challenge, + MSCHAPV2_CHAL_LEN); if (data->auth_challenge == NULL) { eap_mschapv2_deinit(sm, data); return NULL; } - os_memcpy(data->auth_challenge, sm->auth_challenge, - MSCHAPV2_CHAL_LEN); } data->phase2 = sm->init_phase2; @@ -569,11 +567,11 @@ static struct wpabuf * eap_mschapv2_change_password( if (pwhash) { u8 new_password_hash[16]; if (nt_password_hash(new_password, new_password_len, - new_password_hash)) + new_password_hash) || + nt_password_hash_encrypted_with_block(password, + new_password_hash, + cp->encr_hash)) goto fail; - nt_password_hash_encrypted_with_block(password, - new_password_hash, - cp->encr_hash); } else { if (old_nt_password_hash_encrypted_with_new_nt_password_hash( new_password, new_password_len, @@ -860,9 +858,13 @@ static u8 * eap_mschapv2_getKey(struct eap_sm *sm, void *priv, size_t *len) /* MSK = server MS-MPPE-Recv-Key | MS-MPPE-Send-Key, i.e., * peer MS-MPPE-Send-Key | MS-MPPE-Recv-Key */ - get_asymetric_start_key(data->master_key, key, MSCHAPV2_KEY_LEN, 1, 0); - get_asymetric_start_key(data->master_key, key + MSCHAPV2_KEY_LEN, - MSCHAPV2_KEY_LEN, 0, 0); + if (get_asymetric_start_key(data->master_key, key, MSCHAPV2_KEY_LEN, 1, + 0) < 0 || + get_asymetric_start_key(data->master_key, key + MSCHAPV2_KEY_LEN, + MSCHAPV2_KEY_LEN, 0, 0) < 0) { + os_free(key); + return NULL; + } wpa_hexdump_key(MSG_DEBUG, "EAP-MSCHAPV2: Derived key", key, key_len); diff --git a/freebsd/contrib/wpa/src/eap_peer/eap_peap.c b/freebsd/contrib/wpa/src/eap_peer/eap_peap.c index ab270bbc..74bc2653 100644 --- a/freebsd/contrib/wpa/src/eap_peer/eap_peap.c +++ b/freebsd/contrib/wpa/src/eap_peer/eap_peap.c @@ -2,7 +2,7 @@ /* * EAP peer method: EAP-PEAP (draft-josefsson-pppext-eap-tls-eap-10.txt) - * Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi> + * Copyright (c) 2004-2019, Jouni Malinen <j@w1.fi> * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -171,7 +171,7 @@ static void * eap_peap_init(struct eap_sm *sm) static void eap_peap_free_key(struct eap_peap_data *data) { if (data->key_data) { - bin_clear_free(data->key_data, EAP_TLS_KEY_LEN); + bin_clear_free(data->key_data, EAP_TLS_KEY_LEN + EAP_EMSK_LEN); data->key_data = NULL; } } @@ -188,9 +188,9 @@ static void eap_peap_deinit(struct eap_sm *sm, void *priv) eap_peer_tls_ssl_deinit(sm, &data->ssl); eap_peap_free_key(data); os_free(data->session_id); - wpabuf_free(data->pending_phase2_req); - wpabuf_free(data->pending_resp); - os_free(data); + wpabuf_clear_free(data->pending_phase2_req); + wpabuf_clear_free(data->pending_resp); + bin_clear_free(data, sizeof(*data)); } @@ -255,7 +255,7 @@ static int eap_peap_derive_cmk(struct eap_sm *sm, struct eap_peap_data *data) { u8 *tk; u8 isk[32], imck[60]; - int resumed; + int resumed, res; /* * Tunnel key (TK) is the first 60 octets of the key generated by @@ -294,9 +294,11 @@ static int eap_peap_derive_cmk(struct eap_sm *sm, struct eap_peap_data *data) * in the end of the label just before ISK; is that just a typo?) */ wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: TempKey", tk, 40); - if (peap_prfplus(data->peap_version, tk, 40, - "Inner Methods Compound Keys", - isk, sizeof(isk), imck, sizeof(imck)) < 0) + res = peap_prfplus(data->peap_version, tk, 40, + "Inner Methods Compound Keys", + isk, sizeof(isk), imck, sizeof(imck)); + os_memset(isk, 0, sizeof(isk)); + if (res < 0) return -1; wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IMCK (IPMKj)", imck, sizeof(imck)); @@ -305,6 +307,7 @@ static int eap_peap_derive_cmk(struct eap_sm *sm, struct eap_peap_data *data) wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IPMK (S-IPMKj)", data->ipmk, 40); os_memcpy(data->cmk, imck + 40, 20); wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CMK (CMKj)", data->cmk, 20); + os_memset(imck, 0, sizeof(imck)); return 0; } @@ -384,7 +387,7 @@ static struct wpabuf * eap_tlv_build_result(struct eap_sm *sm, wpabuf_put_be16(msg, status); /* Status */ if (crypto_tlv_used && eap_tlv_add_cryptobinding(sm, data, msg)) { - wpabuf_free(msg); + wpabuf_clear_free(msg); return NULL; } @@ -653,11 +656,11 @@ static int eap_peap_phase2_request(struct eap_sm *sm, if (*resp == NULL) { ret->methodState = METHOD_DONE; ret->decision = DECISION_FAIL; - wpabuf_free(buf); + wpabuf_clear_free(buf); return -1; } wpabuf_put_buf(*resp, buf); - wpabuf_free(buf); + wpabuf_clear_free(buf); break; } } @@ -728,8 +731,9 @@ static int eap_peap_phase2_request(struct eap_sm *sm, if (*resp == NULL && (config->pending_req_identity || config->pending_req_password || - config->pending_req_otp || config->pending_req_new_password)) { - wpabuf_free(data->pending_phase2_req); + config->pending_req_otp || config->pending_req_new_password || + config->pending_req_sim)) { + wpabuf_clear_free(data->pending_phase2_req); data->pending_phase2_req = wpabuf_alloc_copy(hdr, len); } @@ -808,7 +812,7 @@ continue_req: struct wpabuf *nmsg = wpabuf_alloc(sizeof(struct eap_hdr) + wpabuf_len(in_decrypted)); if (nmsg == NULL) { - wpabuf_free(in_decrypted); + wpabuf_clear_free(in_decrypted); return 0; } nhdr = wpabuf_put(nmsg, sizeof(*nhdr)); @@ -818,7 +822,7 @@ continue_req: nhdr->length = host_to_be16(sizeof(struct eap_hdr) + wpabuf_len(in_decrypted)); - wpabuf_free(in_decrypted); + wpabuf_clear_free(in_decrypted); in_decrypted = nmsg; } @@ -827,7 +831,7 @@ continue_req: wpa_printf(MSG_INFO, "EAP-PEAP: Too short Phase 2 " "EAP frame (len=%lu)", (unsigned long) wpabuf_len(in_decrypted)); - wpabuf_free(in_decrypted); + wpabuf_clear_free(in_decrypted); return 0; } len = be_to_host16(hdr->length); @@ -836,7 +840,7 @@ continue_req: "Phase 2 EAP frame (len=%lu hdr->length=%lu)", (unsigned long) wpabuf_len(in_decrypted), (unsigned long) len); - wpabuf_free(in_decrypted); + wpabuf_clear_free(in_decrypted); return 0; } if (len < wpabuf_len(in_decrypted)) { @@ -853,7 +857,7 @@ continue_req: case EAP_CODE_REQUEST: if (eap_peap_phase2_request(sm, data, ret, in_decrypted, &resp)) { - wpabuf_free(in_decrypted); + wpabuf_clear_free(in_decrypted); wpa_printf(MSG_INFO, "EAP-PEAP: Phase2 Request " "processing failed"); return 0; @@ -873,7 +877,7 @@ continue_req: "completed successfully"); ret->methodState = METHOD_DONE; ret->decision = DECISION_FAIL; - wpabuf_free(in_decrypted); + wpabuf_clear_free(in_decrypted); return 0; } wpa_printf(MSG_DEBUG, "EAP-PEAP: Version 1 - " @@ -883,7 +887,7 @@ continue_req: ret->methodState = METHOD_DONE; data->phase2_success = 1; if (data->peap_outer_success == 2) { - wpabuf_free(in_decrypted); + wpabuf_clear_free(in_decrypted); wpa_printf(MSG_DEBUG, "EAP-PEAP: Use TLS ACK " "to finish authentication"); return 1; @@ -929,7 +933,7 @@ continue_req: break; } - wpabuf_free(in_decrypted); + wpabuf_clear_free(in_decrypted); if (resp) { int skip_change2 = 0; @@ -956,7 +960,7 @@ continue_req: wpa_printf(MSG_INFO, "EAP-PEAP: Failed to encrypt " "a Phase 2 frame"); } - wpabuf_free(resp); + wpabuf_clear_free(resp); } return 0; @@ -1057,7 +1061,7 @@ static struct wpabuf * eap_peap_process(struct eap_sm *sm, void *priv, if (sm->waiting_ext_cert_check) { wpa_printf(MSG_DEBUG, "EAP-PEAP: Waiting external server certificate validation"); - wpabuf_free(data->pending_resp); + wpabuf_clear_free(data->pending_resp); data->pending_resp = resp; return NULL; } @@ -1082,12 +1086,19 @@ static struct wpabuf * eap_peap_process(struct eap_sm *sm, void *priv, "key derivation", label); data->key_data = eap_peer_tls_derive_key(sm, &data->ssl, label, - EAP_TLS_KEY_LEN); + NULL, 0, + EAP_TLS_KEY_LEN + + EAP_EMSK_LEN); if (data->key_data) { - wpa_hexdump_key(MSG_DEBUG, + wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: Derived key", data->key_data, EAP_TLS_KEY_LEN); + wpa_hexdump_key(MSG_DEBUG, + "EAP-PEAP: Derived EMSK", + data->key_data + + EAP_TLS_KEY_LEN, + EAP_EMSK_LEN); } else { wpa_printf(MSG_DEBUG, "EAP-PEAP: Failed to " "derive key"); @@ -1132,7 +1143,7 @@ static struct wpabuf * eap_peap_process(struct eap_sm *sm, void *priv, /* * Application data included in the handshake message. */ - wpabuf_free(data->pending_phase2_req); + wpabuf_clear_free(data->pending_phase2_req); data->pending_phase2_req = resp; resp = NULL; res = eap_peap_decrypt(sm, data, ret, req, &msg, @@ -1145,7 +1156,7 @@ static struct wpabuf * eap_peap_process(struct eap_sm *sm, void *priv, } if (res == 1) { - wpabuf_free(resp); + wpabuf_clear_free(resp); return eap_peer_tls_build_ack(id, EAP_TYPE_PEAP, data->peap_version); } @@ -1165,9 +1176,13 @@ static Boolean eap_peap_has_reauth_data(struct eap_sm *sm, void *priv) static void eap_peap_deinit_for_reauth(struct eap_sm *sm, void *priv) { struct eap_peap_data *data = priv; - wpabuf_free(data->pending_phase2_req); + + if (data->phase2_priv && data->phase2_method && + data->phase2_method->deinit_for_reauth) + data->phase2_method->deinit_for_reauth(sm, data->phase2_priv); + wpabuf_clear_free(data->pending_phase2_req); data->pending_phase2_req = NULL; - wpabuf_free(data->pending_resp); + wpabuf_clear_free(data->pending_resp); data->pending_resp = NULL; data->crypto_binding_used = 0; } @@ -1254,6 +1269,7 @@ static u8 * eap_peap_getKey(struct eap_sm *sm, void *priv, size_t *len) os_memcpy(key, csk, EAP_TLS_KEY_LEN); wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Derived key", key, EAP_TLS_KEY_LEN); + os_memset(csk, 0, sizeof(csk)); } else os_memcpy(key, data->key_data, EAP_TLS_KEY_LEN); @@ -1261,6 +1277,29 @@ static u8 * eap_peap_getKey(struct eap_sm *sm, void *priv, size_t *len) } +static u8 * eap_peap_get_emsk(struct eap_sm *sm, void *priv, size_t *len) +{ + struct eap_peap_data *data = priv; + u8 *key; + + if (!data->key_data || !data->phase2_success) + return NULL; + + if (data->crypto_binding_used) { + /* [MS-PEAP] does not define EMSK derivation */ + return NULL; + } + + key = os_memdup(data->key_data + EAP_TLS_KEY_LEN, EAP_EMSK_LEN); + if (!key) + return NULL; + + *len = EAP_EMSK_LEN; + + return key; +} + + static u8 * eap_peap_get_session_id(struct eap_sm *sm, void *priv, size_t *len) { struct eap_peap_data *data = priv; @@ -1269,12 +1308,11 @@ static u8 * eap_peap_get_session_id(struct eap_sm *sm, void *priv, size_t *len) if (data->session_id == NULL || !data->phase2_success) return NULL; - id = os_malloc(data->id_len); + id = os_memdup(data->session_id, data->id_len); if (id == NULL) return NULL; *len = data->id_len; - os_memcpy(id, data->session_id, data->id_len); return id; } @@ -1294,6 +1332,7 @@ int eap_peer_peap_register(void) eap->process = eap_peap_process; eap->isKeyAvailable = eap_peap_isKeyAvailable; eap->getKey = eap_peap_getKey; + eap->get_emsk = eap_peap_get_emsk; eap->get_status = eap_peap_get_status; eap->has_reauth_data = eap_peap_has_reauth_data; eap->deinit_for_reauth = eap_peap_deinit_for_reauth; diff --git a/freebsd/contrib/wpa/src/eap_peer/eap_proxy.h b/freebsd/contrib/wpa/src/eap_peer/eap_proxy.h index 23cdbe69..9d8e5702 100644 --- a/freebsd/contrib/wpa/src/eap_peer/eap_proxy.h +++ b/freebsd/contrib/wpa/src/eap_peer/eap_proxy.h @@ -20,7 +20,7 @@ enum eap_proxy_status { }; struct eap_proxy_sm * -eap_proxy_init(void *eapol_ctx, struct eapol_callbacks *eapol_cb, +eap_proxy_init(void *eapol_ctx, const struct eapol_callbacks *eapol_cb, void *msg_ctx); void eap_proxy_deinit(struct eap_proxy_sm *eap_proxy); @@ -40,10 +40,16 @@ eap_proxy_packet_update(struct eap_proxy_sm *eap_proxy, u8 *eapReqData, int eap_proxy_sm_get_status(struct eap_proxy_sm *sm, char *buf, size_t buflen, int verbose); -int eap_proxy_get_imsi(struct eap_proxy_sm *eap_proxy, char *imsi_buf, - size_t *imsi_len); +int eap_proxy_get_imsi(struct eap_proxy_sm *eap_proxy, int sim_num, + char *imsi_buf, size_t *imsi_len); int eap_proxy_notify_config(struct eap_proxy_sm *sm, struct eap_peer_config *config); +u8 * eap_proxy_get_eap_session_id(struct eap_proxy_sm *sm, size_t *len); + +u8 * eap_proxy_get_emsk(struct eap_proxy_sm *sm, size_t *len); + +void eap_proxy_sm_abort(struct eap_proxy_sm *sm); + #endif /* EAP_PROXY_H */ diff --git a/freebsd/contrib/wpa/src/eap_peer/eap_psk.c b/freebsd/contrib/wpa/src/eap_peer/eap_psk.c index 49ed1736..02066544 100644 --- a/freebsd/contrib/wpa/src/eap_peer/eap_psk.c +++ b/freebsd/contrib/wpa/src/eap_peer/eap_psk.c @@ -118,14 +118,13 @@ static struct wpabuf * eap_psk_process_1(struct eap_psk_data *data, os_memcpy(data->rand_s, hdr1->rand_s, EAP_PSK_RAND_LEN); os_free(data->id_s); data->id_s_len = len - sizeof(*hdr1); - data->id_s = os_malloc(data->id_s_len); + data->id_s = os_memdup(hdr1 + 1, data->id_s_len); if (data->id_s == NULL) { wpa_printf(MSG_ERROR, "EAP-PSK: Failed to allocate memory for " "ID_S (len=%lu)", (unsigned long) data->id_s_len); ret->ignore = TRUE; return NULL; } - os_memcpy(data->id_s, (u8 *) (hdr1 + 1), data->id_s_len); wpa_hexdump_ascii(MSG_DEBUG, "EAP-PSK: ID_S", data->id_s, data->id_s_len); @@ -275,13 +274,12 @@ static struct wpabuf * eap_psk_process_3(struct eap_psk_data *data, wpabuf_head(reqData), 5); wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: PCHANNEL - cipher msg", msg, left); - decrypted = os_malloc(left); + decrypted = os_memdup(msg, left); if (decrypted == NULL) { ret->methodState = METHOD_DONE; ret->decision = DECISION_FAIL; return NULL; } - os_memcpy(decrypted, msg, left); if (aes_128_eax_decrypt(data->tek, nonce, sizeof(nonce), wpabuf_head(reqData), @@ -427,12 +425,11 @@ static u8 * eap_psk_getKey(struct eap_sm *sm, void *priv, size_t *len) if (data->state != PSK_DONE) return NULL; - key = os_malloc(EAP_MSK_LEN); + key = os_memdup(data->msk, EAP_MSK_LEN); if (key == NULL) return NULL; *len = EAP_MSK_LEN; - os_memcpy(key, data->msk, EAP_MSK_LEN); return key; } @@ -468,12 +465,11 @@ static u8 * eap_psk_get_emsk(struct eap_sm *sm, void *priv, size_t *len) if (data->state != PSK_DONE) return NULL; - key = os_malloc(EAP_EMSK_LEN); + key = os_memdup(data->emsk, EAP_EMSK_LEN); if (key == NULL) return NULL; *len = EAP_EMSK_LEN; - os_memcpy(key, data->emsk, EAP_EMSK_LEN); return key; } diff --git a/freebsd/contrib/wpa/src/eap_peer/eap_tls.c b/freebsd/contrib/wpa/src/eap_peer/eap_tls.c index 35afcf77..37d7f57f 100644 --- a/freebsd/contrib/wpa/src/eap_peer/eap_tls.c +++ b/freebsd/contrib/wpa/src/eap_peer/eap_tls.c @@ -175,14 +175,32 @@ static struct wpabuf * eap_tls_failure(struct eap_sm *sm, static void eap_tls_success(struct eap_sm *sm, struct eap_tls_data *data, struct eap_method_ret *ret) { + const char *label; + wpa_printf(MSG_DEBUG, "EAP-TLS: Done"); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_UNCOND_SUCC; + if (data->ssl.tls_out) { + wpa_printf(MSG_DEBUG, "EAP-TLS: Fragment(s) remaining"); + return; + } + + if (data->ssl.tls_v13) { + label = "EXPORTER_EAP_TLS_Key_Material"; + + /* A possible NewSessionTicket may be received before + * EAP-Success, so need to allow it to be received. */ + ret->methodState = METHOD_MAY_CONT; + ret->decision = DECISION_COND_SUCC; + } else { + label = "client EAP encryption"; + + ret->methodState = METHOD_DONE; + ret->decision = DECISION_UNCOND_SUCC; + } eap_tls_free_key(data); - data->key_data = eap_peer_tls_derive_key(sm, &data->ssl, - "client EAP encryption", + data->key_data = eap_peer_tls_derive_key(sm, &data->ssl, label, + NULL, 0, EAP_TLS_KEY_LEN + EAP_EMSK_LEN); if (data->key_data) { @@ -340,12 +358,11 @@ static u8 * eap_tls_getKey(struct eap_sm *sm, void *priv, size_t *len) if (data->key_data == NULL) return NULL; - key = os_malloc(EAP_TLS_KEY_LEN); + key = os_memdup(data->key_data, EAP_TLS_KEY_LEN); if (key == NULL) return NULL; *len = EAP_TLS_KEY_LEN; - os_memcpy(key, data->key_data, EAP_TLS_KEY_LEN); return key; } @@ -359,12 +376,11 @@ static u8 * eap_tls_get_emsk(struct eap_sm *sm, void *priv, size_t *len) if (data->key_data == NULL) return NULL; - key = os_malloc(EAP_EMSK_LEN); + key = os_memdup(data->key_data + EAP_TLS_KEY_LEN, EAP_EMSK_LEN); if (key == NULL) return NULL; *len = EAP_EMSK_LEN; - os_memcpy(key, data->key_data + EAP_TLS_KEY_LEN, EAP_EMSK_LEN); return key; } @@ -378,12 +394,11 @@ static u8 * eap_tls_get_session_id(struct eap_sm *sm, void *priv, size_t *len) if (data->session_id == NULL) return NULL; - id = os_malloc(data->id_len); + id = os_memdup(data->session_id, data->id_len); if (id == NULL) return NULL; *len = data->id_len; - os_memcpy(id, data->session_id, data->id_len); return id; } diff --git a/freebsd/contrib/wpa/src/eap_peer/eap_tls_common.c b/freebsd/contrib/wpa/src/eap_peer/eap_tls_common.c index 8908dc2f..d8b0f47f 100644 --- a/freebsd/contrib/wpa/src/eap_peer/eap_tls_common.c +++ b/freebsd/contrib/wpa/src/eap_peer/eap_tls_common.c @@ -2,7 +2,7 @@ /* * EAP peer: EAP-TLS/PEAP/TTLS/FAST common functions - * Copyright (c) 2004-2013, Jouni Malinen <j@w1.fi> + * Copyright (c) 2004-2019, Jouni Malinen <j@w1.fi> * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -72,34 +72,53 @@ static void eap_tls_params_flags(struct tls_connection_params *params, params->flags &= ~TLS_CONN_DISABLE_SESSION_TICKET; if (os_strstr(txt, "tls_disable_tlsv1_0=1")) params->flags |= TLS_CONN_DISABLE_TLSv1_0; - if (os_strstr(txt, "tls_disable_tlsv1_0=0")) + if (os_strstr(txt, "tls_disable_tlsv1_0=0")) { params->flags &= ~TLS_CONN_DISABLE_TLSv1_0; + params->flags |= TLS_CONN_ENABLE_TLSv1_0; + } if (os_strstr(txt, "tls_disable_tlsv1_1=1")) params->flags |= TLS_CONN_DISABLE_TLSv1_1; - if (os_strstr(txt, "tls_disable_tlsv1_1=0")) + if (os_strstr(txt, "tls_disable_tlsv1_1=0")) { params->flags &= ~TLS_CONN_DISABLE_TLSv1_1; + params->flags |= TLS_CONN_ENABLE_TLSv1_1; + } if (os_strstr(txt, "tls_disable_tlsv1_2=1")) params->flags |= TLS_CONN_DISABLE_TLSv1_2; - if (os_strstr(txt, "tls_disable_tlsv1_2=0")) + if (os_strstr(txt, "tls_disable_tlsv1_2=0")) { params->flags &= ~TLS_CONN_DISABLE_TLSv1_2; + params->flags |= TLS_CONN_ENABLE_TLSv1_2; + } + if (os_strstr(txt, "tls_disable_tlsv1_3=1")) + params->flags |= TLS_CONN_DISABLE_TLSv1_3; + if (os_strstr(txt, "tls_disable_tlsv1_3=0")) + params->flags &= ~TLS_CONN_DISABLE_TLSv1_3; if (os_strstr(txt, "tls_ext_cert_check=1")) params->flags |= TLS_CONN_EXT_CERT_CHECK; if (os_strstr(txt, "tls_ext_cert_check=0")) params->flags &= ~TLS_CONN_EXT_CERT_CHECK; + if (os_strstr(txt, "tls_suiteb=1")) + params->flags |= TLS_CONN_SUITEB; + if (os_strstr(txt, "tls_suiteb=0")) + params->flags &= ~TLS_CONN_SUITEB; + if (os_strstr(txt, "tls_suiteb_no_ecdh=1")) + params->flags |= TLS_CONN_SUITEB_NO_ECDH; + if (os_strstr(txt, "tls_suiteb_no_ecdh=0")) + params->flags &= ~TLS_CONN_SUITEB_NO_ECDH; } static void eap_tls_params_from_conf1(struct tls_connection_params *params, struct eap_peer_config *config) { - params->ca_cert = (char *) config->ca_cert; - params->ca_path = (char *) config->ca_path; - params->client_cert = (char *) config->client_cert; - params->private_key = (char *) config->private_key; - params->private_key_passwd = (char *) config->private_key_passwd; - params->dh_file = (char *) config->dh_file; - params->subject_match = (char *) config->subject_match; - params->altsubject_match = (char *) config->altsubject_match; + params->ca_cert = config->ca_cert; + params->ca_path = config->ca_path; + params->client_cert = config->client_cert; + params->private_key = config->private_key; + params->private_key_passwd = config->private_key_passwd; + params->dh_file = config->dh_file; + params->subject_match = config->subject_match; + params->altsubject_match = config->altsubject_match; + params->check_cert_subject = config->check_cert_subject; params->suffix_match = config->domain_suffix_match; params->domain_match = config->domain_match; params->engine = config->engine; @@ -115,14 +134,15 @@ static void eap_tls_params_from_conf1(struct tls_connection_params *params, static void eap_tls_params_from_conf2(struct tls_connection_params *params, struct eap_peer_config *config) { - params->ca_cert = (char *) config->ca_cert2; - params->ca_path = (char *) config->ca_path2; - params->client_cert = (char *) config->client_cert2; - params->private_key = (char *) config->private_key2; - params->private_key_passwd = (char *) config->private_key2_passwd; - params->dh_file = (char *) config->dh_file2; - params->subject_match = (char *) config->subject_match2; - params->altsubject_match = (char *) config->altsubject_match2; + params->ca_cert = config->ca_cert2; + params->ca_path = config->ca_path2; + params->client_cert = config->client_cert2; + params->private_key = config->private_key2; + params->private_key_passwd = config->private_key2_passwd; + params->dh_file = config->dh_file2; + params->subject_match = config->subject_match2; + params->altsubject_match = config->altsubject_match2; + params->check_cert_subject = config->check_cert_subject2; params->suffix_match = config->domain_suffix_match2; params->domain_match = config->domain_match2; params->engine = config->engine2; @@ -153,6 +173,25 @@ static int eap_tls_params_from_conf(struct eap_sm *sm, */ params->flags |= TLS_CONN_DISABLE_SESSION_TICKET; } + if (data->eap_type == EAP_TYPE_FAST || + data->eap_type == EAP_TYPE_TTLS || + data->eap_type == EAP_TYPE_PEAP) { + /* The current EAP peer implementation is not yet ready for the + * TLS v1.3 changes, so disable this by default for now. */ + params->flags |= TLS_CONN_DISABLE_TLSv1_3; + } + if (data->eap_type == EAP_TYPE_TLS || + data->eap_type == EAP_UNAUTH_TLS_TYPE || + data->eap_type == EAP_WFA_UNAUTH_TLS_TYPE) { + /* While the current EAP-TLS implementation is more or less + * complete for TLS v1.3, there has been no interoperability + * testing with other implementations, so disable for by default + * for now until there has been chance to confirm that no + * significant interoperability issues show up with TLS version + * update. + */ + params->flags |= TLS_CONN_DISABLE_TLSv1_3; + } if (phase2) { wpa_printf(MSG_DEBUG, "TLS: using phase2 config options"); eap_tls_params_from_conf2(params, config); @@ -312,6 +351,8 @@ void eap_peer_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data) * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() * @data: Data for TLS processing * @label: Label string for deriving the keys, e.g., "client EAP encryption" + * @context: Optional extra upper-layer context (max len 2^16) + * @context_len: The length of the context value * @len: Length of the key material to generate (usually 64 for MSK) * Returns: Pointer to allocated key on success or %NULL on failure * @@ -320,9 +361,12 @@ void eap_peer_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data) * different label to bind the key usage into the generated material. * * The caller is responsible for freeing the returned buffer. + * + * Note: To provide the RFC 5705 context, the context variable must be non-NULL. */ u8 * eap_peer_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data, - const char *label, size_t len) + const char *label, const u8 *context, + size_t context_len, size_t len) { u8 *out; @@ -330,8 +374,8 @@ u8 * eap_peer_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data, if (out == NULL) return NULL; - if (tls_connection_export_key(data->ssl_ctx, data->conn, label, out, - len)) { + if (tls_connection_export_key(data->ssl_ctx, data->conn, label, + context, context_len, out, len)) { os_free(out); return NULL; } @@ -360,6 +404,29 @@ u8 * eap_peer_tls_derive_session_id(struct eap_sm *sm, struct tls_random keys; u8 *out; + if (eap_type == EAP_TYPE_TLS && data->tls_v13) { + u8 *id, *method_id; + + /* Session-Id = <EAP-Type> || Method-Id + * Method-Id = TLS-Exporter("EXPORTER_EAP_TLS_Method-Id", + * "", 64) + */ + *len = 1 + 64; + id = os_malloc(*len); + if (!id) + return NULL; + method_id = eap_peer_tls_derive_key( + sm, data, "EXPORTER_EAP_TLS_Method-Id", NULL, 0, 64); + if (!method_id) { + os_free(id); + return NULL; + } + id[0] = eap_type; + os_memcpy(id + 1, method_id, 64); + os_free(method_id); + return id; + } + if (tls_connection_get_random(sm->ssl_ctx, data->conn, &keys) || keys.client_random == NULL || keys.server_random == NULL) return NULL; @@ -663,6 +730,8 @@ int eap_peer_tls_process_helper(struct eap_sm *sm, struct eap_ssl_data *data, * the AS. */ int res = eap_tls_process_input(sm, data, in_data, out_data); + char buf[20]; + if (res) { /* * Input processing failed (res = -1) or more data is @@ -675,6 +744,12 @@ int eap_peer_tls_process_helper(struct eap_sm *sm, struct eap_ssl_data *data, * The incoming message has been reassembled and processed. The * response was allocated into data->tls_out buffer. */ + + if (tls_get_version(data->ssl_ctx, data->conn, + buf, sizeof(buf)) == 0) { + wpa_printf(MSG_DEBUG, "SSL: Using TLS version %s", buf); + data->tls_v13 = os_strcmp(buf, "TLSv1.3") == 0; + } } if (data->tls_out == NULL) { diff --git a/freebsd/contrib/wpa/src/eap_peer/eap_tls_common.h b/freebsd/contrib/wpa/src/eap_peer/eap_tls_common.h index acd2b783..5f825294 100644 --- a/freebsd/contrib/wpa/src/eap_peer/eap_tls_common.h +++ b/freebsd/contrib/wpa/src/eap_peer/eap_tls_common.h @@ -73,6 +73,11 @@ struct eap_ssl_data { * eap_type - EAP method used in Phase 1 (EAP_TYPE_TLS/PEAP/TTLS/FAST) */ u8 eap_type; + + /** + * tls_v13 - Whether TLS v1.3 or newer is used + */ + int tls_v13; }; @@ -94,7 +99,8 @@ int eap_peer_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data, struct eap_peer_config *config, u8 eap_type); void eap_peer_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data); u8 * eap_peer_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data, - const char *label, size_t len); + const char *label, const u8 *context, + size_t context_len, size_t len); u8 * eap_peer_tls_derive_session_id(struct eap_sm *sm, struct eap_ssl_data *data, u8 eap_type, size_t *len); diff --git a/freebsd/contrib/wpa/src/eap_peer/eap_ttls.c b/freebsd/contrib/wpa/src/eap_peer/eap_ttls.c index f9601e45..9376e2bc 100644 --- a/freebsd/contrib/wpa/src/eap_peer/eap_ttls.c +++ b/freebsd/contrib/wpa/src/eap_peer/eap_ttls.c @@ -198,8 +198,8 @@ static void eap_ttls_deinit(struct eap_sm *sm, void *priv) eap_peer_tls_ssl_deinit(sm, &data->ssl); eap_ttls_free_key(data); os_free(data->session_id); - wpabuf_free(data->pending_phase2_req); - wpabuf_free(data->pending_resp); + wpabuf_clear_free(data->pending_phase2_req); + wpabuf_clear_free(data->pending_resp); os_free(data); } @@ -250,7 +250,7 @@ static int eap_ttls_avp_encapsulate(struct wpabuf **resp, u32 avp_code, msg = wpabuf_alloc(sizeof(struct ttls_avp) + wpabuf_len(*resp) + 4); if (msg == NULL) { - wpabuf_free(*resp); + wpabuf_clear_free(*resp); *resp = NULL; return -1; } @@ -260,7 +260,7 @@ static int eap_ttls_avp_encapsulate(struct wpabuf **resp, u32 avp_code, os_memcpy(pos, wpabuf_head(*resp), wpabuf_len(*resp)); pos += wpabuf_len(*resp); AVP_PAD(avp, pos); - wpabuf_free(*resp); + wpabuf_clear_free(*resp); wpabuf_put(msg, pos - avp); *resp = msg; return 0; @@ -273,6 +273,7 @@ static int eap_ttls_v0_derive_key(struct eap_sm *sm, eap_ttls_free_key(data); data->key_data = eap_peer_tls_derive_key(sm, &data->ssl, "ttls keying material", + NULL, 0, EAP_TLS_KEY_LEN + EAP_EMSK_LEN); if (!data->key_data) { @@ -305,7 +306,8 @@ static int eap_ttls_v0_derive_key(struct eap_sm *sm, static u8 * eap_ttls_implicit_challenge(struct eap_sm *sm, struct eap_ttls_data *data, size_t len) { - return eap_peer_tls_derive_key(sm, &data->ssl, "ttls challenge", len); + return eap_peer_tls_derive_key(sm, &data->ssl, "ttls challenge", + NULL, 0, len); } #endif /* CONFIG_FIPS */ @@ -460,7 +462,7 @@ static int eap_ttls_phase2_request_eap(struct eap_sm *sm, if (*resp == NULL && (config->pending_req_identity || config->pending_req_password || - config->pending_req_otp)) { + config->pending_req_otp || config->pending_req_sim)) { return 0; } @@ -512,7 +514,7 @@ static int eap_ttls_phase2_request_mschapv2(struct eap_sm *sm, challenge = eap_ttls_implicit_challenge( sm, data, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN + 1); if (challenge == NULL) { - wpabuf_free(msg); + wpabuf_clear_free(msg); wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAPV2: Failed to derive " "implicit challenge"); return -1; @@ -531,7 +533,7 @@ static int eap_ttls_phase2_request_mschapv2(struct eap_sm *sm, *pos++ = 0; /* Flags */ if (os_get_random(pos, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN) < 0) { os_free(challenge); - wpabuf_free(msg); + wpabuf_clear_free(msg); wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAPV2: Failed to get " "random data for peer challenge"); return -1; @@ -545,7 +547,7 @@ static int eap_ttls_phase2_request_mschapv2(struct eap_sm *sm, peer_challenge, pos, data->auth_response, data->master_key)) { os_free(challenge); - wpabuf_free(msg); + wpabuf_clear_free(msg); wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAPV2: Failed to derive " "response"); return -1; @@ -606,7 +608,7 @@ static int eap_ttls_phase2_request_mschap(struct eap_sm *sm, challenge = eap_ttls_implicit_challenge( sm, data, EAP_TTLS_MSCHAP_CHALLENGE_LEN + 1); if (challenge == NULL) { - wpabuf_free(msg); + wpabuf_clear_free(msg); wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAP: Failed to derive " "implicit challenge"); return -1; @@ -626,12 +628,28 @@ static int eap_ttls_phase2_request_mschap(struct eap_sm *sm, os_memset(pos, 0, 24); /* LM-Response */ pos += 24; if (pwhash) { - challenge_response(challenge, password, pos); /* NT-Response */ + /* NT-Response */ + if (challenge_response(challenge, password, pos)) { + wpa_printf(MSG_ERROR, + "EAP-TTLS/MSCHAP: Failed derive password hash"); + wpabuf_clear_free(msg); + os_free(challenge); + return -1; + } + wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: MSCHAP password hash", password, 16); } else { - nt_challenge_response(challenge, password, password_len, - pos); /* NT-Response */ + /* NT-Response */ + if (nt_challenge_response(challenge, password, password_len, + pos)) { + wpa_printf(MSG_ERROR, + "EAP-TTLS/MSCHAP: Failed derive password"); + wpabuf_clear_free(msg); + os_free(challenge); + return -1; + } + wpa_hexdump_ascii_key(MSG_DEBUG, "EAP-TTLS: MSCHAP password", password, password_len); } @@ -746,7 +764,7 @@ static int eap_ttls_phase2_request_chap(struct eap_sm *sm, challenge = eap_ttls_implicit_challenge( sm, data, EAP_TTLS_CHAP_CHALLENGE_LEN + 1); if (challenge == NULL) { - wpabuf_free(msg); + wpabuf_clear_free(msg); wpa_printf(MSG_ERROR, "EAP-TTLS/CHAP: Failed to derive " "implicit challenge"); return -1; @@ -872,13 +890,12 @@ static int eap_ttls_parse_attr_eap(const u8 *dpos, size_t dlen, { wpa_printf(MSG_DEBUG, "EAP-TTLS: AVP - EAP Message"); if (parse->eapdata == NULL) { - parse->eapdata = os_malloc(dlen); + parse->eapdata = os_memdup(dpos, dlen); if (parse->eapdata == NULL) { wpa_printf(MSG_WARNING, "EAP-TTLS: Failed to allocate " "memory for Phase 2 EAP data"); return -1; } - os_memcpy(parse->eapdata, dpos, dlen); parse->eap_len = dlen; } else { u8 *neweap = os_realloc(parse->eapdata, parse->eap_len + dlen); @@ -1060,10 +1077,10 @@ static int eap_ttls_encrypt_response(struct eap_sm *sm, resp, out_data)) { wpa_printf(MSG_INFO, "EAP-TTLS: Failed to encrypt a Phase 2 " "frame"); - wpabuf_free(resp); + wpabuf_clear_free(resp); return -1; } - wpabuf_free(resp); + wpabuf_clear_free(resp); return 0; } @@ -1282,8 +1299,9 @@ static int eap_ttls_process_decrypted(struct eap_sm *sm, } else if (config->pending_req_identity || config->pending_req_password || config->pending_req_otp || - config->pending_req_new_password) { - wpabuf_free(data->pending_phase2_req); + config->pending_req_new_password || + config->pending_req_sim) { + wpabuf_clear_free(data->pending_phase2_req); data->pending_phase2_req = wpabuf_dup(in_decrypted); } @@ -1319,13 +1337,14 @@ static int eap_ttls_implicit_identity_request(struct eap_sm *sm, (config->pending_req_identity || config->pending_req_password || config->pending_req_otp || - config->pending_req_new_password)) { + config->pending_req_new_password || + config->pending_req_sim)) { /* * Use empty buffer to force implicit request * processing when EAP request is re-processed after * user input. */ - wpabuf_free(data->pending_phase2_req); + wpabuf_clear_free(data->pending_phase2_req); data->pending_phase2_req = wpabuf_alloc(0); } @@ -1398,7 +1417,7 @@ static int eap_ttls_decrypt(struct eap_sm *sm, struct eap_ttls_data *data, in_decrypted = data->pending_phase2_req; data->pending_phase2_req = NULL; if (wpabuf_len(in_decrypted) == 0) { - wpabuf_free(in_decrypted); + wpabuf_clear_free(in_decrypted); return eap_ttls_implicit_identity_request( sm, data, ret, identifier, out_data); } @@ -1434,7 +1453,7 @@ continue_req: &parse, in_decrypted, out_data); done: - wpabuf_free(in_decrypted); + wpabuf_clear_free(in_decrypted); os_free(parse.eapdata); if (retval < 0) { @@ -1494,7 +1513,7 @@ static int eap_ttls_process_handshake(struct eap_sm *sm, if (sm->waiting_ext_cert_check) { wpa_printf(MSG_DEBUG, "EAP-TTLS: Waiting external server certificate validation"); - wpabuf_free(data->pending_resp); + wpabuf_clear_free(data->pending_resp); data->pending_resp = *out_data; *out_data = NULL; return 0; @@ -1528,7 +1547,7 @@ static int eap_ttls_process_handshake(struct eap_sm *sm, /* * Application data included in the handshake message. */ - wpabuf_free(data->pending_phase2_req); + wpabuf_clear_free(data->pending_phase2_req); data->pending_phase2_req = *out_data; *out_data = NULL; res = eap_ttls_decrypt(sm, data, ret, identifier, in_data, @@ -1539,7 +1558,7 @@ static int eap_ttls_process_handshake(struct eap_sm *sm, } -static void eap_ttls_check_auth_status(struct eap_sm *sm, +static void eap_ttls_check_auth_status(struct eap_sm *sm, struct eap_ttls_data *data, struct eap_method_ret *ret) { @@ -1631,7 +1650,7 @@ static struct wpabuf * eap_ttls_process(struct eap_sm *sm, void *priv, /* FIX: what about res == -1? Could just move all error processing into * the other functions and get rid of this res==1 case here. */ if (res == 1) { - wpabuf_free(resp); + wpabuf_clear_free(resp); return eap_peer_tls_build_ack(id, EAP_TYPE_TTLS, data->ttls_version); } @@ -1650,9 +1669,13 @@ static Boolean eap_ttls_has_reauth_data(struct eap_sm *sm, void *priv) static void eap_ttls_deinit_for_reauth(struct eap_sm *sm, void *priv) { struct eap_ttls_data *data = priv; - wpabuf_free(data->pending_phase2_req); + + if (data->phase2_priv && data->phase2_method && + data->phase2_method->deinit_for_reauth) + data->phase2_method->deinit_for_reauth(sm, data->phase2_priv); + wpabuf_clear_free(data->pending_phase2_req); data->pending_phase2_req = NULL; - wpabuf_free(data->pending_resp); + wpabuf_clear_free(data->pending_resp); data->pending_resp = NULL; data->decision_succ = DECISION_FAIL; #ifdef EAP_TNC @@ -1741,12 +1764,11 @@ static u8 * eap_ttls_getKey(struct eap_sm *sm, void *priv, size_t *len) if (data->key_data == NULL || !data->phase2_success) return NULL; - key = os_malloc(EAP_TLS_KEY_LEN); + key = os_memdup(data->key_data, EAP_TLS_KEY_LEN); if (key == NULL) return NULL; *len = EAP_TLS_KEY_LEN; - os_memcpy(key, data->key_data, EAP_TLS_KEY_LEN); return key; } @@ -1760,12 +1782,11 @@ static u8 * eap_ttls_get_session_id(struct eap_sm *sm, void *priv, size_t *len) if (data->session_id == NULL || !data->phase2_success) return NULL; - id = os_malloc(data->id_len); + id = os_memdup(data->session_id, data->id_len); if (id == NULL) return NULL; *len = data->id_len; - os_memcpy(id, data->session_id, data->id_len); return id; } @@ -1779,12 +1800,11 @@ static u8 * eap_ttls_get_emsk(struct eap_sm *sm, void *priv, size_t *len) if (data->key_data == NULL) return NULL; - key = os_malloc(EAP_EMSK_LEN); + key = os_memdup(data->key_data + EAP_TLS_KEY_LEN, EAP_EMSK_LEN); if (key == NULL) return NULL; *len = EAP_EMSK_LEN; - os_memcpy(key, data->key_data + EAP_TLS_KEY_LEN, EAP_EMSK_LEN); return key; } diff --git a/freebsd/contrib/wpa/src/eapol_auth/eapol_auth_sm.h b/freebsd/contrib/wpa/src/eapol_auth/eapol_auth_sm.h index e1974e43..44f3f31c 100644 --- a/freebsd/contrib/wpa/src/eapol_auth/eapol_auth_sm.h +++ b/freebsd/contrib/wpa/src/eapol_auth/eapol_auth_sm.h @@ -28,6 +28,7 @@ struct eapol_auth_config { char *erp_domain; /* a copy of this will be allocated */ int erp; /* Whether ERP is enabled on authentication server */ unsigned int tls_session_lifetime; + unsigned int tls_flags; u8 *pac_opaque_encr_key; u8 *eap_fast_a_id; size_t eap_fast_a_id_len; diff --git a/freebsd/contrib/wpa/src/eapol_supp/eapol_supp_sm.c b/freebsd/contrib/wpa/src/eapol_supp/eapol_supp_sm.c index 938e0d05..c69f815e 100644 --- a/freebsd/contrib/wpa/src/eapol_supp/eapol_supp_sm.c +++ b/freebsd/contrib/wpa/src/eapol_supp/eapol_supp_sm.c @@ -18,6 +18,7 @@ #include "crypto/md5.h" #include "common/eapol_common.h" #include "eap_peer/eap.h" +#include "eap_peer/eap_config.h" #include "eap_peer/eap_proxy.h" #include "eapol_supp_sm.h" @@ -97,7 +98,7 @@ struct eapol_sm { SUPP_BE_RECEIVE = 4, SUPP_BE_RESPONSE = 5, SUPP_BE_FAIL = 6, - SUPP_BE_TIMEOUT = 7, + SUPP_BE_TIMEOUT = 7, SUPP_BE_SUCCESS = 8 } SUPP_BE_state; /* dot1xSuppBackendPaeState */ /* Variables */ @@ -190,8 +191,9 @@ static void eapol_port_timers_tick(void *eloop_ctx, void *timeout_ctx) } if (sm->authWhile | sm->heldWhile | sm->startWhen | sm->idleWhile) { - eloop_register_timeout(1, 0, eapol_port_timers_tick, eloop_ctx, - sm); + if (eloop_register_timeout(1, 0, eapol_port_timers_tick, + eloop_ctx, sm) < 0) + sm->timer_tick_enabled = 0; } else { wpa_printf(MSG_DEBUG, "EAPOL: disable timer tick"); sm->timer_tick_enabled = 0; @@ -205,9 +207,9 @@ static void eapol_enable_timer_tick(struct eapol_sm *sm) if (sm->timer_tick_enabled) return; wpa_printf(MSG_DEBUG, "EAPOL: enable timer tick"); - sm->timer_tick_enabled = 1; eloop_cancel_timeout(eapol_port_timers_tick, NULL, sm); - eloop_register_timeout(1, 0, eapol_port_timers_tick, NULL, sm); + if (eloop_register_timeout(1, 0, eapol_port_timers_tick, NULL, sm) == 0) + sm->timer_tick_enabled = 1; } @@ -252,6 +254,8 @@ SM_STATE(SUPP_PAE, CONNECTING) if (sm->eapTriggerStart) send_start = 1; + if (sm->ctx->preauth) + send_start = 1; sm->eapTriggerStart = FALSE; if (send_start) { @@ -492,9 +496,24 @@ SM_STATE(SUPP_BE, SUCCESS) #ifdef CONFIG_EAP_PROXY if (sm->use_eap_proxy) { if (eap_proxy_key_available(sm->eap_proxy)) { + u8 *session_id, *emsk; + size_t session_id_len, emsk_len; + /* New key received - clear IEEE 802.1X EAPOL-Key replay * counter */ sm->replay_counter_valid = FALSE; + + session_id = eap_proxy_get_eap_session_id( + sm->eap_proxy, &session_id_len); + emsk = eap_proxy_get_emsk(sm->eap_proxy, &emsk_len); + if (sm->config->erp && session_id && emsk) { + eap_peer_erp_init(sm->eap, session_id, + session_id_len, emsk, + emsk_len); + } else { + os_free(session_id); + bin_clear_free(emsk, emsk_len); + } } return; } @@ -899,6 +918,9 @@ static void eapol_sm_abortSupp(struct eapol_sm *sm) wpabuf_free(sm->eapReqData); sm->eapReqData = NULL; eap_sm_abort(sm->eap); +#ifdef CONFIG_EAP_PROXY + eap_proxy_sm_abort(sm->eap_proxy); +#endif /* CONFIG_EAP_PROXY */ } @@ -2000,7 +2022,17 @@ static void eapol_sm_notify_status(void *ctx, const char *status, } +static void eapol_sm_notify_eap_error(void *ctx, int error_code) +{ + struct eapol_sm *sm = ctx; + + if (sm->ctx->eap_error_cb) + sm->ctx->eap_error_cb(sm->ctx->ctx, error_code); +} + + #ifdef CONFIG_EAP_PROXY + static void eapol_sm_eap_proxy_cb(void *ctx) { struct eapol_sm *sm = ctx; @@ -2008,6 +2040,18 @@ static void eapol_sm_eap_proxy_cb(void *ctx) if (sm->ctx->eap_proxy_cb) sm->ctx->eap_proxy_cb(sm->ctx->ctx); } + + +static void +eapol_sm_eap_proxy_notify_sim_status(void *ctx, + enum eap_proxy_sim_state sim_state) +{ + struct eapol_sm *sm = ctx; + + if (sm->ctx->eap_proxy_notify_sim_status) + sm->ctx->eap_proxy_notify_sim_status(sm->ctx->ctx, sim_state); +} + #endif /* CONFIG_EAP_PROXY */ @@ -2034,8 +2078,11 @@ static const struct eapol_callbacks eapol_cb = eapol_sm_eap_param_needed, eapol_sm_notify_cert, eapol_sm_notify_status, + eapol_sm_notify_eap_error, #ifdef CONFIG_EAP_PROXY eapol_sm_eap_proxy_cb, + eapol_sm_eap_proxy_notify_sim_status, + eapol_sm_get_eap_proxy_imsi, #endif /* CONFIG_EAP_PROXY */ eapol_sm_set_anon_id }; @@ -2097,8 +2144,8 @@ struct eapol_sm *eapol_sm_init(struct eapol_ctx *ctx) sm->initialize = FALSE; eapol_sm_step(sm); - sm->timer_tick_enabled = 1; - eloop_register_timeout(1, 0, eapol_port_timers_tick, NULL, sm); + if (eloop_register_timeout(1, 0, eapol_port_timers_tick, NULL, sm) == 0) + sm->timer_tick_enabled = 1; return sm; } @@ -2143,16 +2190,16 @@ int eapol_sm_failed(struct eapol_sm *sm) } -int eapol_sm_get_eap_proxy_imsi(struct eapol_sm *sm, char *imsi, size_t *len) -{ #ifdef CONFIG_EAP_PROXY +int eapol_sm_get_eap_proxy_imsi(void *ctx, int sim_num, char *imsi, size_t *len) +{ + struct eapol_sm *sm = ctx; + if (sm->eap_proxy == NULL) return -1; - return eap_proxy_get_imsi(sm->eap_proxy, imsi, len); -#else /* CONFIG_EAP_PROXY */ - return -1; -#endif /* CONFIG_EAP_PROXY */ + return eap_proxy_get_imsi(sm->eap_proxy, sim_num, imsi, len); } +#endif /* CONFIG_EAP_PROXY */ void eapol_sm_erp_flush(struct eapol_sm *sm) @@ -2160,3 +2207,56 @@ void eapol_sm_erp_flush(struct eapol_sm *sm) if (sm) eap_peer_erp_free_keys(sm->eap); } + + +struct wpabuf * eapol_sm_build_erp_reauth_start(struct eapol_sm *sm) +{ +#ifdef CONFIG_ERP + if (!sm) + return NULL; + return eap_peer_build_erp_reauth_start(sm->eap, 0); +#else /* CONFIG_ERP */ + return NULL; +#endif /* CONFIG_ERP */ +} + + +void eapol_sm_process_erp_finish(struct eapol_sm *sm, const u8 *buf, + size_t len) +{ +#ifdef CONFIG_ERP + if (!sm) + return; + eap_peer_finish(sm->eap, (const struct eap_hdr *) buf, len); +#endif /* CONFIG_ERP */ +} + + +int eapol_sm_update_erp_next_seq_num(struct eapol_sm *sm, u16 next_seq_num) +{ +#ifdef CONFIG_ERP + if (!sm) + return -1; + return eap_peer_update_erp_next_seq_num(sm->eap, next_seq_num); +#else /* CONFIG_ERP */ + return -1; +#endif /* CONFIG_ERP */ +} + + +int eapol_sm_get_erp_info(struct eapol_sm *sm, struct eap_peer_config *config, + const u8 **username, size_t *username_len, + const u8 **realm, size_t *realm_len, + u16 *erp_next_seq_num, const u8 **rrk, + size_t *rrk_len) +{ +#ifdef CONFIG_ERP + if (!sm) + return -1; + return eap_peer_get_erp_info(sm->eap, config, username, username_len, + realm, realm_len, erp_next_seq_num, rrk, + rrk_len); +#else /* CONFIG_ERP */ + return -1; +#endif /* CONFIG_ERP */ +} diff --git a/freebsd/contrib/wpa/src/eapol_supp/eapol_supp_sm.h b/freebsd/contrib/wpa/src/eapol_supp/eapol_supp_sm.h index 1309ff75..74f40bb1 100644 --- a/freebsd/contrib/wpa/src/eapol_supp/eapol_supp_sm.h +++ b/freebsd/contrib/wpa/src/eapol_supp/eapol_supp_sm.h @@ -271,12 +271,27 @@ struct eapol_ctx { void (*status_cb)(void *ctx, const char *status, const char *parameter); + /** + * eap_error_cb - Notification of EAP method error + * @ctx: Callback context (ctx) + * @error_code: EAP method error code + */ + void (*eap_error_cb)(void *ctx, int error_code); + #ifdef CONFIG_EAP_PROXY /** * eap_proxy_cb - Callback signifying any updates from eap_proxy * @ctx: eapol_ctx from eap_peer_sm_init() call */ void (*eap_proxy_cb)(void *ctx); + + /** + * eap_proxy_notify_sim_status - Notification of SIM status change + * @ctx: eapol_ctx from eap_peer_sm_init() call + * @status: One of enum value from sim_state + */ + void (*eap_proxy_notify_sim_status)(void *ctx, + enum eap_proxy_sim_state sim_state); #endif /* CONFIG_EAP_PROXY */ /** @@ -328,7 +343,18 @@ void eapol_sm_set_ext_pw_ctx(struct eapol_sm *sm, struct ext_password_data *ext); int eapol_sm_failed(struct eapol_sm *sm); void eapol_sm_erp_flush(struct eapol_sm *sm); -int eapol_sm_get_eap_proxy_imsi(struct eapol_sm *sm, char *imsi, size_t *len); +struct wpabuf * eapol_sm_build_erp_reauth_start(struct eapol_sm *sm); +void eapol_sm_process_erp_finish(struct eapol_sm *sm, const u8 *buf, + size_t len); +int eapol_sm_get_eap_proxy_imsi(void *ctx, int sim_num, char *imsi, + size_t *len); +int eapol_sm_update_erp_next_seq_num(struct eapol_sm *sm, u16 next_seq_num); +int eapol_sm_get_erp_info(struct eapol_sm *sm, struct eap_peer_config *config, + const u8 **username, size_t *username_len, + const u8 **realm, size_t *realm_len, + u16 *erp_next_seq_num, const u8 **rrk, + size_t *rrk_len); + #else /* IEEE8021X_EAPOL */ static inline struct eapol_sm *eapol_sm_init(struct eapol_ctx *ctx) { @@ -438,6 +464,28 @@ static inline int eapol_sm_failed(struct eapol_sm *sm) static inline void eapol_sm_erp_flush(struct eapol_sm *sm) { } +static inline struct wpabuf * +eapol_sm_build_erp_reauth_start(struct eapol_sm *sm) +{ + return NULL; +} +static inline void eapol_sm_process_erp_finish(struct eapol_sm *sm, + const u8 *buf, size_t len) +{ +} +static inline int eapol_sm_update_erp_next_seq_num(struct eapol_sm *sm, + u16 next_seq_num) +{ + return -1; +} +static inline int +eapol_sm_get_erp_info(struct eapol_sm *sm, struct eap_peer_config *config, + const u8 **username, size_t *username_len, + const u8 **realm, size_t *realm_len, + u16 *erp_next_seq_num, const u8 **rrk, size_t *rrk_len) +{ + return -1; +} #endif /* IEEE8021X_EAPOL */ #endif /* EAPOL_SUPP_SM_H */ diff --git a/freebsd/contrib/wpa/src/fst/fst.h b/freebsd/contrib/wpa/src/fst/fst.h index 0c0e435b..29674912 100644 --- a/freebsd/contrib/wpa/src/fst/fst.h +++ b/freebsd/contrib/wpa/src/fst/fst.h @@ -19,10 +19,18 @@ #define US_IN_MS 1000 #define LLT_UNIT_US 32 /* See 10.32.2.2 Transitioning between states */ -#define FST_LLT_MS_TO_VAL(m) (((u32) (m)) * US_IN_MS / LLT_UNIT_US) -#define FST_LLT_VAL_TO_MS(v) (((u32) (v)) * LLT_UNIT_US / US_IN_MS) - -#define FST_MAX_LLT_MS FST_LLT_VAL_TO_MS(-1) +/* + * These were originally + * #define FST_LLT_MS_TO_VAL(m) (((u32) (m)) * US_IN_MS / LLT_UNIT_US) + * #define FST_LLT_VAL_TO_MS(v) (((u32) (v)) * LLT_UNIT_US / US_IN_MS) + * #define FST_MAX_LLT_MS FST_LLT_VAL_TO_MS(-1) + * but those can overflow 32-bit unsigned integer, so use alternative defines + * to avoid undefined behavior with such overflow. + * LLT_UNIT_US/US_IN_MS = 32/1000 = 4/125 + */ +#define FST_LLT_MS_TO_VAL(m) (((u32) (m)) * 125 / 4) +#define FST_LLT_VAL_TO_MS(v) (((u32) (v)) * 4 / 125) +#define FST_MAX_LLT_MS (((u32) -1) / 4) #define FST_MAX_PRIO_VALUE ((u8) -1) #define FST_MAX_GROUP_ID_LEN IFNAMSIZ diff --git a/freebsd/contrib/wpa/src/fst/fst_ctrl_aux.h b/freebsd/contrib/wpa/src/fst/fst_ctrl_aux.h index e2133f50..0aff5d06 100644 --- a/freebsd/contrib/wpa/src/fst/fst_ctrl_aux.h +++ b/freebsd/contrib/wpa/src/fst/fst_ctrl_aux.h @@ -35,6 +35,17 @@ enum fst_event_type { * more info */ }; +enum fst_reason { + REASON_TEARDOWN, + REASON_SETUP, + REASON_SWITCH, + REASON_STT, + REASON_REJECT, + REASON_ERROR_PARAMS, + REASON_RESET, + REASON_DETACH_IFACE, +}; + enum fst_initiator { FST_INITIATOR_UNDEFINED, FST_INITIATOR_LOCAL, @@ -57,16 +68,7 @@ union fst_event_extra { enum fst_session_state new_state; union fst_session_state_switch_extra { struct { - enum fst_reason { - REASON_TEARDOWN, - REASON_SETUP, - REASON_SWITCH, - REASON_STT, - REASON_REJECT, - REASON_ERROR_PARAMS, - REASON_RESET, - REASON_DETACH_IFACE, - } reason; + enum fst_reason reason; u8 reject_code; /* REASON_REJECT */ /* REASON_SWITCH, * REASON_TEARDOWN, diff --git a/freebsd/contrib/wpa/src/l2_packet/l2_packet.h b/freebsd/contrib/wpa/src/l2_packet/l2_packet.h index 2a452458..53871774 100644 --- a/freebsd/contrib/wpa/src/l2_packet/l2_packet.h +++ b/freebsd/contrib/wpa/src/l2_packet/l2_packet.h @@ -42,6 +42,7 @@ struct l2_ethhdr { enum l2_packet_filter_type { L2_PACKET_FILTER_DHCP, L2_PACKET_FILTER_NDISC, + L2_PACKET_FILTER_PKTTYPE, }; /** diff --git a/freebsd/contrib/wpa/src/p2p/p2p.h b/freebsd/contrib/wpa/src/p2p/p2p.h index 7b18dcfc..425b037b 100644 --- a/freebsd/contrib/wpa/src/p2p/p2p.h +++ b/freebsd/contrib/wpa/src/p2p/p2p.h @@ -104,6 +104,11 @@ struct p2p_go_neg_results { unsigned int vht_center_freq2; /** + * he - Indicates if IEEE 802.11ax HE is enabled + */ + int he; + + /** * ssid - SSID of the group */ u8 ssid[SSID_MAX_LEN]; @@ -660,6 +665,8 @@ struct p2p_config { * @buf: Frame body (starting from Category field) * @len: Length of buf in octets * @wait_time: How many msec to wait for a response frame + * @scheduled: Return value indicating whether the transmissions was + * scheduled to happen once the radio is available * Returns: 0 on success, -1 on failure * * The Action frame may not be transmitted immediately and the status @@ -670,7 +677,7 @@ struct p2p_config { */ int (*send_action)(void *ctx, unsigned int freq, const u8 *dst, const u8 *src, const u8 *bssid, const u8 *buf, - size_t len, unsigned int wait_time); + size_t len, unsigned int wait_time, int *scheduled); /** * send_action_done - Notify that Action frame sequence was completed @@ -2005,6 +2012,8 @@ void p2p_set_managed_oper(struct p2p_data *p2p, int enabled); * @p2p: P2P config * @op_class: Selected operating class * @op_channel: Selected social channel + * @avoid_list: Channel ranges to try to avoid or %NULL + * @disallow_list: Channel ranges to discard or %NULL * Returns: 0 on success, -1 on failure * * This function is used before p2p_init is called. A random social channel @@ -2012,7 +2021,9 @@ void p2p_set_managed_oper(struct p2p_data *p2p, int enabled); * returned on success. */ int p2p_config_get_random_social(struct p2p_config *p2p, u8 *op_class, - u8 *op_channel); + u8 *op_channel, + struct wpa_freq_range_list *avoid_list, + struct wpa_freq_range_list *disallow_list); int p2p_set_listen_channel(struct p2p_data *p2p, u8 reg_class, u8 channel, u8 forced); @@ -2266,6 +2277,7 @@ int p2p_set_wfd_ie_prov_disc_req(struct p2p_data *p2p, struct wpabuf *ie); int p2p_set_wfd_ie_prov_disc_resp(struct p2p_data *p2p, struct wpabuf *ie); int p2p_set_wfd_ie_go_neg(struct p2p_data *p2p, struct wpabuf *ie); int p2p_set_wfd_dev_info(struct p2p_data *p2p, const struct wpabuf *elem); +int p2p_set_wfd_r2_dev_info(struct p2p_data *p2p, const struct wpabuf *elem); int p2p_set_wfd_assoc_bssid(struct p2p_data *p2p, const struct wpabuf *elem); int p2p_set_wfd_coupled_sink_info(struct p2p_data *p2p, const struct wpabuf *elem); @@ -2373,6 +2385,8 @@ void p2p_expire_peers(struct p2p_data *p2p); void p2p_set_own_pref_freq_list(struct p2p_data *p2p, const unsigned int *pref_freq_list, unsigned int size); +void p2p_set_override_pref_op_chan(struct p2p_data *p2p, u8 op_class, + u8 chan); /** * p2p_group_get_common_freqs - Get the group common frequencies diff --git a/freebsd/contrib/wpa/src/radius/radius.h b/freebsd/contrib/wpa/src/radius/radius.h index cd510d2c..630c0f9d 100644 --- a/freebsd/contrib/wpa/src/radius/radius.h +++ b/freebsd/contrib/wpa/src/radius/radius.h @@ -102,8 +102,13 @@ enum { RADIUS_ATTR_USER_NAME = 1, RADIUS_ATTR_EXTENDED_LOCATION_POLICY_RULES = 130, RADIUS_ATTR_LOCATION_CAPABLE = 131, RADIUS_ATTR_REQUESTED_LOCATION_INFO = 132, + RADIUS_ATTR_GSS_ACCEPTOR_SERVICE_NAME = 164, + RADIUS_ATTR_GSS_ACCEPTOR_HOST_NAME = 165, + RADIUS_ATTR_GSS_ACCEPTOR_SERVICE_SPECIFICS = 166, + RADIUS_ATTR_GSS_ACCEPTOR_REALM_NAME = 167, RADIUS_ATTR_MOBILITY_DOMAIN_ID = 177, RADIUS_ATTR_WLAN_HESSID = 181, + RADIUS_ATTR_WLAN_REASON_CODE = 185, RADIUS_ATTR_WLAN_PAIRWISE_CIPHER = 186, RADIUS_ATTR_WLAN_GROUP_CIPHER = 187, RADIUS_ATTR_WLAN_AKM_SUITE = 188, @@ -193,6 +198,11 @@ enum { RADIUS_VENDOR_ATTR_WFA_HS20_STA_VERSION = 3, RADIUS_VENDOR_ATTR_WFA_HS20_DEAUTH_REQ = 4, RADIUS_VENDOR_ATTR_WFA_HS20_SESSION_INFO_URL = 5, + RADIUS_VENDOR_ATTR_WFA_HS20_ROAMING_CONSORTIUM = 6, + RADIUS_VENDOR_ATTR_WFA_HS20_T_C_FILENAME = 7, + RADIUS_VENDOR_ATTR_WFA_HS20_TIMESTAMP = 8, + RADIUS_VENDOR_ATTR_WFA_HS20_T_C_FILTERING = 9, + RADIUS_VENDOR_ATTR_WFA_HS20_T_C_URL = 10, }; #ifdef _MSC_VER diff --git a/freebsd/contrib/wpa/src/rsn_supp/peerkey.c b/freebsd/contrib/wpa/src/rsn_supp/peerkey.c deleted file mode 100644 index 87263f86..00000000 --- a/freebsd/contrib/wpa/src/rsn_supp/peerkey.c +++ /dev/null @@ -1,1157 +0,0 @@ -#include <machine/rtems-bsd-user-space.h> - -/* - * WPA Supplicant - PeerKey for Direct Link Setup (DLS) - * Copyright (c) 2006-2015, Jouni Malinen <j@w1.fi> - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#include "includes.h" - -#ifdef CONFIG_PEERKEY - -#include "common.h" -#include "eloop.h" -#include "crypto/sha1.h" -#include "crypto/sha256.h" -#include "crypto/random.h" -#include "common/ieee802_11_defs.h" -#include "wpa.h" -#include "wpa_i.h" -#include "wpa_ie.h" -#include "peerkey.h" - - -static u8 * wpa_add_ie(u8 *pos, const u8 *ie, size_t ie_len) -{ - os_memcpy(pos, ie, ie_len); - return pos + ie_len; -} - - -static u8 * wpa_add_kde(u8 *pos, u32 kde, const u8 *data, size_t data_len) -{ - *pos++ = WLAN_EID_VENDOR_SPECIFIC; - *pos++ = RSN_SELECTOR_LEN + data_len; - RSN_SELECTOR_PUT(pos, kde); - pos += RSN_SELECTOR_LEN; - os_memcpy(pos, data, data_len); - pos += data_len; - return pos; -} - - -static void wpa_supplicant_smk_timeout(void *eloop_ctx, void *timeout_ctx) -{ -#if 0 - struct wpa_sm *sm = eloop_ctx; - struct wpa_peerkey *peerkey = timeout_ctx; -#endif - /* TODO: time out SMK and any STK that was generated using this SMK */ -} - - -static void wpa_supplicant_peerkey_free(struct wpa_sm *sm, - struct wpa_peerkey *peerkey) -{ - eloop_cancel_timeout(wpa_supplicant_smk_timeout, sm, peerkey); - os_free(peerkey); -} - - -static int wpa_supplicant_send_smk_error(struct wpa_sm *sm, const u8 *dst, - const u8 *peer, - u16 mui, u16 error_type, int ver) -{ - size_t rlen; - struct wpa_eapol_key *err; - struct wpa_eapol_key_192 *err192; - struct rsn_error_kde error; - u8 *rbuf, *pos; - size_t kde_len; - u16 key_info; - - kde_len = 2 + RSN_SELECTOR_LEN + sizeof(error); - if (peer) - kde_len += 2 + RSN_SELECTOR_LEN + ETH_ALEN; - - rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, - NULL, sizeof(*err) + kde_len, &rlen, - (void *) &err); - if (rbuf == NULL) - return -1; - err192 = (struct wpa_eapol_key_192 *) err; - - err->type = EAPOL_KEY_TYPE_RSN; - key_info = ver | WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_MIC | - WPA_KEY_INFO_SECURE | WPA_KEY_INFO_ERROR | - WPA_KEY_INFO_REQUEST; - WPA_PUT_BE16(err->key_info, key_info); - WPA_PUT_BE16(err->key_length, 0); - os_memcpy(err->replay_counter, sm->request_counter, - WPA_REPLAY_COUNTER_LEN); - inc_byte_array(sm->request_counter, WPA_REPLAY_COUNTER_LEN); - - WPA_PUT_BE16(err->key_data_length, (u16) kde_len); - pos = (u8 *) (err + 1); - - if (peer) { - /* Peer MAC Address KDE */ - pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peer, ETH_ALEN); - } - - /* Error KDE */ - error.mui = host_to_be16(mui); - error.error_type = host_to_be16(error_type); - wpa_add_kde(pos, RSN_KEY_DATA_ERROR, (u8 *) &error, sizeof(error)); - - if (peer) { - wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key SMK Error (peer " - MACSTR " mui %d error_type %d)", - MAC2STR(peer), mui, error_type); - } else { - wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key SMK Error " - "(mui %d error_type %d)", mui, error_type); - } - - wpa_eapol_key_send(sm, sm->ptk.kck, sm->ptk.kck_len, ver, dst, - ETH_P_EAPOL, rbuf, rlen, err192->key_mic); - - return 0; -} - - -static int wpa_supplicant_send_smk_m3(struct wpa_sm *sm, - const unsigned char *src_addr, - const struct wpa_eapol_key *key, - int ver, struct wpa_peerkey *peerkey) -{ - size_t rlen; - struct wpa_eapol_key *reply; - struct wpa_eapol_key_192 *reply192; - u8 *rbuf, *pos; - size_t kde_len; - u16 key_info; - - /* KDEs: Peer RSN IE, Initiator MAC Address, Initiator Nonce */ - kde_len = peerkey->rsnie_p_len + - 2 + RSN_SELECTOR_LEN + ETH_ALEN + - 2 + RSN_SELECTOR_LEN + WPA_NONCE_LEN; - - rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, - NULL, sizeof(*reply) + kde_len, &rlen, - (void *) &reply); - if (rbuf == NULL) - return -1; - reply192 = (struct wpa_eapol_key_192 *) reply; - - reply->type = EAPOL_KEY_TYPE_RSN; - key_info = ver | WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_MIC | - WPA_KEY_INFO_SECURE; - WPA_PUT_BE16(reply->key_info, key_info); - WPA_PUT_BE16(reply->key_length, 0); - os_memcpy(reply->replay_counter, key->replay_counter, - WPA_REPLAY_COUNTER_LEN); - - os_memcpy(reply->key_nonce, peerkey->pnonce, WPA_NONCE_LEN); - - WPA_PUT_BE16(reply->key_data_length, (u16) kde_len); - pos = (u8 *) (reply + 1); - - /* Peer RSN IE */ - pos = wpa_add_ie(pos, peerkey->rsnie_p, peerkey->rsnie_p_len); - - /* Initiator MAC Address KDE */ - pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peerkey->addr, ETH_ALEN); - - /* Initiator Nonce */ - wpa_add_kde(pos, RSN_KEY_DATA_NONCE, peerkey->inonce, WPA_NONCE_LEN); - - wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key SMK M3"); - wpa_eapol_key_send(sm, sm->ptk.kck, sm->ptk.kck_len, ver, src_addr, - ETH_P_EAPOL, rbuf, rlen, reply192->key_mic); - - return 0; -} - - -static int wpa_supplicant_process_smk_m2( - struct wpa_sm *sm, const unsigned char *src_addr, - const struct wpa_eapol_key *key, size_t extra_len, int ver) -{ - struct wpa_peerkey *peerkey; - struct wpa_eapol_ie_parse kde; - struct wpa_ie_data ie; - int cipher; - struct rsn_ie_hdr *hdr; - u8 *pos; - - wpa_printf(MSG_DEBUG, "RSN: Received SMK M2"); - - if (!sm->peerkey_enabled || sm->proto != WPA_PROTO_RSN) { - wpa_printf(MSG_INFO, "RSN: SMK handshake not allowed for " - "the current network"); - return -1; - } - - if (wpa_supplicant_parse_ies((const u8 *) (key + 1), extra_len, &kde) < - 0) { - wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK M2"); - return -1; - } - - if (kde.rsn_ie == NULL || kde.mac_addr == NULL || - kde.mac_addr_len < ETH_ALEN) { - wpa_printf(MSG_INFO, "RSN: No RSN IE or MAC address KDE in " - "SMK M2"); - return -1; - } - - wpa_printf(MSG_DEBUG, "RSN: SMK M2 - SMK initiator " MACSTR, - MAC2STR(kde.mac_addr)); - - if (kde.rsn_ie_len > PEERKEY_MAX_IE_LEN) { - wpa_printf(MSG_INFO, "RSN: Too long Initiator RSN IE in SMK " - "M2"); - return -1; - } - - if (wpa_parse_wpa_ie_rsn(kde.rsn_ie, kde.rsn_ie_len, &ie) < 0) { - wpa_printf(MSG_INFO, "RSN: Failed to parse RSN IE in SMK M2"); - return -1; - } - - cipher = wpa_pick_pairwise_cipher(ie.pairwise_cipher & - sm->allowed_pairwise_cipher, 0); - if (cipher < 0) { - wpa_printf(MSG_INFO, "RSN: No acceptable cipher in SMK M2"); - wpa_supplicant_send_smk_error(sm, src_addr, kde.mac_addr, - STK_MUI_SMK, STK_ERR_CPHR_NS, - ver); - return -1; - } - wpa_printf(MSG_DEBUG, "RSN: Using %s for PeerKey", - wpa_cipher_txt(cipher)); - - /* TODO: find existing entry and if found, use that instead of adding - * a new one; how to handle the case where both ends initiate at the - * same time? */ - peerkey = os_zalloc(sizeof(*peerkey)); - if (peerkey == NULL) - return -1; - os_memcpy(peerkey->addr, kde.mac_addr, ETH_ALEN); - os_memcpy(peerkey->inonce, key->key_nonce, WPA_NONCE_LEN); - os_memcpy(peerkey->rsnie_i, kde.rsn_ie, kde.rsn_ie_len); - peerkey->rsnie_i_len = kde.rsn_ie_len; - peerkey->cipher = cipher; - peerkey->akmp = ie.key_mgmt; - - if (random_get_bytes(peerkey->pnonce, WPA_NONCE_LEN)) { - wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, - "WPA: Failed to get random data for PNonce"); - wpa_supplicant_peerkey_free(sm, peerkey); - return -1; - } - - hdr = (struct rsn_ie_hdr *) peerkey->rsnie_p; - hdr->elem_id = WLAN_EID_RSN; - WPA_PUT_LE16(hdr->version, RSN_VERSION); - pos = (u8 *) (hdr + 1); - /* Group Suite can be anything for SMK RSN IE; receiver will just - * ignore it. */ - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP); - pos += RSN_SELECTOR_LEN; - /* Include only the selected cipher in pairwise cipher suite */ - WPA_PUT_LE16(pos, 1); - pos += 2; - RSN_SELECTOR_PUT(pos, wpa_cipher_to_suite(WPA_PROTO_RSN, cipher)); - pos += RSN_SELECTOR_LEN; - - hdr->len = (pos - peerkey->rsnie_p) - 2; - peerkey->rsnie_p_len = pos - peerkey->rsnie_p; - wpa_hexdump(MSG_DEBUG, "WPA: RSN IE for SMK handshake", - peerkey->rsnie_p, peerkey->rsnie_p_len); - - wpa_supplicant_send_smk_m3(sm, src_addr, key, ver, peerkey); - - peerkey->next = sm->peerkey; - sm->peerkey = peerkey; - - return 0; -} - - -/** - * rsn_smkid - Derive SMK identifier - * @smk: Station master key (32 bytes) - * @pnonce: Peer Nonce - * @mac_p: Peer MAC address - * @inonce: Initiator Nonce - * @mac_i: Initiator MAC address - * @akmp: Negotiated AKM - * - * 8.5.1.4 Station to station (STK) key hierarchy - * SMKID = HMAC-SHA1-128(SMK, "SMK Name" || PNonce || MAC_P || INonce || MAC_I) - */ -static void rsn_smkid(const u8 *smk, const u8 *pnonce, const u8 *mac_p, - const u8 *inonce, const u8 *mac_i, u8 *smkid, - int akmp) -{ - char *title = "SMK Name"; - const u8 *addr[5]; - const size_t len[5] = { 8, WPA_NONCE_LEN, ETH_ALEN, WPA_NONCE_LEN, - ETH_ALEN }; - unsigned char hash[SHA256_MAC_LEN]; - - addr[0] = (u8 *) title; - addr[1] = pnonce; - addr[2] = mac_p; - addr[3] = inonce; - addr[4] = mac_i; - -#ifdef CONFIG_IEEE80211W - if (wpa_key_mgmt_sha256(akmp)) - hmac_sha256_vector(smk, PMK_LEN, 5, addr, len, hash); - else -#endif /* CONFIG_IEEE80211W */ - hmac_sha1_vector(smk, PMK_LEN, 5, addr, len, hash); - os_memcpy(smkid, hash, PMKID_LEN); -} - - -static void wpa_supplicant_send_stk_1_of_4(struct wpa_sm *sm, - struct wpa_peerkey *peerkey) -{ - size_t mlen; - struct wpa_eapol_key *msg; - u8 *mbuf; - size_t kde_len; - u16 key_info, ver; - - kde_len = 2 + RSN_SELECTOR_LEN + PMKID_LEN; - - mbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, - sizeof(*msg) + kde_len, &mlen, - (void *) &msg); - if (mbuf == NULL) - return; - - msg->type = EAPOL_KEY_TYPE_RSN; - - if (peerkey->cipher != WPA_CIPHER_TKIP) - ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES; - else - ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4; - - key_info = ver | WPA_KEY_INFO_KEY_TYPE | WPA_KEY_INFO_ACK; - WPA_PUT_BE16(msg->key_info, key_info); - - if (peerkey->cipher != WPA_CIPHER_TKIP) - WPA_PUT_BE16(msg->key_length, 16); - else - WPA_PUT_BE16(msg->key_length, 32); - - os_memcpy(msg->replay_counter, peerkey->replay_counter, - WPA_REPLAY_COUNTER_LEN); - inc_byte_array(peerkey->replay_counter, WPA_REPLAY_COUNTER_LEN); - - WPA_PUT_BE16(msg->key_data_length, kde_len); - wpa_add_kde((u8 *) (msg + 1), RSN_KEY_DATA_PMKID, - peerkey->smkid, PMKID_LEN); - - if (random_get_bytes(peerkey->inonce, WPA_NONCE_LEN)) { - wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, - "RSN: Failed to get random data for INonce (STK)"); - os_free(mbuf); - return; - } - wpa_hexdump(MSG_DEBUG, "RSN: INonce for STK 4-Way Handshake", - peerkey->inonce, WPA_NONCE_LEN); - os_memcpy(msg->key_nonce, peerkey->inonce, WPA_NONCE_LEN); - - wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key STK 1/4 to " MACSTR, - MAC2STR(peerkey->addr)); - wpa_eapol_key_send(sm, NULL, 0, ver, peerkey->addr, ETH_P_EAPOL, - mbuf, mlen, NULL); -} - - -static void wpa_supplicant_send_stk_3_of_4(struct wpa_sm *sm, - struct wpa_peerkey *peerkey) -{ - size_t mlen; - struct wpa_eapol_key *msg; - u8 *mbuf, *pos; - size_t kde_len; - u16 key_info, ver; - be32 lifetime; - - kde_len = peerkey->rsnie_i_len + - 2 + RSN_SELECTOR_LEN + sizeof(lifetime); - - mbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, - sizeof(*msg) + kde_len, &mlen, - (void *) &msg); - if (mbuf == NULL) - return; - - msg->type = EAPOL_KEY_TYPE_RSN; - - if (peerkey->cipher != WPA_CIPHER_TKIP) - ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES; - else - ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4; - - key_info = ver | WPA_KEY_INFO_KEY_TYPE | WPA_KEY_INFO_ACK | - WPA_KEY_INFO_MIC | WPA_KEY_INFO_SECURE; - WPA_PUT_BE16(msg->key_info, key_info); - - if (peerkey->cipher != WPA_CIPHER_TKIP) - WPA_PUT_BE16(msg->key_length, 16); - else - WPA_PUT_BE16(msg->key_length, 32); - - os_memcpy(msg->replay_counter, peerkey->replay_counter, - WPA_REPLAY_COUNTER_LEN); - inc_byte_array(peerkey->replay_counter, WPA_REPLAY_COUNTER_LEN); - - WPA_PUT_BE16(msg->key_data_length, kde_len); - pos = (u8 *) (msg + 1); - pos = wpa_add_ie(pos, peerkey->rsnie_i, peerkey->rsnie_i_len); - lifetime = host_to_be32(peerkey->lifetime); - wpa_add_kde(pos, RSN_KEY_DATA_LIFETIME, - (u8 *) &lifetime, sizeof(lifetime)); - - os_memcpy(msg->key_nonce, peerkey->inonce, WPA_NONCE_LEN); - - wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key STK 3/4 to " MACSTR, - MAC2STR(peerkey->addr)); - wpa_eapol_key_send(sm, peerkey->stk.kck, peerkey->stk.kck_len, ver, - peerkey->addr, ETH_P_EAPOL, mbuf, mlen, - msg->key_mic); -} - - -static int wpa_supplicant_process_smk_m4(struct wpa_peerkey *peerkey, - struct wpa_eapol_ie_parse *kde) -{ - wpa_printf(MSG_DEBUG, "RSN: Received SMK M4 (Initiator " MACSTR ")", - MAC2STR(kde->mac_addr)); - - if (os_memcmp(kde->smk + PMK_LEN, peerkey->pnonce, WPA_NONCE_LEN) != 0) - { - wpa_printf(MSG_INFO, "RSN: PNonce in SMK KDE does not " - "match with the one used in SMK M3"); - return -1; - } - - if (os_memcmp(kde->nonce, peerkey->inonce, WPA_NONCE_LEN) != 0) { - wpa_printf(MSG_INFO, "RSN: INonce in SMK M4 did not " - "match with the one received in SMK M2"); - return -1; - } - - return 0; -} - - -static int wpa_supplicant_process_smk_m5(struct wpa_sm *sm, - const unsigned char *src_addr, - const struct wpa_eapol_key *key, - int ver, - struct wpa_peerkey *peerkey, - struct wpa_eapol_ie_parse *kde) -{ - int cipher; - struct wpa_ie_data ie; - - wpa_printf(MSG_DEBUG, "RSN: Received SMK M5 (Peer " MACSTR ")", - MAC2STR(kde->mac_addr)); - if (kde->rsn_ie == NULL || kde->rsn_ie_len > PEERKEY_MAX_IE_LEN || - wpa_parse_wpa_ie_rsn(kde->rsn_ie, kde->rsn_ie_len, &ie) < 0) { - wpa_printf(MSG_INFO, "RSN: No RSN IE in SMK M5"); - /* TODO: abort negotiation */ - return -1; - } - - if (os_memcmp(key->key_nonce, peerkey->inonce, WPA_NONCE_LEN) != 0) { - wpa_printf(MSG_INFO, "RSN: Key Nonce in SMK M5 does " - "not match with INonce used in SMK M1"); - return -1; - } - - if (os_memcmp(kde->smk + PMK_LEN, peerkey->inonce, WPA_NONCE_LEN) != 0) - { - wpa_printf(MSG_INFO, "RSN: INonce in SMK KDE does not " - "match with the one used in SMK M1"); - return -1; - } - - os_memcpy(peerkey->rsnie_p, kde->rsn_ie, kde->rsn_ie_len); - peerkey->rsnie_p_len = kde->rsn_ie_len; - os_memcpy(peerkey->pnonce, kde->nonce, WPA_NONCE_LEN); - - cipher = wpa_pick_pairwise_cipher(ie.pairwise_cipher & - sm->allowed_pairwise_cipher, 0); - if (cipher < 0) { - wpa_printf(MSG_INFO, "RSN: SMK Peer STA " MACSTR " selected " - "unacceptable cipher", MAC2STR(kde->mac_addr)); - wpa_supplicant_send_smk_error(sm, src_addr, kde->mac_addr, - STK_MUI_SMK, STK_ERR_CPHR_NS, - ver); - /* TODO: abort negotiation */ - return -1; - } - wpa_printf(MSG_DEBUG, "RSN: Using %s for PeerKey", - wpa_cipher_txt(cipher)); - peerkey->cipher = cipher; - - return 0; -} - - -static int wpa_supplicant_process_smk_m45( - struct wpa_sm *sm, const unsigned char *src_addr, - const struct wpa_eapol_key *key, size_t extra_len, int ver) -{ - struct wpa_peerkey *peerkey; - struct wpa_eapol_ie_parse kde; - u32 lifetime; - - if (!sm->peerkey_enabled || sm->proto != WPA_PROTO_RSN) { - wpa_printf(MSG_DEBUG, "RSN: SMK handshake not allowed for " - "the current network"); - return -1; - } - - if (wpa_supplicant_parse_ies((const u8 *) (key + 1), extra_len, &kde) < - 0) { - wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK M4/M5"); - return -1; - } - - if (kde.mac_addr == NULL || kde.mac_addr_len < ETH_ALEN || - kde.nonce == NULL || kde.nonce_len < WPA_NONCE_LEN || - kde.smk == NULL || kde.smk_len < PMK_LEN + WPA_NONCE_LEN || - kde.lifetime == NULL || kde.lifetime_len < 4) { - wpa_printf(MSG_INFO, "RSN: No MAC Address, Nonce, SMK, or " - "Lifetime KDE in SMK M4/M5"); - return -1; - } - - for (peerkey = sm->peerkey; peerkey; peerkey = peerkey->next) { - if (os_memcmp(peerkey->addr, kde.mac_addr, ETH_ALEN) == 0 && - os_memcmp(peerkey->initiator ? peerkey->inonce : - peerkey->pnonce, - key->key_nonce, WPA_NONCE_LEN) == 0) - break; - } - if (peerkey == NULL) { - wpa_printf(MSG_INFO, "RSN: No matching SMK handshake found " - "for SMK M4/M5: peer " MACSTR, - MAC2STR(kde.mac_addr)); - return -1; - } - - if (peerkey->initiator) { - if (wpa_supplicant_process_smk_m5(sm, src_addr, key, ver, - peerkey, &kde) < 0) - return -1; - } else { - if (wpa_supplicant_process_smk_m4(peerkey, &kde) < 0) - return -1; - } - - os_memcpy(peerkey->smk, kde.smk, PMK_LEN); - peerkey->smk_complete = 1; - wpa_hexdump_key(MSG_DEBUG, "RSN: SMK", peerkey->smk, PMK_LEN); - lifetime = WPA_GET_BE32(kde.lifetime); - wpa_printf(MSG_DEBUG, "RSN: SMK lifetime %u seconds", lifetime); - if (lifetime > 1000000000) - lifetime = 1000000000; /* avoid overflowing eloop time */ - peerkey->lifetime = lifetime; - eloop_register_timeout(lifetime, 0, wpa_supplicant_smk_timeout, - sm, peerkey); - - if (peerkey->initiator) { - rsn_smkid(peerkey->smk, peerkey->pnonce, peerkey->addr, - peerkey->inonce, sm->own_addr, peerkey->smkid, - peerkey->akmp); - wpa_supplicant_send_stk_1_of_4(sm, peerkey); - } else { - rsn_smkid(peerkey->smk, peerkey->pnonce, sm->own_addr, - peerkey->inonce, peerkey->addr, peerkey->smkid, - peerkey->akmp); - } - wpa_hexdump(MSG_DEBUG, "RSN: SMKID", peerkey->smkid, PMKID_LEN); - - return 0; -} - - -static int wpa_supplicant_process_smk_error( - struct wpa_sm *sm, const unsigned char *src_addr, - const struct wpa_eapol_key *key, size_t extra_len) -{ - struct wpa_eapol_ie_parse kde; - struct rsn_error_kde error; - u8 peer[ETH_ALEN]; - u16 error_type; - - wpa_printf(MSG_DEBUG, "RSN: Received SMK Error"); - - if (!sm->peerkey_enabled || sm->proto != WPA_PROTO_RSN) { - wpa_printf(MSG_DEBUG, "RSN: SMK handshake not allowed for " - "the current network"); - return -1; - } - - if (wpa_supplicant_parse_ies((const u8 *) (key + 1), extra_len, &kde) < - 0) { - wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK Error"); - return -1; - } - - if (kde.error == NULL || kde.error_len < sizeof(error)) { - wpa_printf(MSG_INFO, "RSN: No Error KDE in SMK Error"); - return -1; - } - - if (kde.mac_addr && kde.mac_addr_len >= ETH_ALEN) - os_memcpy(peer, kde.mac_addr, ETH_ALEN); - else - os_memset(peer, 0, ETH_ALEN); - os_memcpy(&error, kde.error, sizeof(error)); - error_type = be_to_host16(error.error_type); - wpa_msg(sm->ctx->msg_ctx, MSG_INFO, - "RSN: SMK Error KDE received: MUI %d error_type %d peer " - MACSTR, - be_to_host16(error.mui), error_type, - MAC2STR(peer)); - - if (kde.mac_addr && - (error_type == STK_ERR_STA_NR || error_type == STK_ERR_STA_NRSN || - error_type == STK_ERR_CPHR_NS)) { - struct wpa_peerkey *peerkey; - - for (peerkey = sm->peerkey; peerkey; peerkey = peerkey->next) { - if (os_memcmp(peerkey->addr, kde.mac_addr, ETH_ALEN) == - 0) - break; - } - if (peerkey == NULL) { - wpa_printf(MSG_DEBUG, "RSN: No matching SMK handshake " - "found for SMK Error"); - return -1; - } - /* TODO: abort SMK/STK handshake and remove all related keys */ - } - - return 0; -} - - -static void wpa_supplicant_process_stk_1_of_4(struct wpa_sm *sm, - struct wpa_peerkey *peerkey, - const struct wpa_eapol_key *key, - u16 ver, const u8 *key_data, - size_t key_data_len) -{ - struct wpa_eapol_ie_parse ie; - size_t kde_buf_len; - struct wpa_ptk *stk; - u8 buf[8], *kde_buf, *pos; - be32 lifetime; - - wpa_printf(MSG_DEBUG, "RSN: RX message 1 of STK 4-Way Handshake from " - MACSTR " (ver=%d)", MAC2STR(peerkey->addr), ver); - - os_memset(&ie, 0, sizeof(ie)); - - /* RSN: msg 1/4 should contain SMKID for the selected SMK */ - wpa_hexdump(MSG_DEBUG, "RSN: msg 1/4 key data", key_data, key_data_len); - if (wpa_supplicant_parse_ies(key_data, key_data_len, &ie) < 0 || - ie.pmkid == NULL) { - wpa_printf(MSG_DEBUG, "RSN: No SMKID in STK 1/4"); - return; - } - if (os_memcmp_const(ie.pmkid, peerkey->smkid, PMKID_LEN) != 0) { - wpa_hexdump(MSG_DEBUG, "RSN: Unknown SMKID in STK 1/4", - ie.pmkid, PMKID_LEN); - return; - } - - if (random_get_bytes(peerkey->pnonce, WPA_NONCE_LEN)) { - wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, - "RSN: Failed to get random data for PNonce"); - return; - } - wpa_hexdump(MSG_DEBUG, "WPA: Renewed PNonce", - peerkey->pnonce, WPA_NONCE_LEN); - - /* Calculate STK which will be stored as a temporary STK until it has - * been verified when processing message 3/4. */ - stk = &peerkey->tstk; - wpa_pmk_to_ptk(peerkey->smk, PMK_LEN, "Peer key expansion", - sm->own_addr, peerkey->addr, - peerkey->pnonce, key->key_nonce, - stk, peerkey->akmp, peerkey->cipher); - /* Supplicant: swap tx/rx Mic keys */ - os_memcpy(buf, &stk->tk[16], 8); - os_memcpy(&stk->tk[16], &stk->tk[24], 8); - os_memcpy(&stk->tk[24], buf, 8); - peerkey->tstk_set = 1; - - kde_buf_len = peerkey->rsnie_p_len + - 2 + RSN_SELECTOR_LEN + sizeof(lifetime) + - 2 + RSN_SELECTOR_LEN + PMKID_LEN; - kde_buf = os_malloc(kde_buf_len); - if (kde_buf == NULL) - return; - pos = kde_buf; - pos = wpa_add_ie(pos, peerkey->rsnie_p, peerkey->rsnie_p_len); - lifetime = host_to_be32(peerkey->lifetime); - pos = wpa_add_kde(pos, RSN_KEY_DATA_LIFETIME, - (u8 *) &lifetime, sizeof(lifetime)); - wpa_add_kde(pos, RSN_KEY_DATA_PMKID, peerkey->smkid, PMKID_LEN); - - if (wpa_supplicant_send_2_of_4(sm, peerkey->addr, key, ver, - peerkey->pnonce, kde_buf, kde_buf_len, - stk)) { - os_free(kde_buf); - return; - } - os_free(kde_buf); - - os_memcpy(peerkey->inonce, key->key_nonce, WPA_NONCE_LEN); -} - - -static void wpa_supplicant_update_smk_lifetime(struct wpa_sm *sm, - struct wpa_peerkey *peerkey, - struct wpa_eapol_ie_parse *kde) -{ - u32 lifetime; - - if (kde->lifetime == NULL || kde->lifetime_len < sizeof(lifetime)) - return; - - lifetime = WPA_GET_BE32(kde->lifetime); - - if (lifetime >= peerkey->lifetime) { - wpa_printf(MSG_DEBUG, "RSN: Peer used SMK lifetime %u seconds " - "which is larger than or equal to own value %u " - "seconds - ignored", lifetime, peerkey->lifetime); - return; - } - - wpa_printf(MSG_DEBUG, "RSN: Peer used shorter SMK lifetime %u seconds " - "(own was %u seconds) - updated", - lifetime, peerkey->lifetime); - peerkey->lifetime = lifetime; - - eloop_cancel_timeout(wpa_supplicant_smk_timeout, sm, peerkey); - eloop_register_timeout(lifetime, 0, wpa_supplicant_smk_timeout, - sm, peerkey); -} - - -static void wpa_supplicant_process_stk_2_of_4(struct wpa_sm *sm, - struct wpa_peerkey *peerkey, - const struct wpa_eapol_key *key, - u16 ver, const u8 *key_data, - size_t key_data_len) -{ - struct wpa_eapol_ie_parse kde; - - wpa_printf(MSG_DEBUG, "RSN: RX message 2 of STK 4-Way Handshake from " - MACSTR " (ver=%d)", MAC2STR(peerkey->addr), ver); - - os_memset(&kde, 0, sizeof(kde)); - - /* RSN: msg 2/4 should contain SMKID for the selected SMK and RSN IE - * from the peer. It may also include Lifetime KDE. */ - wpa_hexdump(MSG_DEBUG, "RSN: msg 2/4 key data", key_data, key_data_len); - if (wpa_supplicant_parse_ies(key_data, key_data_len, &kde) < 0 || - kde.pmkid == NULL || kde.rsn_ie == NULL) { - wpa_printf(MSG_DEBUG, "RSN: No SMKID or RSN IE in STK 2/4"); - return; - } - - if (os_memcmp_const(kde.pmkid, peerkey->smkid, PMKID_LEN) != 0) { - wpa_hexdump(MSG_DEBUG, "RSN: Unknown SMKID in STK 2/4", - kde.pmkid, PMKID_LEN); - return; - } - - if (kde.rsn_ie_len != peerkey->rsnie_p_len || - os_memcmp(kde.rsn_ie, peerkey->rsnie_p, kde.rsn_ie_len) != 0) { - wpa_printf(MSG_INFO, "RSN: Peer RSN IE in SMK and STK " - "handshakes did not match"); - wpa_hexdump(MSG_DEBUG, "RSN: Peer RSN IE in SMK handshake", - peerkey->rsnie_p, peerkey->rsnie_p_len); - wpa_hexdump(MSG_DEBUG, "RSN: Peer RSN IE in STK handshake", - kde.rsn_ie, kde.rsn_ie_len); - return; - } - - wpa_supplicant_update_smk_lifetime(sm, peerkey, &kde); - - wpa_supplicant_send_stk_3_of_4(sm, peerkey); - os_memcpy(peerkey->pnonce, key->key_nonce, WPA_NONCE_LEN); -} - - -static void wpa_supplicant_process_stk_3_of_4(struct wpa_sm *sm, - struct wpa_peerkey *peerkey, - const struct wpa_eapol_key *key, - u16 ver, const u8 *key_data, - size_t key_data_len) -{ - struct wpa_eapol_ie_parse kde; - size_t key_len; - const u8 *_key; - u8 key_buf[32], rsc[6]; - - wpa_printf(MSG_DEBUG, "RSN: RX message 3 of STK 4-Way Handshake from " - MACSTR " (ver=%d)", MAC2STR(peerkey->addr), ver); - - os_memset(&kde, 0, sizeof(kde)); - - /* RSN: msg 3/4 should contain Initiator RSN IE. It may also include - * Lifetime KDE. */ - wpa_hexdump(MSG_DEBUG, "RSN: msg 3/4 key data", key_data, key_data_len); - if (wpa_supplicant_parse_ies(key_data, key_data_len, &kde) < 0) { - wpa_printf(MSG_DEBUG, "RSN: Failed to parse key data in " - "STK 3/4"); - return; - } - - if (kde.rsn_ie_len != peerkey->rsnie_i_len || - os_memcmp(kde.rsn_ie, peerkey->rsnie_i, kde.rsn_ie_len) != 0) { - wpa_printf(MSG_INFO, "RSN: Initiator RSN IE in SMK and STK " - "handshakes did not match"); - wpa_hexdump(MSG_DEBUG, "RSN: Initiator RSN IE in SMK " - "handshake", - peerkey->rsnie_i, peerkey->rsnie_i_len); - wpa_hexdump(MSG_DEBUG, "RSN: Initiator RSN IE in STK " - "handshake", - kde.rsn_ie, kde.rsn_ie_len); - return; - } - - if (os_memcmp(peerkey->inonce, key->key_nonce, WPA_NONCE_LEN) != 0) { - wpa_printf(MSG_WARNING, "RSN: INonce from message 1 of STK " - "4-Way Handshake differs from 3 of STK 4-Way " - "Handshake - drop packet (src=" MACSTR ")", - MAC2STR(peerkey->addr)); - return; - } - - wpa_supplicant_update_smk_lifetime(sm, peerkey, &kde); - - if (wpa_supplicant_send_4_of_4(sm, peerkey->addr, key, ver, - WPA_GET_BE16(key->key_info), - &peerkey->stk)) - return; - - _key = peerkey->stk.tk; - if (peerkey->cipher == WPA_CIPHER_TKIP) { - /* Swap Tx/Rx keys for Michael MIC */ - os_memcpy(key_buf, _key, 16); - os_memcpy(key_buf + 16, _key + 24, 8); - os_memcpy(key_buf + 24, _key + 16, 8); - _key = key_buf; - key_len = 32; - } else - key_len = 16; - - os_memset(rsc, 0, 6); - if (wpa_sm_set_key(sm, peerkey->cipher, peerkey->addr, 0, 1, - rsc, sizeof(rsc), _key, key_len) < 0) { - os_memset(key_buf, 0, sizeof(key_buf)); - wpa_printf(MSG_WARNING, "RSN: Failed to set STK to the " - "driver."); - return; - } - os_memset(key_buf, 0, sizeof(key_buf)); -} - - -static void wpa_supplicant_process_stk_4_of_4(struct wpa_sm *sm, - struct wpa_peerkey *peerkey, - const struct wpa_eapol_key *key, - u16 ver) -{ - u8 rsc[6]; - - wpa_printf(MSG_DEBUG, "RSN: RX message 4 of STK 4-Way Handshake from " - MACSTR " (ver=%d)", MAC2STR(peerkey->addr), ver); - - os_memset(rsc, 0, 6); - if (wpa_sm_set_key(sm, peerkey->cipher, peerkey->addr, 0, 1, - rsc, sizeof(rsc), peerkey->stk.tk, - peerkey->cipher == WPA_CIPHER_TKIP ? 32 : 16) < 0) { - wpa_printf(MSG_WARNING, "RSN: Failed to set STK to the " - "driver."); - return; - } -} - - -/** - * peerkey_verify_eapol_key_mic - Verify PeerKey MIC - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @peerkey: Pointer to the PeerKey data for the peer - * @key: Pointer to the EAPOL-Key frame header - * @ver: Version bits from EAPOL-Key Key Info - * @buf: Pointer to the beginning of EAPOL-Key frame - * @len: Length of the EAPOL-Key frame - * Returns: 0 on success, -1 on failure - */ -int peerkey_verify_eapol_key_mic(struct wpa_sm *sm, - struct wpa_peerkey *peerkey, - struct wpa_eapol_key_192 *key, u16 ver, - const u8 *buf, size_t len) -{ - u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN]; - size_t mic_len = 16; - int ok = 0; - - if (peerkey->initiator && !peerkey->stk_set) { - wpa_pmk_to_ptk(peerkey->smk, PMK_LEN, "Peer key expansion", - sm->own_addr, peerkey->addr, - peerkey->inonce, key->key_nonce, - &peerkey->stk, peerkey->akmp, peerkey->cipher); - peerkey->stk_set = 1; - } - - os_memcpy(mic, key->key_mic, mic_len); - if (peerkey->tstk_set) { - os_memset(key->key_mic, 0, mic_len); - wpa_eapol_key_mic(peerkey->tstk.kck, peerkey->tstk.kck_len, - sm->key_mgmt, ver, buf, len, key->key_mic); - if (os_memcmp_const(mic, key->key_mic, mic_len) != 0) { - wpa_printf(MSG_WARNING, "RSN: Invalid EAPOL-Key MIC " - "when using TSTK - ignoring TSTK"); - } else { - ok = 1; - peerkey->tstk_set = 0; - peerkey->stk_set = 1; - os_memcpy(&peerkey->stk, &peerkey->tstk, - sizeof(peerkey->stk)); - os_memset(&peerkey->tstk, 0, sizeof(peerkey->tstk)); - } - } - - if (!ok && peerkey->stk_set) { - os_memset(key->key_mic, 0, mic_len); - wpa_eapol_key_mic(peerkey->stk.kck, peerkey->stk.kck_len, - sm->key_mgmt, ver, buf, len, key->key_mic); - if (os_memcmp_const(mic, key->key_mic, mic_len) != 0) { - wpa_printf(MSG_WARNING, "RSN: Invalid EAPOL-Key MIC " - "- dropping packet"); - return -1; - } - ok = 1; - } - - if (!ok) { - wpa_printf(MSG_WARNING, "RSN: Could not verify EAPOL-Key MIC " - "- dropping packet"); - return -1; - } - - os_memcpy(peerkey->replay_counter, key->replay_counter, - WPA_REPLAY_COUNTER_LEN); - peerkey->replay_counter_set = 1; - return 0; -} - - -/** - * wpa_sm_stkstart - Send EAPOL-Key Request for STK handshake (STK M1) - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @peer: MAC address of the peer STA - * Returns: 0 on success, or -1 on failure - * - * Send an EAPOL-Key Request to the current authenticator to start STK - * handshake with the peer. - */ -int wpa_sm_stkstart(struct wpa_sm *sm, const u8 *peer) -{ - size_t rlen, kde_len; - struct wpa_eapol_key *req; - int key_info, ver; - u8 bssid[ETH_ALEN], *rbuf, *pos, *count_pos; - u16 count; - struct rsn_ie_hdr *hdr; - struct wpa_peerkey *peerkey; - struct wpa_ie_data ie; - - if (sm->proto != WPA_PROTO_RSN || !sm->ptk_set || !sm->peerkey_enabled) - return -1; - - if (sm->ap_rsn_ie && - wpa_parse_wpa_ie_rsn(sm->ap_rsn_ie, sm->ap_rsn_ie_len, &ie) == 0 && - !(ie.capabilities & WPA_CAPABILITY_PEERKEY_ENABLED)) { - wpa_printf(MSG_DEBUG, "RSN: Current AP does not support STK"); - return -1; - } - - if (sm->pairwise_cipher != WPA_CIPHER_TKIP) - ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES; - else - ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4; - - if (wpa_sm_get_bssid(sm, bssid) < 0) { - wpa_printf(MSG_WARNING, "Failed to read BSSID for EAPOL-Key " - "SMK M1"); - return -1; - } - - /* TODO: find existing entry and if found, use that instead of adding - * a new one */ - peerkey = os_zalloc(sizeof(*peerkey)); - if (peerkey == NULL) - return -1; - peerkey->initiator = 1; - os_memcpy(peerkey->addr, peer, ETH_ALEN); - peerkey->akmp = sm->key_mgmt; - - /* SMK M1: - * EAPOL-Key(S=1, M=1, A=0, I=0, K=0, SM=1, KeyRSC=0, Nonce=INonce, - * MIC=MIC, DataKDs=(RSNIE_I, MAC_P KDE)) - */ - - hdr = (struct rsn_ie_hdr *) peerkey->rsnie_i; - hdr->elem_id = WLAN_EID_RSN; - WPA_PUT_LE16(hdr->version, RSN_VERSION); - pos = (u8 *) (hdr + 1); - /* Group Suite can be anything for SMK RSN IE; receiver will just - * ignore it. */ - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP); - pos += RSN_SELECTOR_LEN; - count_pos = pos; - pos += 2; - - count = rsn_cipher_put_suites(pos, sm->allowed_pairwise_cipher); - pos += count * RSN_SELECTOR_LEN; - WPA_PUT_LE16(count_pos, count); - - hdr->len = (pos - peerkey->rsnie_i) - 2; - peerkey->rsnie_i_len = pos - peerkey->rsnie_i; - wpa_hexdump(MSG_DEBUG, "WPA: RSN IE for SMK handshake", - peerkey->rsnie_i, peerkey->rsnie_i_len); - - kde_len = peerkey->rsnie_i_len + 2 + RSN_SELECTOR_LEN + ETH_ALEN; - - rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, - sizeof(*req) + kde_len, &rlen, - (void *) &req); - if (rbuf == NULL) { - wpa_supplicant_peerkey_free(sm, peerkey); - return -1; - } - - req->type = EAPOL_KEY_TYPE_RSN; - key_info = WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_MIC | - WPA_KEY_INFO_SECURE | WPA_KEY_INFO_REQUEST | ver; - WPA_PUT_BE16(req->key_info, key_info); - WPA_PUT_BE16(req->key_length, 0); - os_memcpy(req->replay_counter, sm->request_counter, - WPA_REPLAY_COUNTER_LEN); - inc_byte_array(sm->request_counter, WPA_REPLAY_COUNTER_LEN); - - if (random_get_bytes(peerkey->inonce, WPA_NONCE_LEN)) { - wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, - "WPA: Failed to get random data for INonce"); - os_free(rbuf); - wpa_supplicant_peerkey_free(sm, peerkey); - return -1; - } - os_memcpy(req->key_nonce, peerkey->inonce, WPA_NONCE_LEN); - wpa_hexdump(MSG_DEBUG, "WPA: INonce for SMK handshake", - req->key_nonce, WPA_NONCE_LEN); - - WPA_PUT_BE16(req->key_data_length, (u16) kde_len); - pos = (u8 *) (req + 1); - - /* Initiator RSN IE */ - pos = wpa_add_ie(pos, peerkey->rsnie_i, peerkey->rsnie_i_len); - /* Peer MAC address KDE */ - wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peer, ETH_ALEN); - - wpa_printf(MSG_INFO, "RSN: Sending EAPOL-Key SMK M1 Request (peer " - MACSTR ")", MAC2STR(peer)); - wpa_eapol_key_send(sm, sm->ptk.kck, sm->ptk.kck_len, ver, bssid, - ETH_P_EAPOL, rbuf, rlen, req->key_mic); - - peerkey->next = sm->peerkey; - sm->peerkey = peerkey; - - return 0; -} - - -/** - * peerkey_deinit - Free PeerKey values - * @sm: Pointer to WPA state machine data from wpa_sm_init() - */ -void peerkey_deinit(struct wpa_sm *sm) -{ - struct wpa_peerkey *prev, *peerkey = sm->peerkey; - while (peerkey) { - prev = peerkey; - peerkey = peerkey->next; - wpa_supplicant_peerkey_free(sm, prev); - } - sm->peerkey = NULL; -} - - -void peerkey_rx_eapol_4way(struct wpa_sm *sm, struct wpa_peerkey *peerkey, - struct wpa_eapol_key *key, u16 key_info, u16 ver, - const u8 *key_data, size_t key_data_len) -{ - if ((key_info & (WPA_KEY_INFO_MIC | WPA_KEY_INFO_ACK)) == - (WPA_KEY_INFO_MIC | WPA_KEY_INFO_ACK)) { - /* 3/4 STK 4-Way Handshake */ - wpa_supplicant_process_stk_3_of_4(sm, peerkey, key, ver, - key_data, key_data_len); - } else if (key_info & WPA_KEY_INFO_ACK) { - /* 1/4 STK 4-Way Handshake */ - wpa_supplicant_process_stk_1_of_4(sm, peerkey, key, ver, - key_data, key_data_len); - } else if (key_info & WPA_KEY_INFO_SECURE) { - /* 4/4 STK 4-Way Handshake */ - wpa_supplicant_process_stk_4_of_4(sm, peerkey, key, ver); - } else { - /* 2/4 STK 4-Way Handshake */ - wpa_supplicant_process_stk_2_of_4(sm, peerkey, key, ver, - key_data, key_data_len); - } -} - - -void peerkey_rx_eapol_smk(struct wpa_sm *sm, const u8 *src_addr, - struct wpa_eapol_key *key, size_t extra_len, - u16 key_info, u16 ver) -{ - if (key_info & WPA_KEY_INFO_ERROR) { - /* SMK Error */ - wpa_supplicant_process_smk_error(sm, src_addr, key, extra_len); - } else if (key_info & WPA_KEY_INFO_ACK) { - /* SMK M2 */ - wpa_supplicant_process_smk_m2(sm, src_addr, key, extra_len, - ver); - } else { - /* SMK M4 or M5 */ - wpa_supplicant_process_smk_m45(sm, src_addr, key, extra_len, - ver); - } -} - -#endif /* CONFIG_PEERKEY */ diff --git a/freebsd/contrib/wpa/src/rsn_supp/peerkey.h b/freebsd/contrib/wpa/src/rsn_supp/peerkey.h deleted file mode 100644 index 6ccd948b..00000000 --- a/freebsd/contrib/wpa/src/rsn_supp/peerkey.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * WPA Supplicant - PeerKey for Direct Link Setup (DLS) - * Copyright (c) 2006-2015, Jouni Malinen <j@w1.fi> - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#ifndef PEERKEY_H -#define PEERKEY_H - -#define PEERKEY_MAX_IE_LEN 80 -struct wpa_peerkey { - struct wpa_peerkey *next; - int initiator; /* whether this end was initator for SMK handshake */ - u8 addr[ETH_ALEN]; /* other end MAC address */ - u8 inonce[WPA_NONCE_LEN]; /* Initiator Nonce */ - u8 pnonce[WPA_NONCE_LEN]; /* Peer Nonce */ - u8 rsnie_i[PEERKEY_MAX_IE_LEN]; /* Initiator RSN IE */ - size_t rsnie_i_len; - u8 rsnie_p[PEERKEY_MAX_IE_LEN]; /* Peer RSN IE */ - size_t rsnie_p_len; - u8 smk[PMK_LEN]; - int smk_complete; - u8 smkid[PMKID_LEN]; - u32 lifetime; - int cipher; /* Selected cipher (WPA_CIPHER_*) */ - u8 replay_counter[WPA_REPLAY_COUNTER_LEN]; - int replay_counter_set; - int akmp; - - struct wpa_ptk stk, tstk; - int stk_set, tstk_set; -}; - - -#ifdef CONFIG_PEERKEY - -int peerkey_verify_eapol_key_mic(struct wpa_sm *sm, - struct wpa_peerkey *peerkey, - struct wpa_eapol_key_192 *key, u16 ver, - const u8 *buf, size_t len); -void peerkey_rx_eapol_4way(struct wpa_sm *sm, struct wpa_peerkey *peerkey, - struct wpa_eapol_key *key, u16 key_info, u16 ver, - const u8 *key_data, size_t key_data_len); -void peerkey_rx_eapol_smk(struct wpa_sm *sm, const u8 *src_addr, - struct wpa_eapol_key *key, size_t extra_len, - u16 key_info, u16 ver); -void peerkey_deinit(struct wpa_sm *sm); - -#else /* CONFIG_PEERKEY */ - -static inline int -peerkey_verify_eapol_key_mic(struct wpa_sm *sm, - struct wpa_peerkey *peerkey, - struct wpa_eapol_key *key, u16 ver, - const u8 *buf, size_t len) -{ - return -1; -} - -static inline void -peerkey_rx_eapol_4way(struct wpa_sm *sm, struct wpa_peerkey *peerkey, - struct wpa_eapol_key *key, u16 key_info, u16 ver, - const u8 *key_data, size_t key_data_len) -{ -} - -static inline void -peerkey_rx_eapol_smk(struct wpa_sm *sm, const u8 *src_addr, - struct wpa_eapol_key *key, size_t extra_len, - u16 key_info, u16 ver) -{ -} - -static inline void peerkey_deinit(struct wpa_sm *sm) -{ -} - -#endif /* CONFIG_PEERKEY */ - -#endif /* PEERKEY_H */ diff --git a/freebsd/contrib/wpa/src/rsn_supp/pmksa_cache.c b/freebsd/contrib/wpa/src/rsn_supp/pmksa_cache.c index 7f7cbbec..dbf9aba6 100644 --- a/freebsd/contrib/wpa/src/rsn_supp/pmksa_cache.c +++ b/freebsd/contrib/wpa/src/rsn_supp/pmksa_cache.c @@ -45,7 +45,10 @@ static void pmksa_cache_free_entry(struct rsn_pmksa_cache *pmksa, struct rsn_pmksa_cache_entry *entry, enum pmksa_free_reason reason) { - wpa_sm_remove_pmkid(pmksa->sm, entry->aa, entry->pmkid); + wpa_sm_remove_pmkid(pmksa->sm, entry->network_ctx, entry->aa, + entry->pmkid, + entry->fils_cache_id_set ? entry->fils_cache_id : + NULL); pmksa->pmksa_count--; pmksa->free_cb(entry, pmksa->ctx, reason); _pmksa_cache_free_entry(entry); @@ -95,7 +98,7 @@ static void pmksa_cache_set_expiration(struct rsn_pmksa_cache *pmksa) eloop_register_timeout(sec + 1, 0, pmksa_cache_expire, pmksa, NULL); entry = pmksa->sm->cur_pmksa ? pmksa->sm->cur_pmksa : - pmksa_cache_get(pmksa, pmksa->sm->bssid, NULL, NULL); + pmksa_cache_get(pmksa, pmksa->sm->bssid, NULL, NULL, 0); if (entry) { sec = pmksa->pmksa->reauth_time - now.sec; if (sec < 0) @@ -118,6 +121,7 @@ static void pmksa_cache_set_expiration(struct rsn_pmksa_cache *pmksa) * @spa: Supplicant address * @network_ctx: Network configuration context for this PMK * @akmp: WPA_KEY_MGMT_* used in key derivation + * @cache_id: Pointer to FILS Cache Identifier or %NULL if not advertised * Returns: Pointer to the added PMKSA cache entry or %NULL on error * * This function create a PMKSA entry for a new PMK and adds it to the PMKSA @@ -128,9 +132,10 @@ static void pmksa_cache_set_expiration(struct rsn_pmksa_cache *pmksa) struct rsn_pmksa_cache_entry * pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len, const u8 *pmkid, const u8 *kck, size_t kck_len, - const u8 *aa, const u8 *spa, void *network_ctx, int akmp) + const u8 *aa, const u8 *spa, void *network_ctx, int akmp, + const u8 *cache_id) { - struct rsn_pmksa_cache_entry *entry, *pos, *prev; + struct rsn_pmksa_cache_entry *entry; struct os_reltime now; if (pmk_len > PMK_LEN_MAX) @@ -151,24 +156,38 @@ pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len, else if (wpa_key_mgmt_suite_b(akmp)) rsn_pmkid_suite_b(kck, kck_len, aa, spa, entry->pmkid); else - rsn_pmkid(pmk, pmk_len, aa, spa, entry->pmkid, - wpa_key_mgmt_sha256(akmp)); + rsn_pmkid(pmk, pmk_len, aa, spa, entry->pmkid, akmp); os_get_reltime(&now); entry->expiration = now.sec + pmksa->sm->dot11RSNAConfigPMKLifetime; entry->reauth_time = now.sec + pmksa->sm->dot11RSNAConfigPMKLifetime * pmksa->sm->dot11RSNAConfigPMKReauthThreshold / 100; entry->akmp = akmp; + if (cache_id) { + entry->fils_cache_id_set = 1; + os_memcpy(entry->fils_cache_id, cache_id, FILS_CACHE_ID_LEN); + } os_memcpy(entry->aa, aa, ETH_ALEN); entry->network_ctx = network_ctx; + return pmksa_cache_add_entry(pmksa, entry); +} + + +struct rsn_pmksa_cache_entry * +pmksa_cache_add_entry(struct rsn_pmksa_cache *pmksa, + struct rsn_pmksa_cache_entry *entry) +{ + struct rsn_pmksa_cache_entry *pos, *prev; + /* Replace an old entry for the same Authenticator (if found) with the * new entry */ pos = pmksa->pmksa; prev = NULL; while (pos) { - if (os_memcmp(aa, pos->aa, ETH_ALEN) == 0) { - if (pos->pmk_len == pmk_len && - os_memcmp_const(pos->pmk, pmk, pmk_len) == 0 && + if (os_memcmp(entry->aa, pos->aa, ETH_ALEN) == 0) { + if (pos->pmk_len == entry->pmk_len && + os_memcmp_const(pos->pmk, entry->pmk, + entry->pmk_len) == 0 && os_memcmp_const(pos->pmkid, entry->pmkid, PMKID_LEN) == 0) { wpa_printf(MSG_DEBUG, "WPA: reusing previous " @@ -194,8 +213,8 @@ pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len, "the current AP and any PMKSA cache entry " "that was based on the old PMK"); if (!pos->opportunistic) - pmksa_cache_flush(pmksa, network_ctx, pos->pmk, - pos->pmk_len); + pmksa_cache_flush(pmksa, entry->network_ctx, + pos->pmk, pos->pmk_len); pmksa_cache_free_entry(pmksa, pos, PMKSA_REPLACE); break; } @@ -246,8 +265,11 @@ pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len, } pmksa->pmksa_count++; wpa_printf(MSG_DEBUG, "RSN: Added PMKSA cache entry for " MACSTR - " network_ctx=%p", MAC2STR(entry->aa), network_ctx); - wpa_sm_add_pmkid(pmksa->sm, entry->aa, entry->pmkid); + " network_ctx=%p akmp=0x%x", MAC2STR(entry->aa), + entry->network_ctx, entry->akmp); + wpa_sm_add_pmkid(pmksa->sm, entry->network_ctx, entry->aa, entry->pmkid, + entry->fils_cache_id_set ? entry->fils_cache_id : NULL, + entry->pmk, entry->pmk_len); return entry; } @@ -322,17 +344,20 @@ void pmksa_cache_deinit(struct rsn_pmksa_cache *pmksa) * @aa: Authenticator address or %NULL to match any * @pmkid: PMKID or %NULL to match any * @network_ctx: Network context or %NULL to match any + * @akmp: Specific AKMP to search for or 0 for any * Returns: Pointer to PMKSA cache entry or %NULL if no match was found */ struct rsn_pmksa_cache_entry * pmksa_cache_get(struct rsn_pmksa_cache *pmksa, const u8 *aa, const u8 *pmkid, - const void *network_ctx) + const void *network_ctx, + int akmp) { struct rsn_pmksa_cache_entry *entry = pmksa->pmksa; while (entry) { if ((aa == NULL || os_memcmp(entry->aa, aa, ETH_ALEN) == 0) && (pmkid == NULL || os_memcmp(entry->pmkid, pmkid, PMKID_LEN) == 0) && + (!akmp || akmp == entry->akmp) && (network_ctx == NULL || network_ctx == entry->network_ctx)) return entry; entry = entry->next; @@ -347,16 +372,19 @@ pmksa_cache_clone_entry(struct rsn_pmksa_cache *pmksa, const u8 *aa) { struct rsn_pmksa_cache_entry *new_entry; + os_time_t old_expiration = old_entry->expiration; new_entry = pmksa_cache_add(pmksa, old_entry->pmk, old_entry->pmk_len, NULL, NULL, 0, aa, pmksa->sm->own_addr, - old_entry->network_ctx, old_entry->akmp); + old_entry->network_ctx, old_entry->akmp, + old_entry->fils_cache_id_set ? + old_entry->fils_cache_id : NULL); if (new_entry == NULL) return NULL; /* TODO: reorder entries based on expiration time? */ - new_entry->expiration = old_entry->expiration; + new_entry->expiration = old_expiration; new_entry->opportunistic = 1; return new_entry; @@ -368,6 +396,7 @@ pmksa_cache_clone_entry(struct rsn_pmksa_cache *pmksa, * @pmksa: Pointer to PMKSA cache data from pmksa_cache_init() * @network_ctx: Network configuration context * @aa: Authenticator address for the new AP + * @akmp: Specific AKMP to search for or 0 for any * Returns: Pointer to a new PMKSA cache entry or %NULL if not available * * Try to create a new PMKSA cache entry opportunistically by guessing that the @@ -376,7 +405,7 @@ pmksa_cache_clone_entry(struct rsn_pmksa_cache *pmksa, */ struct rsn_pmksa_cache_entry * pmksa_cache_get_opportunistic(struct rsn_pmksa_cache *pmksa, void *network_ctx, - const u8 *aa) + const u8 *aa, int akmp) { struct rsn_pmksa_cache_entry *entry = pmksa->pmksa; @@ -384,7 +413,8 @@ pmksa_cache_get_opportunistic(struct rsn_pmksa_cache *pmksa, void *network_ctx, if (network_ctx == NULL) return NULL; while (entry) { - if (entry->network_ctx == network_ctx) { + if (entry->network_ctx == network_ctx && + (!akmp || entry->akmp == akmp)) { entry = pmksa_cache_clone_entry(pmksa, entry, aa); if (entry) { wpa_printf(MSG_DEBUG, "RSN: added " @@ -399,6 +429,24 @@ pmksa_cache_get_opportunistic(struct rsn_pmksa_cache *pmksa, void *network_ctx, } +static struct rsn_pmksa_cache_entry * +pmksa_cache_get_fils_cache_id(struct rsn_pmksa_cache *pmksa, + const void *network_ctx, const u8 *cache_id) +{ + struct rsn_pmksa_cache_entry *entry; + + for (entry = pmksa->pmksa; entry; entry = entry->next) { + if (network_ctx == entry->network_ctx && + entry->fils_cache_id_set && + os_memcmp(cache_id, entry->fils_cache_id, + FILS_CACHE_ID_LEN) == 0) + return entry; + } + + return NULL; +} + + /** * pmksa_cache_get_current - Get the current used PMKSA entry * @sm: Pointer to WPA state machine data from wpa_sm_init() @@ -431,33 +479,44 @@ void pmksa_cache_clear_current(struct wpa_sm *sm) * @bssid: BSSID for PMKSA or %NULL if not used * @network_ctx: Network configuration context * @try_opportunistic: Whether to allow opportunistic PMKSA caching + * @fils_cache_id: Pointer to FILS Cache Identifier or %NULL if not used * Returns: 0 if PMKSA was found or -1 if no matching entry was found */ int pmksa_cache_set_current(struct wpa_sm *sm, const u8 *pmkid, const u8 *bssid, void *network_ctx, - int try_opportunistic) + int try_opportunistic, const u8 *fils_cache_id, + int akmp) { struct rsn_pmksa_cache *pmksa = sm->pmksa; wpa_printf(MSG_DEBUG, "RSN: PMKSA cache search - network_ctx=%p " - "try_opportunistic=%d", network_ctx, try_opportunistic); + "try_opportunistic=%d akmp=0x%x", + network_ctx, try_opportunistic, akmp); if (pmkid) wpa_hexdump(MSG_DEBUG, "RSN: Search for PMKID", pmkid, PMKID_LEN); if (bssid) wpa_printf(MSG_DEBUG, "RSN: Search for BSSID " MACSTR, MAC2STR(bssid)); + if (fils_cache_id) + wpa_printf(MSG_DEBUG, + "RSN: Search for FILS Cache Identifier %02x%02x", + fils_cache_id[0], fils_cache_id[1]); sm->cur_pmksa = NULL; if (pmkid) sm->cur_pmksa = pmksa_cache_get(pmksa, NULL, pmkid, - network_ctx); + network_ctx, akmp); if (sm->cur_pmksa == NULL && bssid) sm->cur_pmksa = pmksa_cache_get(pmksa, bssid, NULL, - network_ctx); + network_ctx, akmp); if (sm->cur_pmksa == NULL && try_opportunistic && bssid) sm->cur_pmksa = pmksa_cache_get_opportunistic(pmksa, network_ctx, - bssid); + bssid, akmp); + if (sm->cur_pmksa == NULL && fils_cache_id) + sm->cur_pmksa = pmksa_cache_get_fils_cache_id(pmksa, + network_ctx, + fils_cache_id); if (sm->cur_pmksa) { wpa_hexdump(MSG_DEBUG, "RSN: PMKSA cache entry found - PMKID", sm->cur_pmksa->pmkid, PMKID_LEN); @@ -484,11 +543,20 @@ int pmksa_cache_list(struct rsn_pmksa_cache *pmksa, char *buf, size_t len) char *pos = buf; struct rsn_pmksa_cache_entry *entry; struct os_reltime now; + int cache_id_used = 0; + + for (entry = pmksa->pmksa; entry; entry = entry->next) { + if (entry->fils_cache_id_set) { + cache_id_used = 1; + break; + } + } os_get_reltime(&now); ret = os_snprintf(pos, buf + len - pos, "Index / AA / PMKID / expiration (in seconds) / " - "opportunistic\n"); + "opportunistic%s\n", + cache_id_used ? " / FILS Cache Identifier" : ""); if (os_snprintf_error(buf + len - pos, ret)) return pos - buf; pos += ret; @@ -503,18 +571,36 @@ int pmksa_cache_list(struct rsn_pmksa_cache *pmksa, char *buf, size_t len) pos += ret; pos += wpa_snprintf_hex(pos, buf + len - pos, entry->pmkid, PMKID_LEN); - ret = os_snprintf(pos, buf + len - pos, " %d %d\n", + ret = os_snprintf(pos, buf + len - pos, " %d %d", (int) (entry->expiration - now.sec), entry->opportunistic); if (os_snprintf_error(buf + len - pos, ret)) return pos - buf; pos += ret; + if (entry->fils_cache_id_set) { + ret = os_snprintf(pos, buf + len - pos, " %02x%02x", + entry->fils_cache_id[0], + entry->fils_cache_id[1]); + if (os_snprintf_error(buf + len - pos, ret)) + return pos - buf; + pos += ret; + } + ret = os_snprintf(pos, buf + len - pos, "\n"); + if (os_snprintf_error(buf + len - pos, ret)) + return pos - buf; + pos += ret; entry = entry->next; } return pos - buf; } +struct rsn_pmksa_cache_entry * pmksa_cache_head(struct rsn_pmksa_cache *pmksa) +{ + return pmksa->pmksa; +} + + /** * pmksa_cache_init - Initialize PMKSA cache * @free_cb: Callback function to be called when a PMKSA cache entry is freed diff --git a/freebsd/contrib/wpa/src/rsn_supp/pmksa_cache.h b/freebsd/contrib/wpa/src/rsn_supp/pmksa_cache.h index daede6da..6c49fa92 100644 --- a/freebsd/contrib/wpa/src/rsn_supp/pmksa_cache.h +++ b/freebsd/contrib/wpa/src/rsn_supp/pmksa_cache.h @@ -21,6 +21,14 @@ struct rsn_pmksa_cache_entry { int akmp; /* WPA_KEY_MGMT_* */ u8 aa[ETH_ALEN]; + /* + * If FILS Cache Identifier is included (fils_cache_id_set), this PMKSA + * cache entry is applicable to all BSSs (any BSSID/aa[]) that + * advertise the same FILS Cache Identifier within the same ESS. + */ + u8 fils_cache_id[2]; + unsigned int fils_cache_id_set:1; + os_time_t reauth_time; /** @@ -53,20 +61,27 @@ pmksa_cache_init(void (*free_cb)(struct rsn_pmksa_cache_entry *entry, void pmksa_cache_deinit(struct rsn_pmksa_cache *pmksa); struct rsn_pmksa_cache_entry * pmksa_cache_get(struct rsn_pmksa_cache *pmksa, const u8 *aa, const u8 *pmkid, - const void *network_ctx); + const void *network_ctx, + int akmp); int pmksa_cache_list(struct rsn_pmksa_cache *pmksa, char *buf, size_t len); +struct rsn_pmksa_cache_entry * pmksa_cache_head(struct rsn_pmksa_cache *pmksa); struct rsn_pmksa_cache_entry * pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len, const u8 *pmkid, const u8 *kck, size_t kck_len, - const u8 *aa, const u8 *spa, void *network_ctx, int akmp); + const u8 *aa, const u8 *spa, void *network_ctx, int akmp, + const u8 *cache_id); +struct rsn_pmksa_cache_entry * +pmksa_cache_add_entry(struct rsn_pmksa_cache *pmksa, + struct rsn_pmksa_cache_entry *entry); struct rsn_pmksa_cache_entry * pmksa_cache_get_current(struct wpa_sm *sm); void pmksa_cache_clear_current(struct wpa_sm *sm); int pmksa_cache_set_current(struct wpa_sm *sm, const u8 *pmkid, const u8 *bssid, void *network_ctx, - int try_opportunistic); + int try_opportunistic, const u8 *fils_cache_id, + int akmp); struct rsn_pmksa_cache_entry * pmksa_cache_get_opportunistic(struct rsn_pmksa_cache *pmksa, - void *network_ctx, const u8 *aa); + void *network_ctx, const u8 *aa, int akmp); void pmksa_cache_flush(struct rsn_pmksa_cache *pmksa, void *network_ctx, const u8 *pmk, size_t pmk_len); @@ -86,7 +101,7 @@ static inline void pmksa_cache_deinit(struct rsn_pmksa_cache *pmksa) static inline struct rsn_pmksa_cache_entry * pmksa_cache_get(struct rsn_pmksa_cache *pmksa, const u8 *aa, const u8 *pmkid, - const void *network_ctx) + const void *network_ctx, int akmp) { return NULL; } @@ -104,9 +119,23 @@ static inline int pmksa_cache_list(struct rsn_pmksa_cache *pmksa, char *buf, } static inline struct rsn_pmksa_cache_entry * +pmksa_cache_head(struct rsn_pmksa_cache *pmksa) +{ + return NULL; +} + +static inline struct rsn_pmksa_cache_entry * +pmksa_cache_add_entry(struct rsn_pmksa_cache *pmksa, + struct rsn_pmksa_cache_entry *entry) +{ + return NULL; +} + +static inline struct rsn_pmksa_cache_entry * pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len, const u8 *pmkid, const u8 *kck, size_t kck_len, - const u8 *aa, const u8 *spa, void *network_ctx, int akmp) + const u8 *aa, const u8 *spa, void *network_ctx, int akmp, + const u8 *cache_id) { return NULL; } @@ -118,7 +147,9 @@ static inline void pmksa_cache_clear_current(struct wpa_sm *sm) static inline int pmksa_cache_set_current(struct wpa_sm *sm, const u8 *pmkid, const u8 *bssid, void *network_ctx, - int try_opportunistic) + int try_opportunistic, + const u8 *fils_cache_id, + int akmp) { return -1; } diff --git a/freebsd/contrib/wpa/src/rsn_supp/preauth.c b/freebsd/contrib/wpa/src/rsn_supp/preauth.c index 470f5971..ff8dee40 100644 --- a/freebsd/contrib/wpa/src/rsn_supp/preauth.c +++ b/freebsd/contrib/wpa/src/rsn_supp/preauth.c @@ -99,7 +99,7 @@ static void rsn_preauth_eapol_cb(struct eapol_sm *eapol, NULL, 0, sm->preauth_bssid, sm->own_addr, sm->network_ctx, - WPA_KEY_MGMT_IEEE8021X); + WPA_KEY_MGMT_IEEE8021X, NULL); } else { wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "RSN: failed to get master session key from " @@ -325,7 +325,7 @@ void rsn_preauth_candidate_process(struct wpa_sm *sm) dl_list_for_each_safe(candidate, n, &sm->pmksa_candidates, struct rsn_pmksa_candidate, list) { struct rsn_pmksa_cache_entry *p = NULL; - p = pmksa_cache_get(sm->pmksa, candidate->bssid, NULL, NULL); + p = pmksa_cache_get(sm->pmksa, candidate->bssid, NULL, NULL, 0); if (os_memcmp(sm->bssid, candidate->bssid, ETH_ALEN) != 0 && (p == NULL || p->opportunistic)) { wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: PMKSA " @@ -344,7 +344,8 @@ void rsn_preauth_candidate_process(struct wpa_sm *sm) /* Some drivers (e.g., NDIS) expect to get notified about the * PMKIDs again, so report the existing data now. */ if (p) { - wpa_sm_add_pmkid(sm, candidate->bssid, p->pmkid); + wpa_sm_add_pmkid(sm, NULL, candidate->bssid, p->pmkid, + NULL, p->pmk, p->pmk_len); } dl_list_del(&candidate->list); @@ -373,7 +374,7 @@ void pmksa_candidate_add(struct wpa_sm *sm, const u8 *bssid, if (sm->network_ctx && sm->proactive_key_caching) pmksa_cache_get_opportunistic(sm->pmksa, sm->network_ctx, - bssid); + bssid, 0); if (!preauth) { wpa_printf(MSG_DEBUG, "RSN: Ignored PMKID candidate without " @@ -484,7 +485,7 @@ void rsn_preauth_scan_result(struct wpa_sm *sm, const u8 *bssid, if (wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie)) return; - pmksa = pmksa_cache_get(sm->pmksa, bssid, NULL, NULL); + pmksa = pmksa_cache_get(sm->pmksa, bssid, NULL, NULL, 0); if (pmksa && (!pmksa->opportunistic || !(ie.capabilities & WPA_CAPABILITY_PREAUTH))) return; diff --git a/freebsd/contrib/wpa/src/rsn_supp/wpa.c b/freebsd/contrib/wpa/src/rsn_supp/wpa.c index 4ad6bb6a..c2ebec54 100644 --- a/freebsd/contrib/wpa/src/rsn_supp/wpa.c +++ b/freebsd/contrib/wpa/src/rsn_supp/wpa.c @@ -2,7 +2,7 @@ /* * WPA Supplicant - WPA state machine and EAPOL-Key processing - * Copyright (c) 2003-2015, Jouni Malinen <j@w1.fi> + * Copyright (c) 2003-2018, Jouni Malinen <j@w1.fi> * Copyright(c) 2015 Intel Deutschland GmbH * * This software may be distributed under the terms of the BSD license. @@ -12,18 +12,26 @@ #include "includes.h" #include "common.h" +#include "crypto/aes.h" #include "crypto/aes_wrap.h" #include "crypto/crypto.h" #include "crypto/random.h" +#include "crypto/aes_siv.h" +#include "crypto/sha256.h" +#include "crypto/sha384.h" +#include "crypto/sha512.h" #include "common/ieee802_11_defs.h" +#include "common/ieee802_11_common.h" +#include "common/ocv.h" +#include "eap_common/eap_defs.h" #include "eapol_supp/eapol_supp_sm.h" +#include "drivers/driver.h" #include "wpa.h" #include "eloop.h" #include "preauth.h" #include "pmksa_cache.h" #include "wpa_i.h" #include "wpa_ie.h" -#include "peerkey.h" static const u8 null_rsc[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; @@ -32,8 +40,7 @@ static const u8 null_rsc[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; /** * wpa_eapol_key_send - Send WPA/RSN EAPOL-Key message * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @kck: Key Confirmation Key (KCK, part of PTK) - * @kck_len: KCK length in octets + * @ptk: PTK for Key Confirmation/Encryption Key * @ver: Version field from Key Info * @dest: Destination address for the frame * @proto: Ethertype (usually ETH_P_EAPOL) @@ -42,13 +49,16 @@ static const u8 null_rsc[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; * @key_mic: Pointer to the buffer to which the EAPOL-Key MIC is written * Returns: >= 0 on success, < 0 on failure */ -int wpa_eapol_key_send(struct wpa_sm *sm, const u8 *kck, size_t kck_len, +int wpa_eapol_key_send(struct wpa_sm *sm, struct wpa_ptk *ptk, int ver, const u8 *dest, u16 proto, u8 *msg, size_t msg_len, u8 *key_mic) { int ret = -1; - size_t mic_len = wpa_mic_len(sm->key_mgmt); + size_t mic_len = wpa_mic_len(sm->key_mgmt, sm->pmk_len); + wpa_printf(MSG_DEBUG, "WPA: Send EAPOL-Key frame to " MACSTR + " ver=%d mic_len=%d key_mgmt=0x%x", + MAC2STR(dest), ver, (int) mic_len, sm->key_mgmt); if (is_zero_ether_addr(dest) && is_zero_ether_addr(sm->bssid)) { /* * Association event was not yet received; try to fetch @@ -66,16 +76,89 @@ int wpa_eapol_key_send(struct wpa_sm *sm, const u8 *kck, size_t kck_len, MAC2STR(dest)); } } - if (key_mic && - wpa_eapol_key_mic(kck, kck_len, sm->key_mgmt, ver, msg, msg_len, - key_mic)) { - wpa_msg(sm->ctx->msg_ctx, MSG_ERROR, - "WPA: Failed to generate EAPOL-Key version %d key_mgmt 0x%x MIC", - ver, sm->key_mgmt); + + if (mic_len) { + if (key_mic && (!ptk || !ptk->kck_len)) + goto out; + + if (key_mic && + wpa_eapol_key_mic(ptk->kck, ptk->kck_len, sm->key_mgmt, ver, + msg, msg_len, key_mic)) { + wpa_msg(sm->ctx->msg_ctx, MSG_ERROR, + "WPA: Failed to generate EAPOL-Key version %d key_mgmt 0x%x MIC", + ver, sm->key_mgmt); + goto out; + } + if (ptk) + wpa_hexdump_key(MSG_DEBUG, "WPA: KCK", + ptk->kck, ptk->kck_len); + wpa_hexdump(MSG_DEBUG, "WPA: Derived Key MIC", + key_mic, mic_len); + } else { +#ifdef CONFIG_FILS + /* AEAD cipher - Key MIC field not used */ + struct ieee802_1x_hdr *s_hdr, *hdr; + struct wpa_eapol_key *s_key, *key; + u8 *buf, *s_key_data, *key_data; + size_t buf_len = msg_len + AES_BLOCK_SIZE; + size_t key_data_len; + u16 eapol_len; + const u8 *aad[1]; + size_t aad_len[1]; + + if (!ptk || !ptk->kek_len) + goto out; + + key_data_len = msg_len - sizeof(struct ieee802_1x_hdr) - + sizeof(struct wpa_eapol_key) - 2; + + buf = os_malloc(buf_len); + if (!buf) + goto out; + + os_memcpy(buf, msg, msg_len); + hdr = (struct ieee802_1x_hdr *) buf; + key = (struct wpa_eapol_key *) (hdr + 1); + key_data = ((u8 *) (key + 1)) + 2; + + /* Update EAPOL header to include AES-SIV overhead */ + eapol_len = be_to_host16(hdr->length); + eapol_len += AES_BLOCK_SIZE; + hdr->length = host_to_be16(eapol_len); + + /* Update Key Data Length field to include AES-SIV overhead */ + WPA_PUT_BE16((u8 *) (key + 1), AES_BLOCK_SIZE + key_data_len); + + s_hdr = (struct ieee802_1x_hdr *) msg; + s_key = (struct wpa_eapol_key *) (s_hdr + 1); + s_key_data = ((u8 *) (s_key + 1)) + 2; + + wpa_hexdump_key(MSG_DEBUG, "WPA: Plaintext Key Data", + s_key_data, key_data_len); + + wpa_hexdump_key(MSG_DEBUG, "WPA: KEK", ptk->kek, ptk->kek_len); + /* AES-SIV AAD from EAPOL protocol version field (inclusive) to + * to Key Data (exclusive). */ + aad[0] = buf; + aad_len[0] = key_data - buf; + if (aes_siv_encrypt(ptk->kek, ptk->kek_len, + s_key_data, key_data_len, + 1, aad, aad_len, key_data) < 0) { + os_free(buf); + goto out; + } + + wpa_hexdump(MSG_DEBUG, "WPA: Encrypted Key Data from SIV", + key_data, AES_BLOCK_SIZE + key_data_len); + + os_free(msg); + msg = buf; + msg_len = buf_len; +#else /* CONFIG_FILS */ goto out; +#endif /* CONFIG_FILS */ } - wpa_hexdump_key(MSG_DEBUG, "WPA: KCK", kck, kck_len); - wpa_hexdump(MSG_DEBUG, "WPA: Derived Key MIC", key_mic, mic_len); + wpa_hexdump(MSG_MSGDUMP, "WPA: TX EAPOL-Key", msg, msg_len); ret = wpa_sm_ether_send(sm, dest, proto, msg, msg_len); eapol_sm_notify_tx_eapol_key(sm->eapol); @@ -99,12 +182,10 @@ void wpa_sm_key_request(struct wpa_sm *sm, int error, int pairwise) { size_t mic_len, hdrlen, rlen; struct wpa_eapol_key *reply; - struct wpa_eapol_key_192 *reply192; int key_info, ver; - u8 bssid[ETH_ALEN], *rbuf, *key_mic; + u8 bssid[ETH_ALEN], *rbuf, *key_mic, *mic; - if (sm->key_mgmt == WPA_KEY_MGMT_OSEN || - wpa_key_mgmt_suite_b(sm->key_mgmt)) + if (wpa_use_akm_defined(sm->key_mgmt)) ver = WPA_KEY_INFO_TYPE_AKM_DEFINED; else if (wpa_key_mgmt_ft(sm->key_mgmt) || wpa_key_mgmt_sha256(sm->key_mgmt)) @@ -120,20 +201,21 @@ void wpa_sm_key_request(struct wpa_sm *sm, int error, int pairwise) return; } - mic_len = wpa_mic_len(sm->key_mgmt); - hdrlen = mic_len == 24 ? sizeof(*reply192) : sizeof(*reply); + mic_len = wpa_mic_len(sm->key_mgmt, sm->pmk_len); + hdrlen = sizeof(*reply) + mic_len + 2; rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, hdrlen, &rlen, (void *) &reply); if (rbuf == NULL) return; - reply192 = (struct wpa_eapol_key_192 *) reply; reply->type = (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) ? EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA; key_info = WPA_KEY_INFO_REQUEST | ver; if (sm->ptk_set) - key_info |= WPA_KEY_INFO_MIC | WPA_KEY_INFO_SECURE; + key_info |= WPA_KEY_INFO_SECURE; + if (sm->ptk_set && mic_len) + key_info |= WPA_KEY_INFO_MIC; if (error) key_info |= WPA_KEY_INFO_ERROR; if (pairwise) @@ -144,21 +226,19 @@ void wpa_sm_key_request(struct wpa_sm *sm, int error, int pairwise) WPA_REPLAY_COUNTER_LEN); inc_byte_array(sm->request_counter, WPA_REPLAY_COUNTER_LEN); - if (mic_len == 24) - WPA_PUT_BE16(reply192->key_data_length, 0); - else - WPA_PUT_BE16(reply->key_data_length, 0); + mic = (u8 *) (reply + 1); + WPA_PUT_BE16(mic + mic_len, 0); if (!(key_info & WPA_KEY_INFO_MIC)) key_mic = NULL; else - key_mic = reply192->key_mic; /* same offset in reply */ + key_mic = mic; wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "WPA: Sending EAPOL-Key Request (error=%d " "pairwise=%d ptk_set=%d len=%lu)", error, pairwise, sm->ptk_set, (unsigned long) rlen); - wpa_eapol_key_send(sm, sm->ptk.kck, sm->ptk.kck_len, ver, bssid, - ETH_P_EAPOL, rbuf, rlen, key_mic); + wpa_eapol_key_send(sm, &sm->ptk, ver, bssid, ETH_P_EAPOL, rbuf, rlen, + key_mic); } @@ -192,7 +272,7 @@ static int wpa_supplicant_get_pmk(struct wpa_sm *sm, * event before receiving this 1/4 message, so try to find a * matching PMKSA cache entry here. */ sm->cur_pmksa = pmksa_cache_get(sm->pmksa, src_addr, pmkid, - NULL); + NULL, 0); if (sm->cur_pmksa) { wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: found matching PMKID from PMKSA cache"); @@ -212,11 +292,23 @@ static int wpa_supplicant_get_pmk(struct wpa_sm *sm, eapol_sm_notify_cached(sm->eapol); #ifdef CONFIG_IEEE80211R sm->xxkey_len = 0; +#ifdef CONFIG_SAE + if (sm->key_mgmt == WPA_KEY_MGMT_FT_SAE && + sm->pmk_len == PMK_LEN) { + /* Need to allow FT key derivation to proceed with + * PMK from SAE being used as the XXKey in cases where + * the PMKID in msg 1/4 matches the PMKSA entry that was + * just added based on SAE authentication for the + * initial mobility domain association. */ + os_memcpy(sm->xxkey, sm->pmk, sm->pmk_len); + sm->xxkey_len = sm->pmk_len; + } +#endif /* CONFIG_SAE */ #endif /* CONFIG_IEEE80211R */ } else if (wpa_key_mgmt_wpa_ieee8021x(sm->key_mgmt) && sm->eapol) { int res, pmk_len; - if (sm->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) + if (wpa_key_mgmt_sha384(sm->key_mgmt)) pmk_len = PMK_LEN_SUITE_B_192; else pmk_len = PMK_LEN; @@ -235,14 +327,28 @@ static int wpa_supplicant_get_pmk(struct wpa_sm *sm, u8 buf[2 * PMK_LEN]; if (eapol_sm_get_key(sm->eapol, buf, 2 * PMK_LEN) == 0) { - os_memcpy(sm->xxkey, buf + PMK_LEN, PMK_LEN); - sm->xxkey_len = PMK_LEN; + if (wpa_key_mgmt_sha384(sm->key_mgmt)) { + os_memcpy(sm->xxkey, buf, + SHA384_MAC_LEN); + sm->xxkey_len = SHA384_MAC_LEN; + } else { + os_memcpy(sm->xxkey, buf + PMK_LEN, + PMK_LEN); + sm->xxkey_len = PMK_LEN; + } os_memset(buf, 0, sizeof(buf)); } #endif /* CONFIG_IEEE80211R */ } if (res == 0) { struct rsn_pmksa_cache_entry *sa = NULL; + const u8 *fils_cache_id = NULL; + +#ifdef CONFIG_FILS + if (sm->fils_cache_id_set) + fils_cache_id = sm->fils_cache_id; +#endif /* CONFIG_FILS */ + wpa_hexdump_key(MSG_DEBUG, "WPA: PMK from EAPOL state " "machines", sm->pmk, pmk_len); sm->pmk_len = pmk_len; @@ -255,11 +361,12 @@ static int wpa_supplicant_get_pmk(struct wpa_sm *sm, NULL, 0, src_addr, sm->own_addr, sm->network_ctx, - sm->key_mgmt); + sm->key_mgmt, + fils_cache_id); } if (!sm->cur_pmksa && pmkid && - pmksa_cache_get(sm->pmksa, src_addr, pmkid, NULL)) - { + pmksa_cache_get(sm->pmksa, src_addr, pmkid, NULL, + 0)) { wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: the new PMK matches with the " "PMKID"); @@ -279,6 +386,11 @@ static int wpa_supplicant_get_pmk(struct wpa_sm *sm, if (!sm->cur_pmksa) sm->cur_pmksa = sa; +#ifdef CONFIG_IEEE80211R + } else if (wpa_key_mgmt_ft(sm->key_mgmt) && sm->ft_protocol) { + wpa_printf(MSG_DEBUG, + "FT: Continue 4-way handshake without PMK/PMKID for association using FT protocol"); +#endif /* CONFIG_IEEE80211R */ } else { wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: Failed to get master session key from " @@ -343,9 +455,9 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst, { size_t mic_len, hdrlen, rlen; struct wpa_eapol_key *reply; - struct wpa_eapol_key_192 *reply192; u8 *rbuf, *key_mic; u8 *rsn_ie_buf = NULL; + u16 key_info; if (wpa_ie == NULL) { wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: No wpa_ie set - " @@ -385,8 +497,8 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst, wpa_hexdump(MSG_DEBUG, "WPA: WPA IE for msg 2/4", wpa_ie, wpa_ie_len); - mic_len = wpa_mic_len(sm->key_mgmt); - hdrlen = mic_len == 24 ? sizeof(*reply192) : sizeof(*reply); + mic_len = wpa_mic_len(sm->key_mgmt, sm->pmk_len); + hdrlen = sizeof(*reply) + mic_len + 2; rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, hdrlen + wpa_ie_len, &rlen, (void *) &reply); @@ -394,13 +506,16 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst, os_free(rsn_ie_buf); return -1; } - reply192 = (struct wpa_eapol_key_192 *) reply; reply->type = (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) ? EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA; - WPA_PUT_BE16(reply->key_info, - ver | WPA_KEY_INFO_KEY_TYPE | WPA_KEY_INFO_MIC); + key_info = ver | WPA_KEY_INFO_KEY_TYPE; + if (mic_len) + key_info |= WPA_KEY_INFO_MIC; + else + key_info |= WPA_KEY_INFO_ENCR_KEY_DATA; + WPA_PUT_BE16(reply->key_info, key_info); if (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) WPA_PUT_BE16(reply->key_length, 0); else @@ -410,36 +525,41 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst, wpa_hexdump(MSG_DEBUG, "WPA: Replay Counter", reply->replay_counter, WPA_REPLAY_COUNTER_LEN); - key_mic = reply192->key_mic; /* same offset for reply and reply192 */ - if (mic_len == 24) { - WPA_PUT_BE16(reply192->key_data_length, wpa_ie_len); - os_memcpy(reply192 + 1, wpa_ie, wpa_ie_len); - } else { - WPA_PUT_BE16(reply->key_data_length, wpa_ie_len); - os_memcpy(reply + 1, wpa_ie, wpa_ie_len); - } + key_mic = (u8 *) (reply + 1); + WPA_PUT_BE16(key_mic + mic_len, wpa_ie_len); /* Key Data Length */ + os_memcpy(key_mic + mic_len + 2, wpa_ie, wpa_ie_len); /* Key Data */ os_free(rsn_ie_buf); os_memcpy(reply->key_nonce, nonce, WPA_NONCE_LEN); wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Sending EAPOL-Key 2/4"); - return wpa_eapol_key_send(sm, ptk->kck, ptk->kck_len, ver, dst, - ETH_P_EAPOL, rbuf, rlen, key_mic); + return wpa_eapol_key_send(sm, ptk, ver, dst, ETH_P_EAPOL, rbuf, rlen, + key_mic); } static int wpa_derive_ptk(struct wpa_sm *sm, const unsigned char *src_addr, const struct wpa_eapol_key *key, struct wpa_ptk *ptk) { + const u8 *z = NULL; + size_t z_len = 0; + #ifdef CONFIG_IEEE80211R if (wpa_key_mgmt_ft(sm->key_mgmt)) return wpa_derive_ptk_ft(sm, src_addr, key, ptk); #endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_DPP2 + if (sm->key_mgmt == WPA_KEY_MGMT_DPP && sm->dpp_z) { + z = wpabuf_head(sm->dpp_z); + z_len = wpabuf_len(sm->dpp_z); + } +#endif /* CONFIG_DPP2 */ + return wpa_pmk_to_ptk(sm->pmk, sm->pmk_len, "Pairwise key expansion", sm->own_addr, sm->bssid, sm->snonce, key->key_nonce, ptk, sm->key_mgmt, - sm->pairwise_cipher); + sm->pairwise_cipher, z, z_len); } @@ -502,7 +622,8 @@ static void wpa_supplicant_process_1_of_4(struct wpa_sm *sm, /* Calculate PTK which will be stored as a temporary PTK until it has * been verified when processing message 3/4. */ ptk = &sm->tptk; - wpa_derive_ptk(sm, src_addr, key, ptk); + if (wpa_derive_ptk(sm, src_addr, key, ptk) < 0) + goto failed; if (sm->pairwise_cipher == WPA_CIPHER_TKIP) { u8 buf[8]; /* Supplicant: swap tx/rx Mic keys */ @@ -516,6 +637,33 @@ static void wpa_supplicant_process_1_of_4(struct wpa_sm *sm, kde = sm->assoc_wpa_ie; kde_len = sm->assoc_wpa_ie_len; +#ifdef CONFIG_OCV + if (wpa_sm_ocv_enabled(sm)) { + struct wpa_channel_info ci; + u8 *pos; + + if (wpa_sm_channel_info(sm, &ci) != 0) { + wpa_printf(MSG_WARNING, + "Failed to get channel info for OCI element in EAPOL-Key 2/4"); + goto failed; + } + + kde_buf = os_malloc(kde_len + 2 + RSN_SELECTOR_LEN + 3); + if (!kde_buf) { + wpa_printf(MSG_WARNING, + "Failed to allocate memory for KDE with OCI in EAPOL-Key 2/4"); + goto failed; + } + + os_memcpy(kde_buf, kde, kde_len); + kde = kde_buf; + pos = kde + kde_len; + if (ocv_insert_oci_kde(&ci, &pos) < 0) + goto failed; + kde_len = pos - kde; + } +#endif /* CONFIG_OCV */ + #ifdef CONFIG_P2P if (sm->p2p) { kde_buf = os_malloc(kde_len + 2 + RSN_SELECTOR_LEN + 1); @@ -573,7 +721,9 @@ static void wpa_supplicant_key_neg_complete(struct wpa_sm *sm, sm, addr, MLME_SETPROTECTION_PROTECT_TYPE_RX_TX, MLME_SETPROTECTION_KEY_TYPE_PAIRWISE); eapol_sm_notify_portValid(sm->eapol, TRUE); - if (wpa_key_mgmt_wpa_psk(sm->key_mgmt)) + if (wpa_key_mgmt_wpa_psk(sm->key_mgmt) || + sm->key_mgmt == WPA_KEY_MGMT_DPP || + sm->key_mgmt == WPA_KEY_MGMT_OWE) eapol_sm_notify_eap_success(sm->eapol, TRUE); /* * Start preauthentication after a short wait to avoid a @@ -582,7 +732,9 @@ static void wpa_supplicant_key_neg_complete(struct wpa_sm *sm, * likelihood of the first preauth EAPOL-Start frame getting to * the target AP. */ - eloop_register_timeout(1, 0, wpa_sm_start_preauth, sm, NULL); + if (!dl_list_empty(&sm->pmksa_candidates)) + eloop_register_timeout(1, 0, wpa_sm_start_preauth, + sm, NULL); } if (sm->cur_pmksa && sm->cur_pmksa->opportunistic) { @@ -640,6 +792,11 @@ static int wpa_supplicant_install_ptk(struct wpa_sm *sm, 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); + return -1; + } rsclen = wpa_cipher_rsc_len(sm->pairwise_cipher); if (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) { @@ -660,6 +817,7 @@ static int wpa_supplicant_install_ptk(struct wpa_sm *sm, /* TK is not needed anymore in supplicant */ os_memset(sm->ptk.tk, 0, WPA_TK_MAX_LEN); + sm->ptk.tk_len = 0; sm->ptk.installed = 1; if (sm->wpa_ptk_rekey) { @@ -870,8 +1028,6 @@ static int wpa_supplicant_pairwise_gtk(struct wpa_sm *sm, } os_memset(&gd, 0, sizeof(gd)); - wpa_supplicant_key_neg_complete(sm, sm->bssid, - key_info & WPA_KEY_INFO_SECURE); return 0; } @@ -897,7 +1053,7 @@ static int wpa_supplicant_install_igtk(struct wpa_sm *sm, } wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, - "WPA: IGTK keyid %d pn %02x%02x%02x%02x%02x%02x", + "WPA: IGTK keyid %d pn " COMPACT_MACSTR, keyidx, MAC2STR(igtk->pn)); wpa_hexdump_key(MSG_DEBUG, "WPA: IGTK", igtk->igtk, len); if (keyidx > 4095) { @@ -909,9 +1065,27 @@ static int wpa_supplicant_install_igtk(struct wpa_sm *sm, broadcast_ether_addr, keyidx, 0, igtk->pn, sizeof(igtk->pn), igtk->igtk, len) < 0) { - wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, - "WPA: Failed to configure IGTK to the driver"); - return -1; + if (keyidx == 0x0400 || keyidx == 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 + * valid IGTK, so do not try to configure this key with + * swapped KeyID bytes. Instead, continue without + * configuring the IGTK so that the driver can drop any + * received group-addressed robust management frames due + * to missing keys. + * + * Normally, this error behavior would result in us + * disconnecting, but there are number of deployed APs + * with this broken behavior, so as an interoperability + * workaround, allow the connection to proceed. */ + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, + "WPA: Ignore IGTK configuration error due to invalid IGTK KeyID byte order"); + } else { + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, + "WPA: Failed to configure IGTK to the driver"); + return -1; + } } if (wnm_sleep) { @@ -1205,22 +1379,24 @@ int wpa_supplicant_send_4_of_4(struct wpa_sm *sm, const unsigned char *dst, { size_t mic_len, hdrlen, rlen; struct wpa_eapol_key *reply; - struct wpa_eapol_key_192 *reply192; u8 *rbuf, *key_mic; - mic_len = wpa_mic_len(sm->key_mgmt); - hdrlen = mic_len == 24 ? sizeof(*reply192) : sizeof(*reply); + mic_len = wpa_mic_len(sm->key_mgmt, sm->pmk_len); + hdrlen = sizeof(*reply) + mic_len + 2; rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, hdrlen, &rlen, (void *) &reply); if (rbuf == NULL) return -1; - reply192 = (struct wpa_eapol_key_192 *) reply; reply->type = (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) ? EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA; key_info &= WPA_KEY_INFO_SECURE; - key_info |= ver | WPA_KEY_INFO_KEY_TYPE | WPA_KEY_INFO_MIC; + key_info |= ver | WPA_KEY_INFO_KEY_TYPE; + if (mic_len) + key_info |= WPA_KEY_INFO_MIC; + else + key_info |= WPA_KEY_INFO_ENCR_KEY_DATA; WPA_PUT_BE16(reply->key_info, key_info); if (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) WPA_PUT_BE16(reply->key_length, 0); @@ -1229,15 +1405,12 @@ int wpa_supplicant_send_4_of_4(struct wpa_sm *sm, const unsigned char *dst, os_memcpy(reply->replay_counter, key->replay_counter, WPA_REPLAY_COUNTER_LEN); - key_mic = reply192->key_mic; /* same offset for reply and reply192 */ - if (mic_len == 24) - WPA_PUT_BE16(reply192->key_data_length, 0); - else - WPA_PUT_BE16(reply->key_data_length, 0); + key_mic = (u8 *) (reply + 1); + WPA_PUT_BE16(key_mic + mic_len, 0); wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Sending EAPOL-Key 4/4"); - return wpa_eapol_key_send(sm, ptk->kck, ptk->kck_len, ver, dst, - ETH_P_EAPOL, rbuf, rlen, key_mic); + return wpa_eapol_key_send(sm, ptk, ver, dst, ETH_P_EAPOL, rbuf, rlen, + key_mic); } @@ -1309,6 +1482,26 @@ static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm, } #endif /* CONFIG_P2P */ +#ifdef CONFIG_OCV + if (wpa_sm_ocv_enabled(sm)) { + struct wpa_channel_info ci; + + if (wpa_sm_channel_info(sm, &ci) != 0) { + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, + "Failed to get channel info to validate received OCI in EAPOL-Key 3/4"); + return; + } + + if (ocv_verify_tx_params(ie.oci, ie.oci_len, &ci, + channel_width_to_int(ci.chanwidth), + ci.seg1_idx) != 0) { + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "%s", + ocv_errorstr); + return; + } + } +#endif /* CONFIG_OCV */ + if (wpa_supplicant_send_4_of_4(sm, sm->bssid, key, ver, key_info, &sm->ptk) < 0) { goto failed; @@ -1333,8 +1526,11 @@ static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm, wpa_sm_set_state(sm, WPA_GROUP_HANDSHAKE); if (sm->group_cipher == WPA_CIPHER_GTK_NOT_USED) { - wpa_supplicant_key_neg_complete(sm, sm->bssid, - key_info & WPA_KEY_INFO_SECURE); + /* No GTK to be set to the driver */ + } else if (!ie.gtk && sm->proto == WPA_PROTO_RSN) { + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, + "RSN: No GTK KDE included in EAPOL-Key msg 3/4"); + goto failed; } else if (ie.gtk && wpa_supplicant_pairwise_gtk(sm, key, ie.gtk, ie.gtk_len, key_info) < 0) { @@ -1349,16 +1545,26 @@ static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm, goto failed; } + if (sm->group_cipher == WPA_CIPHER_GTK_NOT_USED || ie.gtk) + wpa_supplicant_key_neg_complete(sm, sm->bssid, + key_info & WPA_KEY_INFO_SECURE); + if (ie.gtk) wpa_sm_set_rekey_offload(sm); - if (sm->proto == WPA_PROTO_RSN && wpa_key_mgmt_suite_b(sm->key_mgmt)) { + /* Add PMKSA cache entry for Suite B AKMs here since PMKID can be + * calculated only after KCK has been derived. Though, do not replace an + * existing PMKSA entry after each 4-way handshake (i.e., new KCK/PMKID) + * to avoid unnecessary changes of PMKID while continuing to use the + * same PMK. */ + if (sm->proto == WPA_PROTO_RSN && wpa_key_mgmt_suite_b(sm->key_mgmt) && + !sm->cur_pmksa) { struct rsn_pmksa_cache_entry *sa; sa = pmksa_cache_add(sm->pmksa, sm->pmk, sm->pmk_len, NULL, sm->ptk.kck, sm->ptk.kck_len, sm->bssid, sm->own_addr, - sm->network_ctx, sm->key_mgmt); + sm->network_ctx, sm->key_mgmt, NULL); if (!sm->cur_pmksa) sm->cur_pmksa = sa; } @@ -1380,7 +1586,8 @@ static int wpa_supplicant_process_1_of_2_rsn(struct wpa_sm *sm, int maxkeylen; struct wpa_eapol_ie_parse ie; - wpa_hexdump(MSG_DEBUG, "RSN: msg 1/2 key data", keydata, keydatalen); + wpa_hexdump_key(MSG_DEBUG, "RSN: msg 1/2 key data", + keydata, keydatalen); if (wpa_supplicant_parse_ies(keydata, keydatalen, &ie) < 0) return -1; if (ie.gtk && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) { @@ -1395,6 +1602,26 @@ static int wpa_supplicant_process_1_of_2_rsn(struct wpa_sm *sm, } maxkeylen = gd->gtk_len = ie.gtk_len - 2; +#ifdef CONFIG_OCV + if (wpa_sm_ocv_enabled(sm)) { + struct wpa_channel_info ci; + + if (wpa_sm_channel_info(sm, &ci) != 0) { + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, + "Failed to get channel info to validate received OCI in EAPOL-Key group msg 1/2"); + return -1; + } + + if (ocv_verify_tx_params(ie.oci, ie.oci_len, &ci, + channel_width_to_int(ci.chanwidth), + ci.seg1_idx) != 0) { + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "%s", + ocv_errorstr); + return -1; + } + } +#endif /* CONFIG_OCV */ + if (wpa_supplicant_check_group_cipher(sm, sm->group_cipher, gd->gtk_len, maxkeylen, &gd->key_rsc_len, &gd->alg)) @@ -1514,22 +1741,30 @@ static int wpa_supplicant_send_2_of_2(struct wpa_sm *sm, { size_t mic_len, hdrlen, rlen; struct wpa_eapol_key *reply; - struct wpa_eapol_key_192 *reply192; u8 *rbuf, *key_mic; + size_t kde_len = 0; - mic_len = wpa_mic_len(sm->key_mgmt); - hdrlen = mic_len == 24 ? sizeof(*reply192) : sizeof(*reply); +#ifdef CONFIG_OCV + if (wpa_sm_ocv_enabled(sm)) + kde_len = OCV_OCI_KDE_LEN; +#endif /* CONFIG_OCV */ + + mic_len = wpa_mic_len(sm->key_mgmt, sm->pmk_len); + hdrlen = sizeof(*reply) + mic_len + 2; rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, - hdrlen, &rlen, (void *) &reply); + hdrlen + kde_len, &rlen, (void *) &reply); if (rbuf == NULL) return -1; - reply192 = (struct wpa_eapol_key_192 *) reply; reply->type = (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) ? EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA; key_info &= WPA_KEY_INFO_KEY_INDEX_MASK; - key_info |= ver | WPA_KEY_INFO_MIC | WPA_KEY_INFO_SECURE; + key_info |= ver | WPA_KEY_INFO_SECURE; + if (mic_len) + key_info |= WPA_KEY_INFO_MIC; + else + key_info |= WPA_KEY_INFO_ENCR_KEY_DATA; WPA_PUT_BE16(reply->key_info, key_info); if (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) WPA_PUT_BE16(reply->key_length, 0); @@ -1538,15 +1773,32 @@ static int wpa_supplicant_send_2_of_2(struct wpa_sm *sm, os_memcpy(reply->replay_counter, key->replay_counter, WPA_REPLAY_COUNTER_LEN); - key_mic = reply192->key_mic; /* same offset for reply and reply192 */ - if (mic_len == 24) - WPA_PUT_BE16(reply192->key_data_length, 0); - else - WPA_PUT_BE16(reply->key_data_length, 0); + key_mic = (u8 *) (reply + 1); + WPA_PUT_BE16(key_mic + mic_len, kde_len); /* Key Data Length */ + +#ifdef CONFIG_OCV + if (wpa_sm_ocv_enabled(sm)) { + struct wpa_channel_info ci; + u8 *pos; + + if (wpa_sm_channel_info(sm, &ci) != 0) { + wpa_printf(MSG_WARNING, + "Failed to get channel info for OCI element in EAPOL-Key 2/2"); + os_free(rbuf); + return -1; + } + + pos = key_mic + mic_len + 2; /* Key Data */ + if (ocv_insert_oci_kde(&ci, &pos) < 0) { + os_free(rbuf); + return -1; + } + } +#endif /* CONFIG_OCV */ wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Sending EAPOL-Key 2/2"); - return wpa_eapol_key_send(sm, sm->ptk.kck, sm->ptk.kck_len, ver, - sm->bssid, ETH_P_EAPOL, rbuf, rlen, key_mic); + return wpa_eapol_key_send(sm, &sm->ptk, ver, sm->bssid, ETH_P_EAPOL, + rbuf, rlen, key_mic); } @@ -1561,7 +1813,7 @@ static void wpa_supplicant_process_1_of_2(struct wpa_sm *sm, struct wpa_gtk_data gd; const u8 *key_rsc; - if (!sm->msg_3_of_4_ok) { + if (!sm->msg_3_of_4_ok && !wpa_fils_is_completed(sm)) { wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "WPA: Group Key Handshake started prior to completion of 4-way handshake"); goto failed; @@ -1622,42 +1874,68 @@ failed: static int wpa_supplicant_verify_eapol_key_mic(struct wpa_sm *sm, - struct wpa_eapol_key_192 *key, + struct wpa_eapol_key *key, u16 ver, const u8 *buf, size_t len) { u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN]; int ok = 0; - size_t mic_len = wpa_mic_len(sm->key_mgmt); + size_t mic_len = wpa_mic_len(sm->key_mgmt, sm->pmk_len); - os_memcpy(mic, key->key_mic, mic_len); + os_memcpy(mic, key + 1, mic_len); if (sm->tptk_set) { - os_memset(key->key_mic, 0, mic_len); - wpa_eapol_key_mic(sm->tptk.kck, sm->tptk.kck_len, sm->key_mgmt, - ver, buf, len, key->key_mic); - if (os_memcmp_const(mic, key->key_mic, mic_len) != 0) { + os_memset(key + 1, 0, mic_len); + if (wpa_eapol_key_mic(sm->tptk.kck, sm->tptk.kck_len, + sm->key_mgmt, + ver, buf, len, (u8 *) (key + 1)) < 0 || + os_memcmp_const(mic, key + 1, mic_len) != 0) { wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: Invalid EAPOL-Key MIC " "when using TPTK - ignoring TPTK"); +#ifdef TEST_FUZZ + wpa_printf(MSG_INFO, + "TEST: Ignore Key MIC failure for fuzz testing"); + goto continue_fuzz; +#endif /* TEST_FUZZ */ } else { +#ifdef TEST_FUZZ + continue_fuzz: +#endif /* TEST_FUZZ */ ok = 1; sm->tptk_set = 0; sm->ptk_set = 1; os_memcpy(&sm->ptk, &sm->tptk, sizeof(sm->ptk)); os_memset(&sm->tptk, 0, sizeof(sm->tptk)); + /* + * This assures the same TPTK in sm->tptk can never be + * copied twice to sm->ptk as the new PTK. In + * combination with the installed flag in the wpa_ptk + * struct, this assures the same PTK is only installed + * once. + */ + sm->renew_snonce = 1; } } if (!ok && sm->ptk_set) { - os_memset(key->key_mic, 0, mic_len); - wpa_eapol_key_mic(sm->ptk.kck, sm->ptk.kck_len, sm->key_mgmt, - ver, buf, len, key->key_mic); - if (os_memcmp_const(mic, key->key_mic, mic_len) != 0) { + os_memset(key + 1, 0, mic_len); + if (wpa_eapol_key_mic(sm->ptk.kck, sm->ptk.kck_len, + sm->key_mgmt, + ver, buf, len, (u8 *) (key + 1)) < 0 || + os_memcmp_const(mic, key + 1, mic_len) != 0) { wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: Invalid EAPOL-Key MIC - " "dropping packet"); +#ifdef TEST_FUZZ + wpa_printf(MSG_INFO, + "TEST: Ignore Key MIC failure for fuzz testing"); + goto continue_fuzz2; +#endif /* TEST_FUZZ */ return -1; } +#ifdef TEST_FUZZ + continue_fuzz2: +#endif /* TEST_FUZZ */ ok = 1; } @@ -1677,7 +1955,8 @@ static int wpa_supplicant_verify_eapol_key_mic(struct wpa_sm *sm, /* Decrypt RSN EAPOL-Key key data (RC4 or AES-WRAP) */ static int wpa_supplicant_decrypt_key_data(struct wpa_sm *sm, - struct wpa_eapol_key *key, u16 ver, + struct wpa_eapol_key *key, + size_t mic_len, u16 ver, u8 *key_data, size_t *key_data_len) { wpa_hexdump(MSG_DEBUG, "RSN: encrypted key data", @@ -1698,6 +1977,8 @@ static int wpa_supplicant_decrypt_key_data(struct wpa_sm *sm, return -1; #else /* CONFIG_NO_RC4 */ u8 ek[32]; + + wpa_printf(MSG_DEBUG, "WPA: Decrypt Key Data using RC4"); os_memcpy(ek, key->key_iv, 16); os_memcpy(ek + 16, sm->ptk.kek, sm->ptk.kek_len); if (rc4_skip(ek, 32, 256, key_data, *key_data_len)) { @@ -1710,9 +1991,12 @@ static int wpa_supplicant_decrypt_key_data(struct wpa_sm *sm, #endif /* CONFIG_NO_RC4 */ } else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES || ver == WPA_KEY_INFO_TYPE_AES_128_CMAC || - sm->key_mgmt == WPA_KEY_MGMT_OSEN || - wpa_key_mgmt_suite_b(sm->key_mgmt)) { + wpa_use_aes_key_wrap(sm->key_mgmt)) { u8 *buf; + + wpa_printf(MSG_DEBUG, + "WPA: Decrypt Key Data using AES-UNWRAP (KEK length %u)", + (unsigned int) sm->ptk.kek_len); if (*key_data_len < 8 || *key_data_len % 8) { wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: Unsupported AES-WRAP len %u", @@ -1726,17 +2010,28 @@ static int wpa_supplicant_decrypt_key_data(struct wpa_sm *sm, "WPA: No memory for AES-UNWRAP buffer"); return -1; } +#ifdef TEST_FUZZ + os_memset(buf, 0x11, *key_data_len); +#endif /* TEST_FUZZ */ if (aes_unwrap(sm->ptk.kek, sm->ptk.kek_len, *key_data_len / 8, key_data, buf)) { +#ifdef TEST_FUZZ + wpa_printf(MSG_INFO, + "TEST: Ignore AES unwrap failure for fuzz testing"); + goto continue_fuzz; +#endif /* TEST_FUZZ */ bin_clear_free(buf, *key_data_len); wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: AES unwrap failed - " "could not decrypt EAPOL-Key key data"); return -1; } +#ifdef TEST_FUZZ + continue_fuzz: +#endif /* TEST_FUZZ */ os_memcpy(key_data, buf, *key_data_len); bin_clear_free(buf, *key_data_len); - WPA_PUT_BE16(key->key_data_length, *key_data_len); + WPA_PUT_BE16(((u8 *) (key + 1)) + mic_len, *key_data_len); } else { wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: Unsupported key_info type %d", ver); @@ -1799,6 +2094,76 @@ static void wpa_eapol_key_dump(struct wpa_sm *sm, } +#ifdef CONFIG_FILS +static int wpa_supp_aead_decrypt(struct wpa_sm *sm, u8 *buf, size_t buf_len, + size_t *key_data_len) +{ + struct wpa_ptk *ptk; + struct ieee802_1x_hdr *hdr; + struct wpa_eapol_key *key; + u8 *pos, *tmp; + const u8 *aad[1]; + size_t aad_len[1]; + + if (*key_data_len < AES_BLOCK_SIZE) { + wpa_printf(MSG_INFO, "No room for AES-SIV data in the frame"); + return -1; + } + + if (sm->tptk_set) + ptk = &sm->tptk; + else if (sm->ptk_set) + ptk = &sm->ptk; + else + return -1; + + hdr = (struct ieee802_1x_hdr *) buf; + key = (struct wpa_eapol_key *) (hdr + 1); + pos = (u8 *) (key + 1); + pos += 2; /* Pointing at the Encrypted Key Data field */ + + tmp = os_malloc(*key_data_len); + if (!tmp) + return -1; + + /* AES-SIV AAD from EAPOL protocol version field (inclusive) to + * to Key Data (exclusive). */ + aad[0] = buf; + aad_len[0] = pos - buf; + if (aes_siv_decrypt(ptk->kek, ptk->kek_len, pos, *key_data_len, + 1, aad, aad_len, tmp) < 0) { + wpa_printf(MSG_INFO, "Invalid AES-SIV data in the frame"); + bin_clear_free(tmp, *key_data_len); + return -1; + } + + /* AEAD decryption and validation completed successfully */ + (*key_data_len) -= AES_BLOCK_SIZE; + wpa_hexdump_key(MSG_DEBUG, "WPA: Decrypted Key Data", + tmp, *key_data_len); + + /* Replace Key Data field with the decrypted version */ + os_memcpy(pos, tmp, *key_data_len); + pos -= 2; /* Key Data Length field */ + WPA_PUT_BE16(pos, *key_data_len); + bin_clear_free(tmp, *key_data_len); + + if (sm->tptk_set) { + sm->tptk_set = 0; + sm->ptk_set = 1; + os_memcpy(&sm->ptk, &sm->tptk, sizeof(sm->ptk)); + os_memset(&sm->tptk, 0, sizeof(sm->tptk)); + } + + os_memcpy(sm->rx_replay_counter, key->replay_counter, + WPA_REPLAY_COUNTER_LEN); + sm->rx_replay_counter_set = 1; + + return 0; +} +#endif /* CONFIG_FILS */ + + /** * wpa_sm_rx_eapol - Process received WPA EAPOL frames * @sm: Pointer to WPA state machine data from wpa_sm_init() @@ -1821,20 +2186,18 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr, size_t plen, data_len, key_data_len; const struct ieee802_1x_hdr *hdr; struct wpa_eapol_key *key; - struct wpa_eapol_key_192 *key192; u16 key_info, ver; u8 *tmp = NULL; int ret = -1; - struct wpa_peerkey *peerkey = NULL; - u8 *key_data; + u8 *mic, *key_data; size_t mic_len, keyhdrlen; #ifdef CONFIG_IEEE80211R sm->ft_completed = 0; #endif /* CONFIG_IEEE80211R */ - mic_len = wpa_mic_len(sm->key_mgmt); - keyhdrlen = mic_len == 24 ? sizeof(*key192) : sizeof(*key); + mic_len = wpa_mic_len(sm->key_mgmt, sm->pmk_len); + keyhdrlen = sizeof(*key) + mic_len + 2; if (len < sizeof(*hdr) + keyhdrlen) { wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, @@ -1881,17 +2244,12 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr, * Make a copy of the frame since we need to modify the buffer during * MAC validation and Key Data decryption. */ - tmp = os_malloc(data_len); + tmp = os_memdup(buf, data_len); if (tmp == NULL) goto out; - os_memcpy(tmp, buf, data_len); key = (struct wpa_eapol_key *) (tmp + sizeof(struct ieee802_1x_hdr)); - key192 = (struct wpa_eapol_key_192 *) - (tmp + sizeof(struct ieee802_1x_hdr)); - if (mic_len == 24) - key_data = (u8 *) (key192 + 1); - else - key_data = (u8 *) (key + 1); + mic = (u8 *) (key + 1); + key_data = mic + mic_len + 2; if (key->type != EAPOL_KEY_TYPE_WPA && key->type != EAPOL_KEY_TYPE_RSN) { @@ -1902,11 +2260,8 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr, goto out; } - if (mic_len == 24) - key_data_len = WPA_GET_BE16(key192->key_data_length); - else - key_data_len = WPA_GET_BE16(key->key_data_length); - wpa_eapol_key_dump(sm, key, key_data_len, key192->key_mic, mic_len); + key_data_len = WPA_GET_BE16(mic + mic_len); + wpa_eapol_key_dump(sm, key, key_data_len, mic, mic_len); if (key_data_len > plen - keyhdrlen) { wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "WPA: Invalid EAPOL-Key " @@ -1924,23 +2279,14 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr, ver != WPA_KEY_INFO_TYPE_AES_128_CMAC && #endif /* CONFIG_IEEE80211R || CONFIG_IEEE80211W */ ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES && - !wpa_key_mgmt_suite_b(sm->key_mgmt) && - sm->key_mgmt != WPA_KEY_MGMT_OSEN) { + !wpa_use_akm_defined(sm->key_mgmt)) { wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "WPA: Unsupported EAPOL-Key descriptor version %d", ver); goto out; } - if (sm->key_mgmt == WPA_KEY_MGMT_OSEN && - ver != WPA_KEY_INFO_TYPE_AKM_DEFINED) { - wpa_msg(sm->ctx->msg_ctx, MSG_INFO, - "OSEN: Unsupported EAPOL-Key descriptor version %d", - ver); - goto out; - } - - if (wpa_key_mgmt_suite_b(sm->key_mgmt) && + if (wpa_use_akm_defined(sm->key_mgmt) && ver != WPA_KEY_INFO_TYPE_AKM_DEFINED) { wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "RSN: Unsupported EAPOL-Key descriptor version %d (expected AKM defined = 0)", @@ -1951,7 +2297,8 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr, #ifdef CONFIG_IEEE80211R if (wpa_key_mgmt_ft(sm->key_mgmt)) { /* IEEE 802.11r uses a new key_info type (AES-128-CMAC). */ - if (ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) { + if (ver != WPA_KEY_INFO_TYPE_AES_128_CMAC && + !wpa_use_akm_defined(sm->key_mgmt)) { wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "FT: AP did not use AES-128-CMAC"); goto out; @@ -1961,8 +2308,7 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr, #ifdef CONFIG_IEEE80211W if (wpa_key_mgmt_sha256(sm->key_mgmt)) { if (ver != WPA_KEY_INFO_TYPE_AES_128_CMAC && - sm->key_mgmt != WPA_KEY_MGMT_OSEN && - !wpa_key_mgmt_suite_b(sm->key_mgmt)) { + !wpa_use_akm_defined(sm->key_mgmt)) { wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "WPA: AP did not use the " "negotiated AES-128-CMAC"); @@ -1971,7 +2317,7 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr, } else #endif /* CONFIG_IEEE80211W */ if (sm->pairwise_cipher == WPA_CIPHER_CCMP && - !wpa_key_mgmt_suite_b(sm->key_mgmt) && + !wpa_use_akm_defined(sm->key_mgmt) && ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "WPA: CCMP is used, but EAPOL-Key " @@ -1991,7 +2337,7 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr, } else goto out; } else if (sm->pairwise_cipher == WPA_CIPHER_GCMP && - !wpa_key_mgmt_suite_b(sm->key_mgmt) && + !wpa_use_akm_defined(sm->key_mgmt) && ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "WPA: GCMP is used, but EAPOL-Key " @@ -1999,44 +2345,7 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr, goto out; } -#ifdef CONFIG_PEERKEY - for (peerkey = sm->peerkey; peerkey; peerkey = peerkey->next) { - if (os_memcmp(peerkey->addr, src_addr, ETH_ALEN) == 0) - break; - } - - if (!(key_info & WPA_KEY_INFO_SMK_MESSAGE) && peerkey) { - if (!peerkey->initiator && peerkey->replay_counter_set && - os_memcmp(key->replay_counter, peerkey->replay_counter, - WPA_REPLAY_COUNTER_LEN) <= 0) { - wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, - "RSN: EAPOL-Key Replay Counter did not " - "increase (STK) - dropping packet"); - goto out; - } else if (peerkey->initiator) { - u8 _tmp[WPA_REPLAY_COUNTER_LEN]; - os_memcpy(_tmp, key->replay_counter, - WPA_REPLAY_COUNTER_LEN); - inc_byte_array(_tmp, WPA_REPLAY_COUNTER_LEN); - if (os_memcmp(_tmp, peerkey->replay_counter, - WPA_REPLAY_COUNTER_LEN) != 0) { - wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, - "RSN: EAPOL-Key Replay " - "Counter did not match (STK) - " - "dropping packet"); - goto out; - } - } - } - - if (peerkey && peerkey->initiator && (key_info & WPA_KEY_INFO_ACK)) { - wpa_msg(sm->ctx->msg_ctx, MSG_INFO, - "RSN: Ack bit in key_info from STK peer"); - goto out; - } -#endif /* CONFIG_PEERKEY */ - - if (!peerkey && sm->rx_replay_counter_set && + if (sm->rx_replay_counter_set && os_memcmp(key->replay_counter, sm->rx_replay_counter, WPA_REPLAY_COUNTER_LEN) <= 0) { wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, @@ -2045,11 +2354,13 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr, goto out; } - if (!(key_info & (WPA_KEY_INFO_ACK | WPA_KEY_INFO_SMK_MESSAGE)) -#ifdef CONFIG_PEERKEY - && (peerkey == NULL || !peerkey->initiator) -#endif /* CONFIG_PEERKEY */ - ) { + if (key_info & WPA_KEY_INFO_SMK_MESSAGE) { + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, + "WPA: Unsupported SMK bit in key_info"); + goto out; + } + + if (!(key_info & WPA_KEY_INFO_ACK)) { wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "WPA: No Ack bit in key_info"); goto out; @@ -2061,19 +2372,19 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr, goto out; } - if ((key_info & WPA_KEY_INFO_MIC) && !peerkey && - wpa_supplicant_verify_eapol_key_mic(sm, key192, ver, tmp, data_len)) + if ((key_info & WPA_KEY_INFO_MIC) && + wpa_supplicant_verify_eapol_key_mic(sm, key, ver, tmp, data_len)) goto out; -#ifdef CONFIG_PEERKEY - if ((key_info & WPA_KEY_INFO_MIC) && peerkey && - peerkey_verify_eapol_key_mic(sm, peerkey, key192, ver, tmp, - data_len)) - goto out; -#endif /* CONFIG_PEERKEY */ +#ifdef CONFIG_FILS + if (!mic_len && (key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) { + if (wpa_supp_aead_decrypt(sm, tmp, data_len, &key_data_len)) + goto out; + } +#endif /* CONFIG_FILS */ if ((sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) && - (key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) { + (key_info & WPA_KEY_INFO_ENCR_KEY_DATA) && mic_len) { /* * Only decrypt the Key Data field if the frame's authenticity * was verified. When using AES-SIV (FILS), the MIC flag is not @@ -2085,7 +2396,8 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr, "WPA: Ignore EAPOL-Key with encrypted but unauthenticated data"); goto out; } - if (wpa_supplicant_decrypt_key_data(sm, key, ver, key_data, + if (wpa_supplicant_decrypt_key_data(sm, key, mic_len, + ver, key_data, &key_data_len)) goto out; } @@ -2097,11 +2409,8 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr, "non-zero key index"); goto out; } - if (peerkey) { - /* PeerKey 4-Way Handshake */ - peerkey_rx_eapol_4way(sm, peerkey, key, key_info, ver, - key_data, key_data_len); - } else if (key_info & WPA_KEY_INFO_MIC) { + if (key_info & (WPA_KEY_INFO_MIC | + WPA_KEY_INFO_ENCR_KEY_DATA)) { /* 3/4 4-Way Handshake */ wpa_supplicant_process_3_of_4(sm, key, ver, key_data, key_data_len); @@ -2111,19 +2420,16 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr, ver, key_data, key_data_len); } - } else if (key_info & WPA_KEY_INFO_SMK_MESSAGE) { - /* PeerKey SMK Handshake */ - peerkey_rx_eapol_smk(sm, src_addr, key, key_data_len, key_info, - ver); } else { - if (key_info & WPA_KEY_INFO_MIC) { + if ((mic_len && (key_info & WPA_KEY_INFO_MIC)) || + (!mic_len && (key_info & WPA_KEY_INFO_ENCR_KEY_DATA))) { /* 1/2 Group Key Handshake */ wpa_supplicant_process_1_of_2(sm, src_addr, key, key_data, key_data_len, ver); } else { wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, - "WPA: EAPOL-Key (Group) without Mic bit - " + "WPA: EAPOL-Key (Group) without Mic/Encr bit - " "dropped"); } } @@ -2298,6 +2604,7 @@ static void wpa_sm_pmksa_free_cb(struct rsn_pmksa_cache_entry *entry, } if (deauth) { + sm->pmk_len = 0; os_memset(sm->pmk, 0, sizeof(sm->pmk)); wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED); } @@ -2355,13 +2662,24 @@ void wpa_sm_deinit(struct wpa_sm *sm) os_free(sm->ap_rsn_ie); wpa_sm_drop_sa(sm); os_free(sm->ctx); - peerkey_deinit(sm); #ifdef CONFIG_IEEE80211R os_free(sm->assoc_resp_ies); #endif /* CONFIG_IEEE80211R */ #ifdef CONFIG_TESTING_OPTIONS wpabuf_free(sm->test_assoc_ie); #endif /* CONFIG_TESTING_OPTIONS */ +#ifdef CONFIG_FILS_SK_PFS + crypto_ecdh_deinit(sm->fils_ecdh); +#endif /* CONFIG_FILS_SK_PFS */ +#ifdef CONFIG_FILS + wpabuf_free(sm->fils_ft_ies); +#endif /* CONFIG_FILS */ +#ifdef CONFIG_OWE + crypto_ecdh_deinit(sm->owe_ecdh); +#endif /* CONFIG_OWE */ +#ifdef CONFIG_DPP2 + wpabuf_clear_free(sm->dpp_z); +#endif /* CONFIG_DPP2 */ os_free(sm); } @@ -2403,8 +2721,21 @@ void wpa_sm_notify_assoc(struct wpa_sm *sm, const u8 *bssid) wpa_ft_prepare_auth_request(sm, NULL); clear_keys = 0; + sm->ft_protocol = 1; + } else { + sm->ft_protocol = 0; } #endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_FILS + if (sm->fils_completed) { + /* + * Clear portValid to kick EAPOL state machine to re-enter + * AUTHENTICATED state to get the EAPOL port Authorized. + */ + wpa_supplicant_key_neg_complete(sm, sm->bssid, 1); + clear_keys = 0; + } +#endif /* CONFIG_FILS */ if (clear_keys) { /* @@ -2445,7 +2776,6 @@ void wpa_sm_notify_disassoc(struct wpa_sm *sm) { eloop_cancel_timeout(wpa_sm_start_preauth, sm, NULL); eloop_cancel_timeout(wpa_sm_rekey_ptk, sm, NULL); - peerkey_deinit(sm); rsn_preauth_deinit(sm); pmksa_cache_clear_current(sm); if (wpa_sm_get_state(sm) == WPA_4WAY_HANDSHAKE) @@ -2453,14 +2783,19 @@ void wpa_sm_notify_disassoc(struct wpa_sm *sm) #ifdef CONFIG_TDLS wpa_tdls_disassoc(sm); #endif /* CONFIG_TDLS */ +#ifdef CONFIG_FILS + sm->fils_completed = 0; +#endif /* CONFIG_FILS */ #ifdef CONFIG_IEEE80211R sm->ft_reassoc_completed = 0; + sm->ft_protocol = 0; #endif /* CONFIG_IEEE80211R */ /* Keys are not needed in the WPA state machine anymore */ wpa_sm_drop_sa(sm); sm->msg_3_of_4_ok = 0; + os_memset(sm->bssid, 0, ETH_ALEN); } @@ -2480,6 +2815,8 @@ void wpa_sm_set_pmk(struct wpa_sm *sm, const u8 *pmk, size_t pmk_len, if (sm == NULL) return; + wpa_hexdump_key(MSG_DEBUG, "WPA: Set PMK based on external data", + pmk, pmk_len); sm->pmk_len = pmk_len; os_memcpy(sm->pmk, pmk, pmk_len); @@ -2492,7 +2829,7 @@ void wpa_sm_set_pmk(struct wpa_sm *sm, const u8 *pmk, size_t pmk_len, if (bssid) { pmksa_cache_add(sm->pmksa, pmk, pmk_len, pmkid, NULL, 0, bssid, sm->own_addr, - sm->network_ctx, sm->key_mgmt); + sm->network_ctx, sm->key_mgmt, NULL); } } @@ -2510,11 +2847,15 @@ void wpa_sm_set_pmk_from_pmksa(struct wpa_sm *sm) return; if (sm->cur_pmksa) { + wpa_hexdump_key(MSG_DEBUG, + "WPA: Set PMK based on current PMKSA", + sm->cur_pmksa->pmk, sm->cur_pmksa->pmk_len); sm->pmk_len = sm->cur_pmksa->pmk_len; os_memcpy(sm->pmk, sm->cur_pmksa->pmk, sm->pmk_len); } else { - sm->pmk_len = PMK_LEN; - os_memset(sm->pmk, 0, PMK_LEN); + wpa_printf(MSG_DEBUG, "WPA: No current PMKSA - clear PMK"); + sm->pmk_len = 0; + os_memset(sm->pmk, 0, PMK_LEN_MAX); } } @@ -2562,7 +2903,6 @@ void wpa_sm_set_config(struct wpa_sm *sm, struct rsn_supp_config *config) if (config) { sm->network_ctx = config->network_ctx; - sm->peerkey_enabled = config->peerkey_enabled; sm->allowed_pairwise_cipher = config->allowed_pairwise_cipher; sm->proactive_key_caching = config->proactive_key_caching; sm->eap_workaround = config->eap_workaround; @@ -2575,9 +2915,17 @@ void wpa_sm_set_config(struct wpa_sm *sm, struct rsn_supp_config *config) sm->wpa_ptk_rekey = config->wpa_ptk_rekey; sm->p2p = config->p2p; sm->wpa_rsc_relaxation = config->wpa_rsc_relaxation; +#ifdef CONFIG_FILS + if (config->fils_cache_id) { + sm->fils_cache_id_set = 1; + os_memcpy(sm->fils_cache_id, config->fils_cache_id, + FILS_CACHE_ID_LEN); + } else { + sm->fils_cache_id_set = 0; + } +#endif /* CONFIG_FILS */ } else { sm->network_ctx = NULL; - sm->peerkey_enabled = 0; sm->allowed_pairwise_cipher = 0; sm->proactive_key_caching = 0; sm->eap_workaround = 0; @@ -2687,6 +3035,9 @@ int wpa_sm_set_param(struct wpa_sm *sm, enum wpa_sm_conf_params param, case WPA_PARAM_MFP: sm->mfp = value; break; + case WPA_PARAM_OCV: + sm->ocv = value; + break; default: break; } @@ -2730,9 +3081,12 @@ int wpa_sm_get_status(struct wpa_sm *sm, char *buf, size_t buflen, >= 0 && rsn.capabilities & (WPA_CAPABILITY_MFPR | WPA_CAPABILITY_MFPC)) { - ret = os_snprintf(pos, end - pos, "pmf=%d\n", + ret = os_snprintf(pos, end - pos, "pmf=%d\n" + "mgmt_group_cipher=%s\n", (rsn.capabilities & - WPA_CAPABILITY_MFPR) ? 2 : 1); + WPA_CAPABILITY_MFPR) ? 2 : 1, + wpa_cipher_txt( + sm->mgmt_group_cipher)); if (os_snprintf_error(end - pos, ret)) return pos - buf; pos += ret; @@ -2758,6 +3112,19 @@ int wpa_sm_pmf_enabled(struct wpa_sm *sm) } +int wpa_sm_ocv_enabled(struct wpa_sm *sm) +{ + struct wpa_ie_data rsn; + + if (!sm->ocv || !sm->ap_rsn_ie) + return 0; + + return wpa_parse_wpa_ie_rsn(sm->ap_rsn_ie, sm->ap_rsn_ie_len, + &rsn) >= 0 && + (rsn.capabilities & WPA_CAPABILITY_OCVC); +} + + /** * wpa_sm_set_assoc_wpa_ie_default - Generate own WPA/RSN IE from configuration * @sm: Pointer to WPA state machine data from wpa_sm_init() @@ -2798,12 +3165,15 @@ int wpa_sm_set_assoc_wpa_ie_default(struct wpa_sm *sm, u8 *wpa_ie, * the correct version of the IE even if PMKSA caching is * aborted (which would remove PMKID from IE generation). */ - sm->assoc_wpa_ie = os_malloc(*wpa_ie_len); + sm->assoc_wpa_ie = os_memdup(wpa_ie, *wpa_ie_len); if (sm->assoc_wpa_ie == NULL) return -1; - os_memcpy(sm->assoc_wpa_ie, wpa_ie, *wpa_ie_len); sm->assoc_wpa_ie_len = *wpa_ie_len; + } else { + wpa_hexdump(MSG_DEBUG, + "WPA: Leave previously set WPA IE default", + sm->assoc_wpa_ie, sm->assoc_wpa_ie_len); } return 0; @@ -2834,11 +3204,10 @@ int wpa_sm_set_assoc_wpa_ie(struct wpa_sm *sm, const u8 *ie, size_t len) sm->assoc_wpa_ie_len = 0; } else { wpa_hexdump(MSG_DEBUG, "WPA: set own WPA/RSN IE", ie, len); - sm->assoc_wpa_ie = os_malloc(len); + sm->assoc_wpa_ie = os_memdup(ie, len); if (sm->assoc_wpa_ie == NULL) return -1; - os_memcpy(sm->assoc_wpa_ie, ie, len); sm->assoc_wpa_ie_len = len; } @@ -2869,11 +3238,10 @@ int wpa_sm_set_ap_wpa_ie(struct wpa_sm *sm, const u8 *ie, size_t len) sm->ap_wpa_ie_len = 0; } else { wpa_hexdump(MSG_DEBUG, "WPA: set AP WPA IE", ie, len); - sm->ap_wpa_ie = os_malloc(len); + sm->ap_wpa_ie = os_memdup(ie, len); if (sm->ap_wpa_ie == NULL) return -1; - os_memcpy(sm->ap_wpa_ie, ie, len); sm->ap_wpa_ie_len = len; } @@ -2904,11 +3272,10 @@ int wpa_sm_set_ap_rsn_ie(struct wpa_sm *sm, const u8 *ie, size_t len) sm->ap_rsn_ie_len = 0; } else { wpa_hexdump(MSG_DEBUG, "WPA: set AP RSN IE", ie, len); - sm->ap_rsn_ie = os_malloc(len); + sm->ap_rsn_ie = os_memdup(ie, len); if (sm->ap_rsn_ie == NULL) return -1; - os_memcpy(sm->ap_rsn_ie, ie, len); sm->ap_rsn_ie_len = len; } @@ -2947,11 +3314,43 @@ int wpa_sm_pmksa_cache_list(struct wpa_sm *sm, char *buf, size_t len) } +struct rsn_pmksa_cache_entry * wpa_sm_pmksa_cache_head(struct wpa_sm *sm) +{ + return pmksa_cache_head(sm->pmksa); +} + + +struct rsn_pmksa_cache_entry * +wpa_sm_pmksa_cache_add_entry(struct wpa_sm *sm, + struct rsn_pmksa_cache_entry * entry) +{ + return pmksa_cache_add_entry(sm->pmksa, entry); +} + + +void wpa_sm_pmksa_cache_add(struct wpa_sm *sm, const u8 *pmk, size_t pmk_len, + const u8 *pmkid, const u8 *bssid, + const u8 *fils_cache_id) +{ + sm->cur_pmksa = pmksa_cache_add(sm->pmksa, pmk, pmk_len, pmkid, NULL, 0, + bssid, sm->own_addr, sm->network_ctx, + sm->key_mgmt, fils_cache_id); +} + + +int wpa_sm_pmksa_exists(struct wpa_sm *sm, const u8 *bssid, + const void *network_ctx) +{ + return pmksa_cache_get(sm->pmksa, bssid, NULL, network_ctx, 0) != NULL; +} + + void wpa_sm_drop_sa(struct wpa_sm *sm) { wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Clear old PMK and PTK"); sm->ptk_set = 0; sm->tptk_set = 0; + sm->pmk_len = 0; os_memset(sm->pmk, 0, sizeof(sm->pmk)); os_memset(&sm->ptk, 0, sizeof(sm->ptk)); os_memset(&sm->tptk, 0, sizeof(sm->tptk)); @@ -2963,8 +3362,11 @@ void wpa_sm_drop_sa(struct wpa_sm *sm) #endif /* CONFIG_IEEE80211W */ #ifdef CONFIG_IEEE80211R os_memset(sm->xxkey, 0, sizeof(sm->xxkey)); + sm->xxkey_len = 0; os_memset(sm->pmk_r0, 0, sizeof(sm->pmk_r0)); + sm->pmk_r0_len = 0; os_memset(sm->pmk_r1, 0, sizeof(sm->pmk_r1)); + sm->pmk_r1_len = 0; #endif /* CONFIG_IEEE80211R */ } @@ -3049,27 +3451,6 @@ int wpa_wnmsleep_install_key(struct wpa_sm *sm, u8 subelem_id, u8 *buf) #endif /* CONFIG_WNM */ -#ifdef CONFIG_PEERKEY -int wpa_sm_rx_eapol_peerkey(struct wpa_sm *sm, const u8 *src_addr, - const u8 *buf, size_t len) -{ - struct wpa_peerkey *peerkey; - - for (peerkey = sm->peerkey; peerkey; peerkey = peerkey->next) { - if (os_memcmp(peerkey->addr, src_addr, ETH_ALEN) == 0) - break; - } - - if (!peerkey) - return 0; - - wpa_sm_rx_eapol(sm, src_addr, buf, len); - - return 1; -} -#endif /* CONFIG_PEERKEY */ - - #ifdef CONFIG_P2P int wpa_sm_get_p2p_ip_addr(struct wpa_sm *sm, u8 *buf) @@ -3114,9 +3495,1202 @@ void wpa_sm_set_ptk_kck_kek(struct wpa_sm *sm, #ifdef CONFIG_TESTING_OPTIONS + void wpa_sm_set_test_assoc_ie(struct wpa_sm *sm, struct wpabuf *buf) { wpabuf_free(sm->test_assoc_ie); sm->test_assoc_ie = buf; } + + +const u8 * wpa_sm_get_anonce(struct wpa_sm *sm) +{ + return sm->anonce; +} + #endif /* CONFIG_TESTING_OPTIONS */ + + +unsigned int wpa_sm_get_key_mgmt(struct wpa_sm *sm) +{ + return sm->key_mgmt; +} + + +#ifdef CONFIG_FILS + +struct wpabuf * fils_build_auth(struct wpa_sm *sm, int dh_group, const u8 *md) +{ + struct wpabuf *buf = NULL; + struct wpabuf *erp_msg; + struct wpabuf *pub = NULL; + + erp_msg = eapol_sm_build_erp_reauth_start(sm->eapol); + if (!erp_msg && !sm->cur_pmksa) { + wpa_printf(MSG_DEBUG, + "FILS: Neither ERP EAP-Initiate/Re-auth nor PMKSA cache entry is available - skip FILS"); + goto fail; + } + + wpa_printf(MSG_DEBUG, "FILS: Try to use FILS (erp=%d pmksa_cache=%d)", + erp_msg != NULL, sm->cur_pmksa != NULL); + + sm->fils_completed = 0; + + if (!sm->assoc_wpa_ie) { + wpa_printf(MSG_INFO, "FILS: No own RSN IE set for FILS"); + goto fail; + } + + if (random_get_bytes(sm->fils_nonce, FILS_NONCE_LEN) < 0 || + random_get_bytes(sm->fils_session, FILS_SESSION_LEN) < 0) + goto fail; + + wpa_hexdump(MSG_DEBUG, "FILS: Generated FILS Nonce", + sm->fils_nonce, FILS_NONCE_LEN); + wpa_hexdump(MSG_DEBUG, "FILS: Generated FILS Session", + sm->fils_session, FILS_SESSION_LEN); + +#ifdef CONFIG_FILS_SK_PFS + sm->fils_dh_group = dh_group; + if (dh_group) { + crypto_ecdh_deinit(sm->fils_ecdh); + sm->fils_ecdh = crypto_ecdh_init(dh_group); + if (!sm->fils_ecdh) { + wpa_printf(MSG_INFO, + "FILS: Could not initialize ECDH with group %d", + dh_group); + goto fail; + } + pub = crypto_ecdh_get_pubkey(sm->fils_ecdh, 1); + if (!pub) + goto fail; + wpa_hexdump_buf(MSG_DEBUG, "FILS: Element (DH public key)", + pub); + sm->fils_dh_elem_len = wpabuf_len(pub); + } +#endif /* CONFIG_FILS_SK_PFS */ + + buf = wpabuf_alloc(1000 + sm->assoc_wpa_ie_len + + (pub ? wpabuf_len(pub) : 0)); + if (!buf) + goto fail; + + /* Fields following the Authentication algorithm number field */ + + /* Authentication Transaction seq# */ + wpabuf_put_le16(buf, 1); + + /* Status Code */ + wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS); + + /* TODO: FILS PK */ +#ifdef CONFIG_FILS_SK_PFS + if (dh_group) { + /* Finite Cyclic Group */ + wpabuf_put_le16(buf, dh_group); + /* Element */ + wpabuf_put_buf(buf, pub); + } +#endif /* CONFIG_FILS_SK_PFS */ + + /* RSNE */ + wpa_hexdump(MSG_DEBUG, "FILS: RSNE in FILS Authentication frame", + sm->assoc_wpa_ie, sm->assoc_wpa_ie_len); + wpabuf_put_data(buf, sm->assoc_wpa_ie, sm->assoc_wpa_ie_len); + + if (md) { + /* MDE when using FILS for FT initial association */ + struct rsn_mdie *mdie; + + wpabuf_put_u8(buf, WLAN_EID_MOBILITY_DOMAIN); + wpabuf_put_u8(buf, sizeof(*mdie)); + mdie = wpabuf_put(buf, sizeof(*mdie)); + os_memcpy(mdie->mobility_domain, md, MOBILITY_DOMAIN_ID_LEN); + mdie->ft_capab = 0; + } + + /* FILS Nonce */ + wpabuf_put_u8(buf, WLAN_EID_EXTENSION); /* Element ID */ + wpabuf_put_u8(buf, 1 + FILS_NONCE_LEN); /* Length */ + /* Element ID Extension */ + wpabuf_put_u8(buf, WLAN_EID_EXT_FILS_NONCE); + wpabuf_put_data(buf, sm->fils_nonce, FILS_NONCE_LEN); + + /* FILS Session */ + wpabuf_put_u8(buf, WLAN_EID_EXTENSION); /* Element ID */ + wpabuf_put_u8(buf, 1 + FILS_SESSION_LEN); /* Length */ + /* Element ID Extension */ + wpabuf_put_u8(buf, WLAN_EID_EXT_FILS_SESSION); + wpabuf_put_data(buf, sm->fils_session, FILS_SESSION_LEN); + + /* FILS Wrapped Data */ + sm->fils_erp_pmkid_set = 0; + if (erp_msg) { + wpabuf_put_u8(buf, WLAN_EID_EXTENSION); /* Element ID */ + wpabuf_put_u8(buf, 1 + wpabuf_len(erp_msg)); /* Length */ + /* Element ID Extension */ + wpabuf_put_u8(buf, WLAN_EID_EXT_FILS_WRAPPED_DATA); + wpabuf_put_buf(buf, erp_msg); + /* Calculate pending PMKID here so that we do not need to + * maintain a copy of the EAP-Initiate/Reauth message. */ + if (fils_pmkid_erp(sm->key_mgmt, wpabuf_head(erp_msg), + wpabuf_len(erp_msg), + sm->fils_erp_pmkid) == 0) + sm->fils_erp_pmkid_set = 1; + } + + wpa_hexdump_buf(MSG_DEBUG, "RSN: FILS fields for Authentication frame", + buf); + +fail: + wpabuf_free(erp_msg); + wpabuf_free(pub); + return buf; +} + + +int fils_process_auth(struct wpa_sm *sm, const u8 *bssid, const u8 *data, + size_t len) +{ + const u8 *pos, *end; + struct ieee802_11_elems elems; + struct wpa_ie_data rsn; + int pmkid_match = 0; + u8 ick[FILS_ICK_MAX_LEN]; + size_t ick_len; + int res; + struct wpabuf *dh_ss = NULL; + const u8 *g_sta = NULL; + size_t g_sta_len = 0; + const u8 *g_ap = NULL; + size_t g_ap_len = 0; + struct wpabuf *pub = NULL; + + os_memcpy(sm->bssid, bssid, ETH_ALEN); + + wpa_hexdump(MSG_DEBUG, "FILS: Authentication frame fields", + data, len); + pos = data; + end = data + len; + + /* TODO: FILS PK */ +#ifdef CONFIG_FILS_SK_PFS + if (sm->fils_dh_group) { + u16 group; + + /* Using FILS PFS */ + + /* Finite Cyclic Group */ + if (end - pos < 2) { + wpa_printf(MSG_DEBUG, + "FILS: No room for Finite Cyclic Group"); + goto fail; + } + group = WPA_GET_LE16(pos); + pos += 2; + if (group != sm->fils_dh_group) { + wpa_printf(MSG_DEBUG, + "FILS: Unexpected change in Finite Cyclic Group: %u (expected %u)", + group, sm->fils_dh_group); + goto fail; + } + + /* Element */ + if ((size_t) (end - pos) < sm->fils_dh_elem_len) { + wpa_printf(MSG_DEBUG, "FILS: No room for Element"); + goto fail; + } + + if (!sm->fils_ecdh) { + wpa_printf(MSG_DEBUG, "FILS: No ECDH state available"); + goto fail; + } + dh_ss = crypto_ecdh_set_peerkey(sm->fils_ecdh, 1, pos, + sm->fils_dh_elem_len); + if (!dh_ss) { + wpa_printf(MSG_DEBUG, "FILS: ECDH operation failed"); + goto fail; + } + wpa_hexdump_buf_key(MSG_DEBUG, "FILS: DH_SS", dh_ss); + g_ap = pos; + g_ap_len = sm->fils_dh_elem_len; + pos += sm->fils_dh_elem_len; + } +#endif /* CONFIG_FILS_SK_PFS */ + + wpa_hexdump(MSG_DEBUG, "FILS: Remaining IEs", pos, end - pos); + if (ieee802_11_parse_elems(pos, end - pos, &elems, 1) == ParseFailed) { + wpa_printf(MSG_DEBUG, "FILS: Could not parse elements"); + goto fail; + } + + /* RSNE */ + wpa_hexdump(MSG_DEBUG, "FILS: RSN element", elems.rsn_ie, + elems.rsn_ie_len); + if (!elems.rsn_ie || + wpa_parse_wpa_ie_rsn(elems.rsn_ie - 2, elems.rsn_ie_len + 2, + &rsn) < 0) { + wpa_printf(MSG_DEBUG, "FILS: No RSN element"); + goto fail; + } + + if (!elems.fils_nonce) { + wpa_printf(MSG_DEBUG, "FILS: No FILS Nonce field"); + goto fail; + } + os_memcpy(sm->fils_anonce, elems.fils_nonce, FILS_NONCE_LEN); + wpa_hexdump(MSG_DEBUG, "FILS: ANonce", sm->fils_anonce, FILS_NONCE_LEN); + +#ifdef CONFIG_IEEE80211R + if (wpa_key_mgmt_ft(sm->key_mgmt)) { + struct wpa_ft_ies parse; + + if (!elems.mdie || !elems.ftie) { + wpa_printf(MSG_DEBUG, "FILS+FT: No MDE or FTE"); + goto fail; + } + + if (wpa_ft_parse_ies(pos, end - pos, &parse, + wpa_key_mgmt_sha384(sm->key_mgmt)) < 0) { + wpa_printf(MSG_DEBUG, "FILS+FT: Failed to parse IEs"); + goto fail; + } + + if (!parse.r0kh_id) { + wpa_printf(MSG_DEBUG, + "FILS+FT: No R0KH-ID subelem in FTE"); + goto fail; + } + os_memcpy(sm->r0kh_id, parse.r0kh_id, parse.r0kh_id_len); + sm->r0kh_id_len = parse.r0kh_id_len; + wpa_hexdump_ascii(MSG_DEBUG, "FILS+FT: R0KH-ID", + sm->r0kh_id, sm->r0kh_id_len); + + if (!parse.r1kh_id) { + wpa_printf(MSG_DEBUG, + "FILS+FT: No R1KH-ID subelem in FTE"); + goto fail; + } + os_memcpy(sm->r1kh_id, parse.r1kh_id, FT_R1KH_ID_LEN); + wpa_hexdump(MSG_DEBUG, "FILS+FT: R1KH-ID", + sm->r1kh_id, FT_R1KH_ID_LEN); + + /* TODO: Check MDE and FTE payload */ + + wpabuf_free(sm->fils_ft_ies); + sm->fils_ft_ies = wpabuf_alloc(2 + elems.mdie_len + + 2 + elems.ftie_len); + if (!sm->fils_ft_ies) + goto fail; + wpabuf_put_data(sm->fils_ft_ies, elems.mdie - 2, + 2 + elems.mdie_len); + wpabuf_put_data(sm->fils_ft_ies, elems.ftie - 2, + 2 + elems.ftie_len); + } else { + wpabuf_free(sm->fils_ft_ies); + sm->fils_ft_ies = NULL; + } +#endif /* CONFIG_IEEE80211R */ + + /* PMKID List */ + if (rsn.pmkid && rsn.num_pmkid > 0) { + wpa_hexdump(MSG_DEBUG, "FILS: PMKID List", + rsn.pmkid, rsn.num_pmkid * PMKID_LEN); + + if (rsn.num_pmkid != 1) { + wpa_printf(MSG_DEBUG, "FILS: Invalid PMKID selection"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "FILS: PMKID", rsn.pmkid, PMKID_LEN); + if (os_memcmp(sm->cur_pmksa->pmkid, rsn.pmkid, PMKID_LEN) != 0) + { + wpa_printf(MSG_DEBUG, "FILS: PMKID mismatch"); + wpa_hexdump(MSG_DEBUG, "FILS: Expected PMKID", + sm->cur_pmksa->pmkid, PMKID_LEN); + goto fail; + } + wpa_printf(MSG_DEBUG, + "FILS: Matching PMKID - continue using PMKSA caching"); + pmkid_match = 1; + } + if (!pmkid_match && sm->cur_pmksa) { + wpa_printf(MSG_DEBUG, + "FILS: No PMKID match - cannot use cached PMKSA entry"); + sm->cur_pmksa = NULL; + } + + /* FILS Session */ + if (!elems.fils_session) { + wpa_printf(MSG_DEBUG, "FILS: No FILS Session element"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "FILS: FILS Session", elems.fils_session, + FILS_SESSION_LEN); + if (os_memcmp(sm->fils_session, elems.fils_session, FILS_SESSION_LEN) + != 0) { + wpa_printf(MSG_DEBUG, "FILS: Session mismatch"); + wpa_hexdump(MSG_DEBUG, "FILS: Expected FILS Session", + sm->fils_session, FILS_SESSION_LEN); + goto fail; + } + + /* FILS Wrapped Data */ + if (!sm->cur_pmksa && elems.fils_wrapped_data) { + u8 rmsk[ERP_MAX_KEY_LEN]; + size_t rmsk_len; + + wpa_hexdump(MSG_DEBUG, "FILS: Wrapped Data", + elems.fils_wrapped_data, + elems.fils_wrapped_data_len); + eapol_sm_process_erp_finish(sm->eapol, elems.fils_wrapped_data, + elems.fils_wrapped_data_len); + if (eapol_sm_failed(sm->eapol)) + goto fail; + + rmsk_len = ERP_MAX_KEY_LEN; + res = eapol_sm_get_key(sm->eapol, rmsk, rmsk_len); + if (res == PMK_LEN) { + rmsk_len = PMK_LEN; + res = eapol_sm_get_key(sm->eapol, rmsk, rmsk_len); + } + if (res) + goto fail; + + res = fils_rmsk_to_pmk(sm->key_mgmt, rmsk, rmsk_len, + sm->fils_nonce, sm->fils_anonce, + dh_ss ? wpabuf_head(dh_ss) : NULL, + dh_ss ? wpabuf_len(dh_ss) : 0, + sm->pmk, &sm->pmk_len); + os_memset(rmsk, 0, sizeof(rmsk)); + + /* Don't use DHss in PTK derivation if PMKSA caching is not + * used. */ + wpabuf_clear_free(dh_ss); + dh_ss = NULL; + + if (res) + goto fail; + + if (!sm->fils_erp_pmkid_set) { + wpa_printf(MSG_DEBUG, "FILS: PMKID not available"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "FILS: PMKID", sm->fils_erp_pmkid, + PMKID_LEN); + wpa_printf(MSG_DEBUG, "FILS: ERP processing succeeded - add PMKSA cache entry for the result"); + sm->cur_pmksa = pmksa_cache_add(sm->pmksa, sm->pmk, sm->pmk_len, + sm->fils_erp_pmkid, NULL, 0, + sm->bssid, sm->own_addr, + sm->network_ctx, sm->key_mgmt, + NULL); + } + + if (!sm->cur_pmksa) { + wpa_printf(MSG_DEBUG, + "FILS: No remaining options to continue FILS authentication"); + goto fail; + } + + if (fils_pmk_to_ptk(sm->pmk, sm->pmk_len, sm->own_addr, sm->bssid, + sm->fils_nonce, sm->fils_anonce, + dh_ss ? wpabuf_head(dh_ss) : NULL, + dh_ss ? wpabuf_len(dh_ss) : 0, + &sm->ptk, ick, &ick_len, + sm->key_mgmt, sm->pairwise_cipher, + sm->fils_ft, &sm->fils_ft_len) < 0) { + wpa_printf(MSG_DEBUG, "FILS: Failed to derive PTK"); + goto fail; + } + + wpabuf_clear_free(dh_ss); + dh_ss = NULL; + + sm->ptk_set = 1; + sm->tptk_set = 0; + os_memset(&sm->tptk, 0, sizeof(sm->tptk)); + +#ifdef CONFIG_FILS_SK_PFS + if (sm->fils_dh_group) { + if (!sm->fils_ecdh) { + wpa_printf(MSG_INFO, "FILS: ECDH not initialized"); + goto fail; + } + pub = crypto_ecdh_get_pubkey(sm->fils_ecdh, 1); + if (!pub) + goto fail; + wpa_hexdump_buf(MSG_DEBUG, "FILS: gSTA", pub); + g_sta = wpabuf_head(pub); + g_sta_len = wpabuf_len(pub); + if (!g_ap) { + wpa_printf(MSG_INFO, "FILS: gAP not available"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "FILS: gAP", g_ap, g_ap_len); + } +#endif /* CONFIG_FILS_SK_PFS */ + + res = fils_key_auth_sk(ick, ick_len, sm->fils_nonce, + sm->fils_anonce, sm->own_addr, sm->bssid, + g_sta, g_sta_len, g_ap, g_ap_len, + sm->key_mgmt, sm->fils_key_auth_sta, + sm->fils_key_auth_ap, + &sm->fils_key_auth_len); + wpabuf_free(pub); + os_memset(ick, 0, sizeof(ick)); + return res; +fail: + wpabuf_free(pub); + wpabuf_clear_free(dh_ss); + return -1; +} + + +#ifdef CONFIG_IEEE80211R +static int fils_ft_build_assoc_req_rsne(struct wpa_sm *sm, struct wpabuf *buf) +{ + struct rsn_ie_hdr *rsnie; + u16 capab; + u8 *pos; + int use_sha384 = wpa_key_mgmt_sha384(sm->key_mgmt); + + /* RSNIE[PMKR0Name/PMKR1Name] */ + rsnie = wpabuf_put(buf, sizeof(*rsnie)); + rsnie->elem_id = WLAN_EID_RSN; + WPA_PUT_LE16(rsnie->version, RSN_VERSION); + + /* Group Suite Selector */ + if (!wpa_cipher_valid_group(sm->group_cipher)) { + wpa_printf(MSG_WARNING, "FT: Invalid group cipher (%d)", + sm->group_cipher); + return -1; + } + pos = wpabuf_put(buf, RSN_SELECTOR_LEN); + RSN_SELECTOR_PUT(pos, wpa_cipher_to_suite(WPA_PROTO_RSN, + sm->group_cipher)); + + /* Pairwise Suite Count */ + wpabuf_put_le16(buf, 1); + + /* Pairwise Suite List */ + if (!wpa_cipher_valid_pairwise(sm->pairwise_cipher)) { + wpa_printf(MSG_WARNING, "FT: Invalid pairwise cipher (%d)", + sm->pairwise_cipher); + return -1; + } + pos = wpabuf_put(buf, RSN_SELECTOR_LEN); + RSN_SELECTOR_PUT(pos, wpa_cipher_to_suite(WPA_PROTO_RSN, + sm->pairwise_cipher)); + + /* Authenticated Key Management Suite Count */ + wpabuf_put_le16(buf, 1); + + /* Authenticated Key Management Suite List */ + pos = wpabuf_put(buf, RSN_SELECTOR_LEN); + if (sm->key_mgmt == WPA_KEY_MGMT_FT_FILS_SHA256) + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_FILS_SHA256); + else if (sm->key_mgmt == WPA_KEY_MGMT_FT_FILS_SHA384) + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_FILS_SHA384); + else { + wpa_printf(MSG_WARNING, + "FILS+FT: Invalid key management type (%d)", + sm->key_mgmt); + return -1; + } + + /* RSN Capabilities */ + capab = 0; +#ifdef CONFIG_IEEE80211W + if (sm->mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC) + capab |= WPA_CAPABILITY_MFPC; +#endif /* CONFIG_IEEE80211W */ + if (sm->ocv) + capab |= WPA_CAPABILITY_OCVC; + wpabuf_put_le16(buf, capab); + + /* PMKID Count */ + wpabuf_put_le16(buf, 1); + + /* PMKID List [PMKR1Name] */ + wpa_hexdump_key(MSG_DEBUG, "FILS+FT: XXKey (FILS-FT)", + sm->fils_ft, sm->fils_ft_len); + wpa_hexdump_ascii(MSG_DEBUG, "FILS+FT: SSID", sm->ssid, sm->ssid_len); + wpa_hexdump(MSG_DEBUG, "FILS+FT: MDID", + sm->mobility_domain, MOBILITY_DOMAIN_ID_LEN); + wpa_hexdump_ascii(MSG_DEBUG, "FILS+FT: R0KH-ID", + sm->r0kh_id, sm->r0kh_id_len); + if (wpa_derive_pmk_r0(sm->fils_ft, sm->fils_ft_len, sm->ssid, + sm->ssid_len, sm->mobility_domain, + sm->r0kh_id, sm->r0kh_id_len, sm->own_addr, + sm->pmk_r0, sm->pmk_r0_name, use_sha384) < 0) { + wpa_printf(MSG_WARNING, "FILS+FT: Could not derive PMK-R0"); + return -1; + } + sm->pmk_r0_len = use_sha384 ? SHA384_MAC_LEN : PMK_LEN; + wpa_hexdump_key(MSG_DEBUG, "FILS+FT: PMK-R0", + sm->pmk_r0, sm->pmk_r0_len); + wpa_hexdump(MSG_DEBUG, "FILS+FT: PMKR0Name", + sm->pmk_r0_name, WPA_PMK_NAME_LEN); + wpa_printf(MSG_DEBUG, "FILS+FT: R1KH-ID: " MACSTR, + MAC2STR(sm->r1kh_id)); + pos = wpabuf_put(buf, WPA_PMK_NAME_LEN); + if (wpa_derive_pmk_r1_name(sm->pmk_r0_name, sm->r1kh_id, sm->own_addr, + sm->pmk_r1_name, use_sha384) < 0) { + wpa_printf(MSG_WARNING, "FILS+FT: Could not derive PMKR1Name"); + return -1; + } + wpa_hexdump(MSG_DEBUG, "FILS+FT: PMKR1Name", sm->pmk_r1_name, + WPA_PMK_NAME_LEN); + os_memcpy(pos, sm->pmk_r1_name, WPA_PMK_NAME_LEN); + +#ifdef CONFIG_IEEE80211W + if (sm->mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC) { + /* Management Group Cipher Suite */ + pos = wpabuf_put(buf, RSN_SELECTOR_LEN); + RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC); + } +#endif /* CONFIG_IEEE80211W */ + + rsnie->len = ((u8 *) wpabuf_put(buf, 0) - (u8 *) rsnie) - 2; + return 0; +} +#endif /* CONFIG_IEEE80211R */ + + +struct wpabuf * fils_build_assoc_req(struct wpa_sm *sm, const u8 **kek, + size_t *kek_len, const u8 **snonce, + const u8 **anonce, + const struct wpabuf **hlp, + unsigned int num_hlp) +{ + struct wpabuf *buf; + size_t len; + unsigned int i; + + len = 1000; +#ifdef CONFIG_IEEE80211R + if (sm->fils_ft_ies) + len += wpabuf_len(sm->fils_ft_ies); + if (wpa_key_mgmt_ft(sm->key_mgmt)) + len += 256; +#endif /* CONFIG_IEEE80211R */ + for (i = 0; hlp && i < num_hlp; i++) + len += 10 + wpabuf_len(hlp[i]); + buf = wpabuf_alloc(len); + if (!buf) + return NULL; + +#ifdef CONFIG_IEEE80211R + if (wpa_key_mgmt_ft(sm->key_mgmt) && sm->fils_ft_ies) { + /* MDE and FTE when using FILS+FT */ + wpabuf_put_buf(buf, sm->fils_ft_ies); + /* RSNE with PMKR1Name in PMKID field */ + if (fils_ft_build_assoc_req_rsne(sm, buf) < 0) { + wpabuf_free(buf); + return NULL; + } + } +#endif /* CONFIG_IEEE80211R */ + + /* FILS Session */ + wpabuf_put_u8(buf, WLAN_EID_EXTENSION); /* Element ID */ + wpabuf_put_u8(buf, 1 + FILS_SESSION_LEN); /* Length */ + /* Element ID Extension */ + wpabuf_put_u8(buf, WLAN_EID_EXT_FILS_SESSION); + wpabuf_put_data(buf, sm->fils_session, FILS_SESSION_LEN); + + /* Everything after FILS Session element gets encrypted in the driver + * with KEK. The buffer returned from here is the plaintext version. */ + + /* TODO: FILS Public Key */ + + /* FILS Key Confirm */ + wpabuf_put_u8(buf, WLAN_EID_EXTENSION); /* Element ID */ + wpabuf_put_u8(buf, 1 + sm->fils_key_auth_len); /* Length */ + /* Element ID Extension */ + wpabuf_put_u8(buf, WLAN_EID_EXT_FILS_KEY_CONFIRM); + wpabuf_put_data(buf, sm->fils_key_auth_sta, sm->fils_key_auth_len); + + /* FILS HLP Container */ + for (i = 0; hlp && i < num_hlp; i++) { + const u8 *pos = wpabuf_head(hlp[i]); + size_t left = wpabuf_len(hlp[i]); + + wpabuf_put_u8(buf, WLAN_EID_EXTENSION); /* Element ID */ + if (left <= 254) + len = 1 + left; + else + len = 255; + wpabuf_put_u8(buf, len); /* Length */ + /* Element ID Extension */ + wpabuf_put_u8(buf, WLAN_EID_EXT_FILS_HLP_CONTAINER); + /* Destination MAC Address, Source MAC Address, HLP Packet. + * HLP Packet is in MSDU format (i.e., included the LLC/SNAP + * header when LPD is used). */ + wpabuf_put_data(buf, pos, len - 1); + pos += len - 1; + left -= len - 1; + while (left) { + wpabuf_put_u8(buf, WLAN_EID_FRAGMENT); + len = left > 255 ? 255 : left; + wpabuf_put_u8(buf, len); + wpabuf_put_data(buf, pos, len); + pos += len; + left -= len; + } + } + + /* TODO: FILS IP Address Assignment */ + +#ifdef CONFIG_OCV + if (wpa_sm_ocv_enabled(sm)) { + struct wpa_channel_info ci; + u8 *pos; + + if (wpa_sm_channel_info(sm, &ci) != 0) { + wpa_printf(MSG_WARNING, + "FILS: Failed to get channel info for OCI element"); + wpabuf_free(buf); + return NULL; + } + + pos = wpabuf_put(buf, OCV_OCI_EXTENDED_LEN); + if (ocv_insert_extended_oci(&ci, pos) < 0) { + wpabuf_free(buf); + return NULL; + } + } +#endif /* CONFIG_OCV */ + + wpa_hexdump_buf(MSG_DEBUG, "FILS: Association Request plaintext", buf); + + *kek = sm->ptk.kek; + *kek_len = sm->ptk.kek_len; + wpa_hexdump_key(MSG_DEBUG, "FILS: KEK for AEAD", *kek, *kek_len); + *snonce = sm->fils_nonce; + wpa_hexdump(MSG_DEBUG, "FILS: SNonce for AEAD AAD", + *snonce, FILS_NONCE_LEN); + *anonce = sm->fils_anonce; + wpa_hexdump(MSG_DEBUG, "FILS: ANonce for AEAD AAD", + *anonce, FILS_NONCE_LEN); + + return buf; +} + + +static void fils_process_hlp_resp(struct wpa_sm *sm, const u8 *resp, size_t len) +{ + const u8 *pos, *end; + + wpa_hexdump(MSG_MSGDUMP, "FILS: HLP response", resp, len); + if (len < 2 * ETH_ALEN) + return; + pos = resp + 2 * ETH_ALEN; + end = resp + len; + if (end - pos >= 6 && + os_memcmp(pos, "\xaa\xaa\x03\x00\x00\x00", 6) == 0) + pos += 6; /* Remove SNAP/LLC header */ + wpa_sm_fils_hlp_rx(sm, resp, resp + ETH_ALEN, pos, end - pos); +} + + +static void fils_process_hlp_container(struct wpa_sm *sm, const u8 *pos, + size_t len) +{ + const u8 *end = pos + len; + u8 *tmp, *tmp_pos; + + /* Check if there are any FILS HLP Container elements */ + while (end - pos >= 2) { + if (2 + pos[1] > end - pos) + return; + if (pos[0] == WLAN_EID_EXTENSION && + pos[1] >= 1 + 2 * ETH_ALEN && + pos[2] == WLAN_EID_EXT_FILS_HLP_CONTAINER) + break; + pos += 2 + pos[1]; + } + if (end - pos < 2) + return; /* No FILS HLP Container elements */ + + tmp = os_malloc(end - pos); + if (!tmp) + return; + + while (end - pos >= 2) { + if (2 + pos[1] > end - pos || + pos[0] != WLAN_EID_EXTENSION || + pos[1] < 1 + 2 * ETH_ALEN || + pos[2] != WLAN_EID_EXT_FILS_HLP_CONTAINER) + break; + tmp_pos = tmp; + os_memcpy(tmp_pos, pos + 3, pos[1] - 1); + tmp_pos += pos[1] - 1; + pos += 2 + pos[1]; + + /* Add possible fragments */ + while (end - pos >= 2 && pos[0] == WLAN_EID_FRAGMENT && + 2 + pos[1] <= end - pos) { + os_memcpy(tmp_pos, pos + 2, pos[1]); + tmp_pos += pos[1]; + pos += 2 + pos[1]; + } + + fils_process_hlp_resp(sm, tmp, tmp_pos - tmp); + } + + os_free(tmp); +} + + +int fils_process_assoc_resp(struct wpa_sm *sm, const u8 *resp, size_t len) +{ + 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; + + if (!sm || !sm->ptk_set) { + wpa_printf(MSG_DEBUG, "FILS: No KEK available"); + return -1; + } + + if (!wpa_key_mgmt_fils(sm->key_mgmt)) { + wpa_printf(MSG_DEBUG, "FILS: Not a FILS AKM"); + return -1; + } + + if (sm->fils_completed) { + wpa_printf(MSG_DEBUG, + "FILS: Association has already been completed for this FILS authentication - ignore unexpected retransmission"); + return -1; + } + + wpa_hexdump(MSG_DEBUG, "FILS: (Re)Association Response frame", + resp, len); + + mgmt = (const struct ieee80211_mgmt *) resp; + if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.assoc_resp)) + return -1; + + end = resp + len; + /* Same offset for Association Response and Reassociation Response */ + ie_start = mgmt->u.assoc_resp.variable; + + if (ieee802_11_parse_elems(ie_start, end - ie_start, &elems, 1) == + ParseFailed) { + wpa_printf(MSG_DEBUG, + "FILS: Failed to parse decrypted elements"); + goto fail; + } + + if (!elems.fils_session) { + wpa_printf(MSG_DEBUG, "FILS: No FILS Session element"); + return -1; + } + if (os_memcmp(elems.fils_session, sm->fils_session, + FILS_SESSION_LEN) != 0) { + wpa_printf(MSG_DEBUG, "FILS: FILS Session mismatch"); + wpa_hexdump(MSG_DEBUG, "FILS: Received FILS Session", + elems.fils_session, FILS_SESSION_LEN); + wpa_hexdump(MSG_DEBUG, "FILS: Expected FILS Session", + sm->fils_session, FILS_SESSION_LEN); + } + + /* TODO: FILS Public Key */ + + if (!elems.fils_key_confirm) { + wpa_printf(MSG_DEBUG, "FILS: No FILS Key Confirm element"); + goto fail; + } + if (elems.fils_key_confirm_len != sm->fils_key_auth_len) { + wpa_printf(MSG_DEBUG, + "FILS: Unexpected Key-Auth length %d (expected %d)", + elems.fils_key_confirm_len, + (int) sm->fils_key_auth_len); + goto fail; + } + if (os_memcmp(elems.fils_key_confirm, sm->fils_key_auth_ap, + sm->fils_key_auth_len) != 0) { + wpa_printf(MSG_DEBUG, "FILS: Key-Auth mismatch"); + wpa_hexdump(MSG_DEBUG, "FILS: Received Key-Auth", + elems.fils_key_confirm, + elems.fils_key_confirm_len); + wpa_hexdump(MSG_DEBUG, "FILS: Expected Key-Auth", + sm->fils_key_auth_ap, sm->fils_key_auth_len); + goto fail; + } + +#ifdef CONFIG_OCV + if (wpa_sm_ocv_enabled(sm)) { + struct wpa_channel_info ci; + + if (wpa_sm_channel_info(sm, &ci) != 0) { + wpa_printf(MSG_WARNING, + "Failed to get channel info to validate received OCI in FILS (Re)Association Response frame"); + goto fail; + } + + if (ocv_verify_tx_params(elems.oci, elems.oci_len, &ci, + channel_width_to_int(ci.chanwidth), + ci.seg1_idx) != 0) { + wpa_printf(MSG_WARNING, "FILS: %s", ocv_errorstr); + goto fail; + } + } +#endif /* CONFIG_OCV */ + +#ifdef CONFIG_IEEE80211R + if (wpa_key_mgmt_ft(sm->key_mgmt) && sm->fils_ft_ies) { + struct wpa_ie_data rsn; + + /* Check that PMKR1Name derived by the AP matches */ + if (!elems.rsn_ie || + wpa_parse_wpa_ie_rsn(elems.rsn_ie - 2, elems.rsn_ie_len + 2, + &rsn) < 0 || + !rsn.pmkid || rsn.num_pmkid != 1 || + os_memcmp(rsn.pmkid, sm->pmk_r1_name, + WPA_PMK_NAME_LEN) != 0) { + wpa_printf(MSG_DEBUG, + "FILS+FT: No RSNE[PMKR1Name] match in AssocResp"); + goto fail; + } + } +#endif /* CONFIG_IEEE80211R */ + + /* Key Delivery */ + if (!elems.key_delivery) { + wpa_printf(MSG_DEBUG, "FILS: No Key Delivery element"); + goto fail; + } + + /* Parse GTK and set the key to the driver */ + os_memset(&gd, 0, sizeof(gd)); + if (wpa_supplicant_parse_ies(elems.key_delivery + WPA_KEY_RSC_LEN, + elems.key_delivery_len - WPA_KEY_RSC_LEN, + &kde) < 0) { + wpa_printf(MSG_DEBUG, "FILS: Failed to parse KDEs"); + goto fail; + } + if (!kde.gtk) { + wpa_printf(MSG_DEBUG, "FILS: No GTK KDE"); + goto fail; + } + maxkeylen = gd.gtk_len = kde.gtk_len - 2; + if (wpa_supplicant_check_group_cipher(sm, sm->group_cipher, + gd.gtk_len, maxkeylen, + &gd.key_rsc_len, &gd.alg)) + goto fail; + + wpa_hexdump_key(MSG_DEBUG, "FILS: Received GTK", kde.gtk, kde.gtk_len); + gd.keyidx = kde.gtk[0] & 0x3; + gd.tx = wpa_supplicant_gtk_tx_bit_workaround(sm, + !!(kde.gtk[0] & BIT(2))); + if (kde.gtk_len - 2 > sizeof(gd.gtk)) { + wpa_printf(MSG_DEBUG, "FILS: Too long GTK in GTK KDE (len=%lu)", + (unsigned long) kde.gtk_len - 2); + goto fail; + } + os_memcpy(gd.gtk, kde.gtk + 2, kde.gtk_len - 2); + + wpa_printf(MSG_DEBUG, "FILS: Set GTK to driver"); + if (wpa_supplicant_install_gtk(sm, &gd, elems.key_delivery, 0) < 0) { + wpa_printf(MSG_DEBUG, "FILS: Failed to set GTK"); + goto fail; + } + + if (ieee80211w_set_keys(sm, &kde) < 0) { + wpa_printf(MSG_DEBUG, "FILS: Failed to set IGTK"); + 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); + goto fail; + } + rsclen = wpa_cipher_rsc_len(sm->pairwise_cipher); + 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) { + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, + "FILS: Failed to set PTK to the driver (alg=%d keylen=%d bssid=" + MACSTR ")", + alg, keylen, MAC2STR(sm->bssid)); + goto fail; + } + + /* TODO: TK could be cleared after auth frame exchange now that driver + * takes care of association frame encryption/decryption. */ + /* TK is not needed anymore in supplicant */ + os_memset(sm->ptk.tk, 0, WPA_TK_MAX_LEN); + sm->ptk.tk_len = 0; + sm->ptk.installed = 1; + + /* FILS HLP Container */ + fils_process_hlp_container(sm, ie_start, end - ie_start); + + /* TODO: FILS IP Address Assignment */ + + wpa_printf(MSG_DEBUG, "FILS: Auth+Assoc completed successfully"); + sm->fils_completed = 1; + + return 0; +fail: + return -1; +} + + +void wpa_sm_set_reset_fils_completed(struct wpa_sm *sm, int set) +{ + if (sm) + sm->fils_completed = !!set; +} + +#endif /* CONFIG_FILS */ + + +int wpa_fils_is_completed(struct wpa_sm *sm) +{ +#ifdef CONFIG_FILS + return sm && sm->fils_completed; +#else /* CONFIG_FILS */ + return 0; +#endif /* CONFIG_FILS */ +} + + +#ifdef CONFIG_OWE + +struct wpabuf * owe_build_assoc_req(struct wpa_sm *sm, u16 group) +{ + struct wpabuf *ie = NULL, *pub = NULL; + size_t prime_len; + + if (group == 19) + prime_len = 32; + else if (group == 20) + prime_len = 48; + else if (group == 21) + prime_len = 66; + else + return NULL; + + crypto_ecdh_deinit(sm->owe_ecdh); + sm->owe_ecdh = crypto_ecdh_init(group); + if (!sm->owe_ecdh) + goto fail; + sm->owe_group = group; + pub = crypto_ecdh_get_pubkey(sm->owe_ecdh, 0); + pub = wpabuf_zeropad(pub, prime_len); + if (!pub) + goto fail; + + ie = wpabuf_alloc(5 + wpabuf_len(pub)); + if (!ie) + goto fail; + wpabuf_put_u8(ie, WLAN_EID_EXTENSION); + wpabuf_put_u8(ie, 1 + 2 + wpabuf_len(pub)); + wpabuf_put_u8(ie, WLAN_EID_EXT_OWE_DH_PARAM); + wpabuf_put_le16(ie, group); + wpabuf_put_buf(ie, pub); + wpabuf_free(pub); + wpa_hexdump_buf(MSG_DEBUG, "OWE: Diffie-Hellman Parameter element", + ie); + + return ie; +fail: + wpabuf_free(pub); + crypto_ecdh_deinit(sm->owe_ecdh); + sm->owe_ecdh = NULL; + return NULL; +} + + +int owe_process_assoc_resp(struct wpa_sm *sm, const u8 *bssid, + const u8 *resp_ies, size_t resp_ies_len) +{ + struct ieee802_11_elems elems; + u16 group; + struct wpabuf *secret, *pub, *hkey; + int res; + u8 prk[SHA512_MAC_LEN], pmkid[SHA512_MAC_LEN]; + const char *info = "OWE Key Generation"; + const u8 *addr[2]; + size_t len[2]; + size_t hash_len, prime_len; + struct wpa_ie_data data; + + if (!resp_ies || + ieee802_11_parse_elems(resp_ies, resp_ies_len, &elems, 1) == + ParseFailed) { + wpa_printf(MSG_INFO, + "OWE: Could not parse Association Response frame elements"); + return -1; + } + + if (sm->cur_pmksa && elems.rsn_ie && + wpa_parse_wpa_ie_rsn(elems.rsn_ie - 2, 2 + elems.rsn_ie_len, + &data) == 0 && + data.num_pmkid == 1 && data.pmkid && + os_memcmp(sm->cur_pmksa->pmkid, data.pmkid, PMKID_LEN) == 0) { + wpa_printf(MSG_DEBUG, "OWE: Use PMKSA caching"); + wpa_sm_set_pmk_from_pmksa(sm); + return 0; + } + + if (!elems.owe_dh) { + wpa_printf(MSG_INFO, + "OWE: No Diffie-Hellman Parameter element found in Association Response frame"); + return -1; + } + + group = WPA_GET_LE16(elems.owe_dh); + if (group != sm->owe_group) { + wpa_printf(MSG_INFO, + "OWE: Unexpected Diffie-Hellman group in response: %u", + group); + return -1; + } + + if (!sm->owe_ecdh) { + wpa_printf(MSG_INFO, "OWE: No ECDH state available"); + return -1; + } + + if (group == 19) + prime_len = 32; + else if (group == 20) + prime_len = 48; + else if (group == 21) + prime_len = 66; + else + return -1; + + secret = crypto_ecdh_set_peerkey(sm->owe_ecdh, 0, + elems.owe_dh + 2, + elems.owe_dh_len - 2); + secret = wpabuf_zeropad(secret, prime_len); + if (!secret) { + wpa_printf(MSG_DEBUG, "OWE: Invalid peer DH public key"); + return -1; + } + wpa_hexdump_buf_key(MSG_DEBUG, "OWE: DH shared secret", secret); + + /* prk = HKDF-extract(C | A | group, z) */ + + pub = crypto_ecdh_get_pubkey(sm->owe_ecdh, 0); + if (!pub) { + wpabuf_clear_free(secret); + return -1; + } + + /* PMKID = Truncate-128(Hash(C | A)) */ + addr[0] = wpabuf_head(pub); + len[0] = wpabuf_len(pub); + addr[1] = elems.owe_dh + 2; + len[1] = elems.owe_dh_len - 2; + if (group == 19) { + res = sha256_vector(2, addr, len, pmkid); + hash_len = SHA256_MAC_LEN; + } else if (group == 20) { + res = sha384_vector(2, addr, len, pmkid); + hash_len = SHA384_MAC_LEN; + } else if (group == 21) { + res = sha512_vector(2, addr, len, pmkid); + hash_len = SHA512_MAC_LEN; + } else { + res = -1; + hash_len = 0; + } + pub = wpabuf_zeropad(pub, prime_len); + if (res < 0 || !pub) { + wpabuf_free(pub); + wpabuf_clear_free(secret); + return -1; + } + + hkey = wpabuf_alloc(wpabuf_len(pub) + elems.owe_dh_len - 2 + 2); + if (!hkey) { + wpabuf_free(pub); + wpabuf_clear_free(secret); + return -1; + } + + wpabuf_put_buf(hkey, pub); /* C */ + wpabuf_free(pub); + wpabuf_put_data(hkey, elems.owe_dh + 2, elems.owe_dh_len - 2); /* A */ + wpabuf_put_le16(hkey, sm->owe_group); /* group */ + if (group == 19) + res = hmac_sha256(wpabuf_head(hkey), wpabuf_len(hkey), + wpabuf_head(secret), wpabuf_len(secret), prk); + else if (group == 20) + res = hmac_sha384(wpabuf_head(hkey), wpabuf_len(hkey), + wpabuf_head(secret), wpabuf_len(secret), prk); + else if (group == 21) + res = hmac_sha512(wpabuf_head(hkey), wpabuf_len(hkey), + wpabuf_head(secret), wpabuf_len(secret), prk); + wpabuf_clear_free(hkey); + wpabuf_clear_free(secret); + if (res < 0) + return -1; + + wpa_hexdump_key(MSG_DEBUG, "OWE: prk", prk, hash_len); + + /* PMK = HKDF-expand(prk, "OWE Key Generation", n) */ + + if (group == 19) + res = hmac_sha256_kdf(prk, hash_len, NULL, (const u8 *) info, + os_strlen(info), sm->pmk, hash_len); + else if (group == 20) + res = hmac_sha384_kdf(prk, hash_len, NULL, (const u8 *) info, + os_strlen(info), sm->pmk, hash_len); + else if (group == 21) + res = hmac_sha512_kdf(prk, hash_len, NULL, (const u8 *) info, + os_strlen(info), sm->pmk, hash_len); + os_memset(prk, 0, SHA512_MAC_LEN); + if (res < 0) { + sm->pmk_len = 0; + return -1; + } + sm->pmk_len = hash_len; + + wpa_hexdump_key(MSG_DEBUG, "OWE: PMK", sm->pmk, sm->pmk_len); + wpa_hexdump(MSG_DEBUG, "OWE: PMKID", pmkid, PMKID_LEN); + pmksa_cache_add(sm->pmksa, sm->pmk, sm->pmk_len, pmkid, NULL, 0, + bssid, sm->own_addr, sm->network_ctx, sm->key_mgmt, + NULL); + + return 0; +} + +#endif /* CONFIG_OWE */ + + +void wpa_sm_set_fils_cache_id(struct wpa_sm *sm, const u8 *fils_cache_id) +{ +#ifdef CONFIG_FILS + if (sm && fils_cache_id) { + sm->fils_cache_id_set = 1; + os_memcpy(sm->fils_cache_id, fils_cache_id, FILS_CACHE_ID_LEN); + } +#endif /* CONFIG_FILS */ +} + + +#ifdef CONFIG_DPP2 +void wpa_sm_set_dpp_z(struct wpa_sm *sm, const struct wpabuf *z) +{ + if (sm) { + wpabuf_clear_free(sm->dpp_z); + sm->dpp_z = z ? wpabuf_dup(z) : NULL; + } +} +#endif /* CONFIG_DPP2 */ diff --git a/freebsd/contrib/wpa/src/rsn_supp/wpa.h b/freebsd/contrib/wpa/src/rsn_supp/wpa.h index 0b7477f3..8903f8e1 100644 --- a/freebsd/contrib/wpa/src/rsn_supp/wpa.h +++ b/freebsd/contrib/wpa/src/rsn_supp/wpa.h @@ -18,6 +18,7 @@ struct wpa_sm; struct eapol_sm; struct wpa_config_blob; struct hostapd_freq_params; +struct wpa_channel_info; struct wpa_sm_ctx { void *ctx; /* pointer to arbitrary upper level context */ @@ -25,7 +26,7 @@ struct wpa_sm_ctx { void (*set_state)(void *ctx, enum wpa_states state); enum wpa_states (*get_state)(void *ctx); - void (*deauthenticate)(void * ctx, int reason_code); + void (*deauthenticate)(void * ctx, int 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, @@ -38,8 +39,11 @@ struct wpa_sm_ctx { void (*cancel_auth_timeout)(void *ctx); u8 * (*alloc_eapol)(void *ctx, u8 type, const void *data, u16 data_len, size_t *msg_len, void **data_pos); - int (*add_pmkid)(void *ctx, const u8 *bssid, const u8 *pmkid); - int (*remove_pmkid)(void *ctx, const u8 *bssid, const u8 *pmkid); + int (*add_pmkid)(void *ctx, void *network_ctx, const u8 *bssid, + const u8 *pmkid, const u8 *fils_cache_id, + const u8 *pmk, size_t pmk_len); + int (*remove_pmkid)(void *ctx, void *network_ctx, const u8 *bssid, + const u8 *pmkid, const u8 *fils_cache_id); void (*set_config_blob)(void *ctx, struct wpa_config_blob *blob); const struct wpa_config_blob * (*get_config_blob)(void *ctx, const char *name); @@ -77,6 +81,9 @@ struct wpa_sm_ctx { const u8 *kck, size_t kck_len, const u8 *replay_ctr); int (*key_mgmt_set_pmk)(void *ctx, const u8 *pmk, size_t pmk_len); + void (*fils_hlp_rx)(void *ctx, const u8 *dst, const u8 *src, + const u8 *pkt, size_t pkt_len); + int (*channel_info)(void *ctx, struct wpa_channel_info *ci); }; @@ -90,12 +97,12 @@ enum wpa_sm_conf_params { WPA_PARAM_KEY_MGMT, WPA_PARAM_MGMT_GROUP, WPA_PARAM_RSN_ENABLED, - WPA_PARAM_MFP + WPA_PARAM_MFP, + WPA_PARAM_OCV }; struct rsn_supp_config { void *network_ctx; - int peerkey_enabled; int allowed_pairwise_cipher; /* bitfield of WPA_CIPHER_* */ int proactive_key_caching; int eap_workaround; @@ -105,6 +112,7 @@ struct rsn_supp_config { int wpa_ptk_rekey; int p2p; int wpa_rsc_relaxation; + const u8 *fils_cache_id; }; #ifndef CONFIG_NO_WPA @@ -136,6 +144,7 @@ int wpa_sm_set_param(struct wpa_sm *sm, enum wpa_sm_conf_params param, int wpa_sm_get_status(struct wpa_sm *sm, char *buf, size_t buflen, int verbose); int wpa_sm_pmf_enabled(struct wpa_sm *sm); +int wpa_sm_ocv_enabled(struct wpa_sm *sm); void wpa_sm_key_request(struct wpa_sm *sm, int error, int pairwise); @@ -147,6 +156,15 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr, const u8 *buf, size_t len); int wpa_sm_parse_own_wpa_ie(struct wpa_sm *sm, struct wpa_ie_data *data); int wpa_sm_pmksa_cache_list(struct wpa_sm *sm, char *buf, size_t len); +struct rsn_pmksa_cache_entry * wpa_sm_pmksa_cache_head(struct wpa_sm *sm); +struct rsn_pmksa_cache_entry * +wpa_sm_pmksa_cache_add_entry(struct wpa_sm *sm, + struct rsn_pmksa_cache_entry * entry); +void wpa_sm_pmksa_cache_add(struct wpa_sm *sm, const u8 *pmk, size_t pmk_len, + const u8 *pmkid, const u8 *bssid, + const u8 *fils_cache_id); +int wpa_sm_pmksa_exists(struct wpa_sm *sm, const u8 *bssid, + const void *network_ctx); void wpa_sm_drop_sa(struct wpa_sm *sm); int wpa_sm_has_ptk(struct wpa_sm *sm); @@ -160,6 +178,7 @@ void wpa_sm_set_rx_replay_ctr(struct wpa_sm *sm, const u8 *rx_replay_counter); void wpa_sm_set_ptk_kck_kek(struct wpa_sm *sm, const u8 *ptk_kck, size_t ptk_kck_len, const u8 *ptk_kek, size_t ptk_kek_len); +int wpa_fils_is_completed(struct wpa_sm *sm); #else /* CONFIG_NO_WPA */ @@ -264,6 +283,11 @@ static inline int wpa_sm_pmf_enabled(struct wpa_sm *sm) return 0; } +static inline int wpa_sm_ocv_enabled(struct wpa_sm *sm) +{ + return 0; +} + static inline void wpa_sm_key_request(struct wpa_sm *sm, int error, int pairwise) { @@ -327,29 +351,20 @@ static inline void wpa_sm_set_ptk_kck_kek(struct wpa_sm *sm, const u8 *ptk_kck, { } -#endif /* CONFIG_NO_WPA */ - -#ifdef CONFIG_PEERKEY -int wpa_sm_stkstart(struct wpa_sm *sm, const u8 *peer); -int wpa_sm_rx_eapol_peerkey(struct wpa_sm *sm, const u8 *src_addr, - const u8 *buf, size_t len); -#else /* CONFIG_PEERKEY */ -static inline int wpa_sm_stkstart(struct wpa_sm *sm, const u8 *peer) -{ - return -1; -} - -static inline int wpa_sm_rx_eapol_peerkey(struct wpa_sm *sm, const u8 *src_addr, - const u8 *buf, size_t len) +static inline int wpa_fils_is_completed(struct wpa_sm *sm) { return 0; } -#endif /* CONFIG_PEERKEY */ + +#endif /* CONFIG_NO_WPA */ #ifdef CONFIG_IEEE80211R int wpa_sm_set_ft_params(struct wpa_sm *sm, const u8 *ies, size_t ies_len); int wpa_ft_prepare_auth_request(struct wpa_sm *sm, const u8 *mdie); +int wpa_ft_add_mdie(struct wpa_sm *sm, u8 *ies, size_t ies_len, + const u8 *mdie); +const u8 * wpa_sm_get_ft_md(struct wpa_sm *sm); int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len, int ft_action, const u8 *target_ap, const u8 *ric_ies, size_t ric_ies_len); @@ -374,6 +389,12 @@ static inline int wpa_ft_prepare_auth_request(struct wpa_sm *sm, return 0; } +static inline int wpa_ft_add_mdie(struct wpa_sm *sm, u8 *ies, size_t ies_len, + const u8 *mdie) +{ + return 0; +} + static inline int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len, int ft_action, const u8 *target_ap) @@ -425,5 +446,25 @@ extern unsigned int tdls_testing; int wpa_wnmsleep_install_key(struct wpa_sm *sm, u8 subelem_id, u8 *buf); void wpa_sm_set_test_assoc_ie(struct wpa_sm *sm, struct wpabuf *buf); +const u8 * wpa_sm_get_anonce(struct wpa_sm *sm); +unsigned int wpa_sm_get_key_mgmt(struct wpa_sm *sm); + +struct wpabuf * fils_build_auth(struct wpa_sm *sm, int dh_group, const u8 *md); +int fils_process_auth(struct wpa_sm *sm, const u8 *bssid, const u8 *data, + size_t len); +struct wpabuf * fils_build_assoc_req(struct wpa_sm *sm, const u8 **kek, + size_t *kek_len, const u8 **snonce, + const u8 **anonce, + const struct wpabuf **hlp, + unsigned int num_hlp); +int fils_process_assoc_resp(struct wpa_sm *sm, const u8 *resp, size_t len); + +struct wpabuf * owe_build_assoc_req(struct wpa_sm *sm, u16 group); +int owe_process_assoc_resp(struct wpa_sm *sm, const u8 *bssid, + const u8 *resp_ies, size_t resp_ies_len); + +void wpa_sm_set_reset_fils_completed(struct wpa_sm *sm, int set); +void wpa_sm_set_fils_cache_id(struct wpa_sm *sm, const u8 *fils_cache_id); +void wpa_sm_set_dpp_z(struct wpa_sm *sm, const struct wpabuf *z); #endif /* WPA_H */ diff --git a/freebsd/contrib/wpa/src/rsn_supp/wpa_ft.c b/freebsd/contrib/wpa/src/rsn_supp/wpa_ft.c index ea5b419f..6738b05b 100644 --- a/freebsd/contrib/wpa/src/rsn_supp/wpa_ft.c +++ b/freebsd/contrib/wpa/src/rsn_supp/wpa_ft.c @@ -2,7 +2,7 @@ /* * WPA Supplicant - IEEE 802.11r - Fast BSS Transition - * Copyright (c) 2006-2015, Jouni Malinen <j@w1.fi> + * Copyright (c) 2006-2018, Jouni Malinen <j@w1.fi> * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -12,9 +12,12 @@ #include "common.h" #include "crypto/aes_wrap.h" +#include "crypto/sha384.h" #include "crypto/random.h" #include "common/ieee802_11_defs.h" #include "common/ieee802_11_common.h" +#include "common/ocv.h" +#include "drivers/driver.h" #include "wpa.h" #include "wpa_i.h" @@ -25,6 +28,7 @@ int wpa_derive_ptk_ft(struct wpa_sm *sm, const unsigned char *src_addr, { u8 ptk_name[WPA_PMK_NAME_LEN]; const u8 *anonce = key->key_nonce; + int use_sha384 = wpa_key_mgmt_sha384(sm->key_mgmt); if (sm->xxkey_len == 0) { wpa_printf(MSG_DEBUG, "FT: XXKey not available for key " @@ -32,21 +36,26 @@ int wpa_derive_ptk_ft(struct wpa_sm *sm, const unsigned char *src_addr, return -1; } - wpa_derive_pmk_r0(sm->xxkey, sm->xxkey_len, sm->ssid, - sm->ssid_len, sm->mobility_domain, - sm->r0kh_id, sm->r0kh_id_len, sm->own_addr, - sm->pmk_r0, sm->pmk_r0_name); - wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R0", sm->pmk_r0, PMK_LEN); + sm->pmk_r0_len = use_sha384 ? SHA384_MAC_LEN : PMK_LEN; + if (wpa_derive_pmk_r0(sm->xxkey, sm->xxkey_len, sm->ssid, + sm->ssid_len, sm->mobility_domain, + sm->r0kh_id, sm->r0kh_id_len, sm->own_addr, + sm->pmk_r0, sm->pmk_r0_name, use_sha384) < 0) + return -1; + wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R0", sm->pmk_r0, sm->pmk_r0_len); wpa_hexdump(MSG_DEBUG, "FT: PMKR0Name", sm->pmk_r0_name, WPA_PMK_NAME_LEN); - wpa_derive_pmk_r1(sm->pmk_r0, sm->pmk_r0_name, sm->r1kh_id, - sm->own_addr, sm->pmk_r1, sm->pmk_r1_name); - wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", sm->pmk_r1, PMK_LEN); + sm->pmk_r1_len = sm->pmk_r0_len; + if (wpa_derive_pmk_r1(sm->pmk_r0, sm->pmk_r0_len, sm->pmk_r0_name, + sm->r1kh_id, sm->own_addr, sm->pmk_r1, + sm->pmk_r1_name) < 0) + return -1; + wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", sm->pmk_r1, sm->pmk_r1_len); wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", sm->pmk_r1_name, WPA_PMK_NAME_LEN); - return wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->snonce, anonce, sm->own_addr, - sm->bssid, sm->pmk_r1_name, ptk, ptk_name, - sm->key_mgmt, sm->pairwise_cipher); + return wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->pmk_r1_len, sm->snonce, anonce, + sm->own_addr, sm->bssid, sm->pmk_r1_name, ptk, + ptk_name, sm->key_mgmt, sm->pairwise_cipher); } @@ -60,11 +69,13 @@ int wpa_derive_ptk_ft(struct wpa_sm *sm, const unsigned char *src_addr, int wpa_sm_set_ft_params(struct wpa_sm *sm, const u8 *ies, size_t ies_len) { struct wpa_ft_ies ft; + int use_sha384; if (sm == NULL) return 0; - if (wpa_ft_parse_ies(ies, ies_len, &ft) < 0) + use_sha384 = wpa_key_mgmt_sha384(sm->key_mgmt); + if (wpa_ft_parse_ies(ies, ies_len, &ft, use_sha384) < 0) return -1; if (ft.mdie && ft.mdie_len < MOBILITY_DOMAIN_ID_LEN + 1) @@ -148,16 +159,17 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len, const u8 *ap_mdie) { size_t buf_len; - u8 *buf, *pos, *ftie_len, *ftie_pos; + u8 *buf, *pos, *ftie_len, *ftie_pos, *fte_mic, *elem_count; struct rsn_mdie *mdie; - struct rsn_ftie *ftie; struct rsn_ie_hdr *rsnie; u16 capab; + int mdie_len; sm->ft_completed = 0; sm->ft_reassoc_completed = 0; - buf_len = 2 + sizeof(struct rsn_mdie) + 2 + sizeof(struct rsn_ftie) + + buf_len = 2 + sizeof(struct rsn_mdie) + 2 + + sizeof(struct rsn_ftie_sha384) + 2 + sm->r0kh_id_len + ric_ies_len + 100; buf = os_zalloc(buf_len); if (buf == NULL) @@ -203,10 +215,20 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len, /* Authenticated Key Management Suite List */ if (sm->key_mgmt == WPA_KEY_MGMT_FT_IEEE8021X) RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_802_1X); +#ifdef CONFIG_SHA384 + else if (sm->key_mgmt == WPA_KEY_MGMT_FT_IEEE8021X_SHA384) + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_802_1X_SHA384); +#endif /* CONFIG_SHA384 */ else if (sm->key_mgmt == WPA_KEY_MGMT_FT_PSK) RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_PSK); else if (sm->key_mgmt == WPA_KEY_MGMT_FT_SAE) RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_SAE); +#ifdef CONFIG_FILS + else if (sm->key_mgmt == WPA_KEY_MGMT_FT_FILS_SHA256) + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_FILS_SHA256); + else if (sm->key_mgmt == WPA_KEY_MGMT_FT_FILS_SHA384) + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_FILS_SHA384); +#endif /* CONFIG_FILS */ else { wpa_printf(MSG_WARNING, "FT: Invalid key management type (%d)", sm->key_mgmt); @@ -218,9 +240,14 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len, /* RSN Capabilities */ capab = 0; #ifdef CONFIG_IEEE80211W - if (sm->mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC) + if (sm->mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC || + sm->mgmt_group_cipher == WPA_CIPHER_BIP_GMAC_128 || + sm->mgmt_group_cipher == WPA_CIPHER_BIP_GMAC_256 || + sm->mgmt_group_cipher == WPA_CIPHER_BIP_CMAC_256) capab |= WPA_CAPABILITY_MFPC; #endif /* CONFIG_IEEE80211W */ + if (sm->ocv) + capab |= WPA_CAPABILITY_OCVC; WPA_PUT_LE16(pos, capab); pos += 2; @@ -233,34 +260,63 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len, pos += WPA_PMK_NAME_LEN; #ifdef CONFIG_IEEE80211W - if (sm->mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC) { - /* Management Group Cipher Suite */ + /* Management Group Cipher Suite */ + switch (sm->mgmt_group_cipher) { + case WPA_CIPHER_AES_128_CMAC: RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC); pos += RSN_SELECTOR_LEN; + break; + case WPA_CIPHER_BIP_GMAC_128: + RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_BIP_GMAC_128); + pos += RSN_SELECTOR_LEN; + break; + case WPA_CIPHER_BIP_GMAC_256: + RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_BIP_GMAC_256); + pos += RSN_SELECTOR_LEN; + break; + case WPA_CIPHER_BIP_CMAC_256: + RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_BIP_CMAC_256); + pos += RSN_SELECTOR_LEN; + break; } #endif /* CONFIG_IEEE80211W */ rsnie->len = (pos - (u8 *) rsnie) - 2; /* MDIE */ - *pos++ = WLAN_EID_MOBILITY_DOMAIN; - *pos++ = sizeof(*mdie); - mdie = (struct rsn_mdie *) pos; - pos += sizeof(*mdie); - os_memcpy(mdie->mobility_domain, sm->mobility_domain, - MOBILITY_DOMAIN_ID_LEN); - mdie->ft_capab = ap_mdie && ap_mdie[1] >= 3 ? ap_mdie[4] : - sm->mdie_ft_capab; + mdie_len = wpa_ft_add_mdie(sm, pos, buf_len - (pos - buf), ap_mdie); + if (mdie_len <= 0) { + os_free(buf); + return NULL; + } + mdie = (struct rsn_mdie *) (pos + 2); + pos += mdie_len; /* FTIE[SNonce, [R1KH-ID,] R0KH-ID ] */ ftie_pos = pos; *pos++ = WLAN_EID_FAST_BSS_TRANSITION; ftie_len = pos++; - ftie = (struct rsn_ftie *) pos; - pos += sizeof(*ftie); - os_memcpy(ftie->snonce, sm->snonce, WPA_NONCE_LEN); - if (anonce) - os_memcpy(ftie->anonce, anonce, WPA_NONCE_LEN); + if (wpa_key_mgmt_sha384(sm->key_mgmt)) { + struct rsn_ftie_sha384 *ftie; + + ftie = (struct rsn_ftie_sha384 *) pos; + fte_mic = ftie->mic; + elem_count = &ftie->mic_control[1]; + pos += sizeof(*ftie); + os_memcpy(ftie->snonce, sm->snonce, WPA_NONCE_LEN); + if (anonce) + os_memcpy(ftie->anonce, anonce, WPA_NONCE_LEN); + } else { + struct rsn_ftie *ftie; + + ftie = (struct rsn_ftie *) pos; + fte_mic = ftie->mic; + elem_count = &ftie->mic_control[1]; + pos += sizeof(*ftie); + os_memcpy(ftie->snonce, sm->snonce, WPA_NONCE_LEN); + if (anonce) + os_memcpy(ftie->anonce, anonce, WPA_NONCE_LEN); + } if (kck) { /* R1KH-ID sub-element in third FT message */ *pos++ = FTIE_SUBELEM_R1KH_ID; @@ -273,6 +329,26 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len, *pos++ = sm->r0kh_id_len; os_memcpy(pos, sm->r0kh_id, sm->r0kh_id_len); pos += sm->r0kh_id_len; +#ifdef CONFIG_OCV + if (kck && wpa_sm_ocv_enabled(sm)) { + /* OCI sub-element in the third FT message */ + struct wpa_channel_info ci; + + if (wpa_sm_channel_info(sm, &ci) != 0) { + wpa_printf(MSG_WARNING, + "Failed to get channel info for OCI element in FTE"); + os_free(buf); + return NULL; + } + + *pos++ = FTIE_SUBELEM_OCI; + *pos++ = OCV_OCI_LEN; + if (ocv_insert_oci(&ci, &pos) < 0) { + os_free(buf); + return NULL; + } + } +#endif /* CONFIG_OCV */ *ftie_len = pos - ftie_len - 1; if (ric_ies) { @@ -294,13 +370,12 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len, * RIC-Request (if present) */ /* Information element count */ - ftie->mic_control[1] = 3 + ieee802_11_ie_count(ric_ies, - ric_ies_len); + *elem_count = 3 + ieee802_11_ie_count(ric_ies, ric_ies_len); if (wpa_ft_mic(kck, kck_len, sm->own_addr, target_ap, 5, ((u8 *) mdie) - 2, 2 + sizeof(*mdie), ftie_pos, 2 + *ftie_len, (u8 *) rsnie, 2 + rsnie->len, ric_ies, - ric_ies_len, ftie->mic) < 0) { + ric_ies_len, fte_mic) < 0) { wpa_printf(MSG_INFO, "FT: Failed to calculate MIC"); os_free(buf); return NULL; @@ -369,6 +444,37 @@ int wpa_ft_prepare_auth_request(struct wpa_sm *sm, const u8 *mdie) } +int wpa_ft_add_mdie(struct wpa_sm *sm, u8 *buf, size_t buf_len, + const u8 *ap_mdie) +{ + u8 *pos = buf; + struct rsn_mdie *mdie; + + if (buf_len < 2 + sizeof(*mdie)) { + wpa_printf(MSG_INFO, + "FT: Failed to add MDIE: short buffer, length=%zu", + buf_len); + return 0; + } + + *pos++ = WLAN_EID_MOBILITY_DOMAIN; + *pos++ = sizeof(*mdie); + mdie = (struct rsn_mdie *) pos; + os_memcpy(mdie->mobility_domain, sm->mobility_domain, + MOBILITY_DOMAIN_ID_LEN); + mdie->ft_capab = ap_mdie && ap_mdie[1] >= 3 ? ap_mdie[4] : + sm->mdie_ft_capab; + + return 2 + sizeof(*mdie); +} + + +const u8 * wpa_sm_get_ft_md(struct wpa_sm *sm) +{ + return sm->mobility_domain; +} + + int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len, int ft_action, const u8 *target_ap, const u8 *ric_ies, size_t ric_ies_len) @@ -377,10 +483,13 @@ int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len, size_t ft_ies_len; struct wpa_ft_ies parse; struct rsn_mdie *mdie; - struct rsn_ftie *ftie; u8 ptk_name[WPA_PMK_NAME_LEN]; int ret; const u8 *bssid; + const u8 *kck; + size_t kck_len; + int use_sha384 = wpa_key_mgmt_sha384(sm->key_mgmt); + const u8 *anonce, *snonce; wpa_hexdump(MSG_DEBUG, "FT: Response IEs", ies, ies_len); wpa_hexdump(MSG_DEBUG, "FT: RIC IEs", ric_ies, ric_ies_len); @@ -406,7 +515,7 @@ int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len, return -1; } - if (wpa_ft_parse_ies(ies, ies_len, &parse) < 0) { + if (wpa_ft_parse_ies(ies, ies_len, &parse, use_sha384) < 0) { wpa_printf(MSG_DEBUG, "FT: Failed to parse IEs"); return -1; } @@ -419,16 +528,34 @@ int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len, return -1; } - ftie = (struct rsn_ftie *) parse.ftie; - if (ftie == NULL || parse.ftie_len < sizeof(*ftie)) { - wpa_printf(MSG_DEBUG, "FT: Invalid FTIE"); - return -1; + if (use_sha384) { + struct rsn_ftie_sha384 *ftie; + + ftie = (struct rsn_ftie_sha384 *) parse.ftie; + if (!ftie || parse.ftie_len < sizeof(*ftie)) { + wpa_printf(MSG_DEBUG, "FT: Invalid FTIE"); + return -1; + } + + anonce = ftie->anonce; + snonce = ftie->snonce; + } else { + struct rsn_ftie *ftie; + + ftie = (struct rsn_ftie *) parse.ftie; + if (!ftie || parse.ftie_len < sizeof(*ftie)) { + wpa_printf(MSG_DEBUG, "FT: Invalid FTIE"); + return -1; + } + + anonce = ftie->anonce; + snonce = ftie->snonce; } - if (os_memcmp(ftie->snonce, sm->snonce, WPA_NONCE_LEN) != 0) { + if (os_memcmp(snonce, sm->snonce, WPA_NONCE_LEN) != 0) { wpa_printf(MSG_DEBUG, "FT: SNonce mismatch in FTIE"); wpa_hexdump(MSG_DEBUG, "FT: Received SNonce", - ftie->snonce, WPA_NONCE_LEN); + snonce, WPA_NONCE_LEN); wpa_hexdump(MSG_DEBUG, "FT: Expected SNonce", sm->snonce, WPA_NONCE_LEN); return -1; @@ -467,23 +594,34 @@ int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len, os_memcpy(sm->r1kh_id, parse.r1kh_id, FT_R1KH_ID_LEN); wpa_hexdump(MSG_DEBUG, "FT: R1KH-ID", sm->r1kh_id, FT_R1KH_ID_LEN); wpa_hexdump(MSG_DEBUG, "FT: SNonce", sm->snonce, WPA_NONCE_LEN); - wpa_hexdump(MSG_DEBUG, "FT: ANonce", ftie->anonce, WPA_NONCE_LEN); - os_memcpy(sm->anonce, ftie->anonce, WPA_NONCE_LEN); - wpa_derive_pmk_r1(sm->pmk_r0, sm->pmk_r0_name, sm->r1kh_id, - sm->own_addr, sm->pmk_r1, sm->pmk_r1_name); - wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", sm->pmk_r1, PMK_LEN); + wpa_hexdump(MSG_DEBUG, "FT: ANonce", anonce, WPA_NONCE_LEN); + os_memcpy(sm->anonce, anonce, WPA_NONCE_LEN); + if (wpa_derive_pmk_r1(sm->pmk_r0, sm->pmk_r0_len, sm->pmk_r0_name, + sm->r1kh_id, sm->own_addr, sm->pmk_r1, + sm->pmk_r1_name) < 0) + return -1; + sm->pmk_r1_len = sm->pmk_r0_len; + wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", sm->pmk_r1, sm->pmk_r1_len); wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", sm->pmk_r1_name, WPA_PMK_NAME_LEN); bssid = target_ap; - if (wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->snonce, ftie->anonce, - sm->own_addr, bssid, sm->pmk_r1_name, &sm->ptk, - ptk_name, sm->key_mgmt, sm->pairwise_cipher) < 0) + if (wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->pmk_r1_len, sm->snonce, + anonce, sm->own_addr, bssid, + sm->pmk_r1_name, &sm->ptk, ptk_name, sm->key_mgmt, + sm->pairwise_cipher) < 0) return -1; - ft_ies = wpa_ft_gen_req_ies(sm, &ft_ies_len, ftie->anonce, + if (wpa_key_mgmt_fils(sm->key_mgmt)) { + kck = sm->ptk.kck2; + kck_len = sm->ptk.kck2_len; + } else { + kck = sm->ptk.kck; + kck_len = sm->ptk.kck_len; + } + ft_ies = wpa_ft_gen_req_ies(sm, &ft_ies_len, anonce, sm->pmk_r1_name, - sm->ptk.kck, sm->ptk.kck_len, bssid, + kck, kck_len, bssid, ric_ies, ric_ies_len, parse.mdie ? parse.mdie - 2 : NULL); if (ft_ies) { @@ -546,6 +684,16 @@ static int wpa_ft_process_gtk_subelem(struct wpa_sm *sm, const u8 *gtk_elem, int keyidx; enum wpa_alg alg; size_t gtk_len, keylen, rsc_len; + const u8 *kek; + size_t kek_len; + + if (wpa_key_mgmt_fils(sm->key_mgmt)) { + kek = sm->ptk.kek2; + kek_len = sm->ptk.kek2_len; + } else { + kek = sm->ptk.kek; + kek_len = sm->ptk.kek_len; + } if (gtk_elem == NULL) { wpa_printf(MSG_DEBUG, "FT: No GTK included in FTIE"); @@ -562,8 +710,7 @@ static int wpa_ft_process_gtk_subelem(struct wpa_sm *sm, const u8 *gtk_elem, return -1; } gtk_len = gtk_elem_len - 19; - if (aes_unwrap(sm->ptk.kek, sm->ptk.kek_len, gtk_len / 8, gtk_elem + 11, - gtk)) { + if (aes_unwrap(kek, kek_len, gtk_len / 8, gtk_elem + 11, gtk)) { wpa_printf(MSG_WARNING, "FT: AES unwrap failed - could not " "decrypt GTK"); return -1; @@ -617,10 +764,24 @@ 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) { - u8 igtk[WPA_IGTK_LEN]; + u8 igtk[WPA_IGTK_MAX_LEN]; + size_t igtk_len; u16 keyidx; + const u8 *kek; + size_t kek_len; + + if (wpa_key_mgmt_fils(sm->key_mgmt)) { + kek = sm->ptk.kek2; + kek_len = sm->ptk.kek2_len; + } else { + kek = sm->ptk.kek; + kek_len = sm->ptk.kek_len; + } - if (sm->mgmt_group_cipher != WPA_CIPHER_AES_128_CMAC) + if (sm->mgmt_group_cipher != WPA_CIPHER_AES_128_CMAC && + sm->mgmt_group_cipher != WPA_CIPHER_BIP_GMAC_128 && + sm->mgmt_group_cipher != WPA_CIPHER_BIP_GMAC_256 && + sm->mgmt_group_cipher != WPA_CIPHER_BIP_CMAC_256) return 0; if (igtk_elem == NULL) { @@ -631,19 +792,19 @@ 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); - if (igtk_elem_len != 2 + 6 + 1 + WPA_IGTK_LEN + 8) { + igtk_len = wpa_cipher_key_len(sm->mgmt_group_cipher); + if (igtk_elem_len != 2 + 6 + 1 + igtk_len + 8) { wpa_printf(MSG_DEBUG, "FT: Invalid IGTK sub-elem " "length %lu", (unsigned long) igtk_elem_len); return -1; } - if (igtk_elem[8] != WPA_IGTK_LEN) { + if (igtk_elem[8] != igtk_len) { wpa_printf(MSG_DEBUG, "FT: Invalid IGTK sub-elem Key Length " "%d", igtk_elem[8]); return -1; } - if (aes_unwrap(sm->ptk.kek, sm->ptk.kek_len, WPA_IGTK_LEN / 8, - igtk_elem + 9, igtk)) { + if (aes_unwrap(kek, kek_len, igtk_len / 8, igtk_elem + 9, igtk)) { wpa_printf(MSG_WARNING, "FT: AES unwrap failed - could not " "decrypt IGTK"); return -1; @@ -654,13 +815,16 @@ static int wpa_ft_process_igtk_subelem(struct wpa_sm *sm, const u8 *igtk_elem, keyidx = WPA_GET_LE16(igtk_elem); wpa_hexdump_key(MSG_DEBUG, "FT: IGTK from Reassoc Resp", igtk, - WPA_IGTK_LEN); - if (wpa_sm_set_key(sm, WPA_ALG_IGTK, broadcast_ether_addr, keyidx, 0, - igtk_elem + 2, 6, igtk, WPA_IGTK_LEN) < 0) { + 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) { wpa_printf(MSG_WARNING, "WPA: Failed to set IGTK to the " "driver."); + os_memset(igtk, 0, sizeof(igtk)); return -1; } + os_memset(igtk, 0, sizeof(igtk)); return 0; } @@ -672,9 +836,13 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, { struct wpa_ft_ies parse; struct rsn_mdie *mdie; - struct rsn_ftie *ftie; unsigned int count; u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN]; + const u8 *kck; + size_t kck_len; + int use_sha384 = wpa_key_mgmt_sha384(sm->key_mgmt); + const u8 *anonce, *snonce, *fte_mic; + u8 fte_elem_count; wpa_hexdump(MSG_DEBUG, "FT: Response IEs", ies, ies_len); @@ -689,7 +857,7 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, return 0; } - if (wpa_ft_parse_ies(ies, ies_len, &parse) < 0) { + if (wpa_ft_parse_ies(ies, ies_len, &parse, use_sha384) < 0) { wpa_printf(MSG_DEBUG, "FT: Failed to parse IEs"); return -1; } @@ -702,25 +870,47 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, return -1; } - ftie = (struct rsn_ftie *) parse.ftie; - if (ftie == NULL || parse.ftie_len < sizeof(*ftie)) { - wpa_printf(MSG_DEBUG, "FT: Invalid FTIE"); - return -1; + if (use_sha384) { + struct rsn_ftie_sha384 *ftie; + + ftie = (struct rsn_ftie_sha384 *) parse.ftie; + if (!ftie || parse.ftie_len < sizeof(*ftie)) { + wpa_printf(MSG_DEBUG, "FT: Invalid FTIE"); + return -1; + } + + anonce = ftie->anonce; + snonce = ftie->snonce; + fte_elem_count = ftie->mic_control[1]; + fte_mic = ftie->mic; + } else { + struct rsn_ftie *ftie; + + ftie = (struct rsn_ftie *) parse.ftie; + if (!ftie || parse.ftie_len < sizeof(*ftie)) { + wpa_printf(MSG_DEBUG, "FT: Invalid FTIE"); + return -1; + } + + anonce = ftie->anonce; + snonce = ftie->snonce; + fte_elem_count = ftie->mic_control[1]; + fte_mic = ftie->mic; } - if (os_memcmp(ftie->snonce, sm->snonce, WPA_NONCE_LEN) != 0) { + if (os_memcmp(snonce, sm->snonce, WPA_NONCE_LEN) != 0) { wpa_printf(MSG_DEBUG, "FT: SNonce mismatch in FTIE"); wpa_hexdump(MSG_DEBUG, "FT: Received SNonce", - ftie->snonce, WPA_NONCE_LEN); + snonce, WPA_NONCE_LEN); wpa_hexdump(MSG_DEBUG, "FT: Expected SNonce", sm->snonce, WPA_NONCE_LEN); return -1; } - if (os_memcmp(ftie->anonce, sm->anonce, WPA_NONCE_LEN) != 0) { + if (os_memcmp(anonce, sm->anonce, WPA_NONCE_LEN) != 0) { wpa_printf(MSG_DEBUG, "FT: ANonce mismatch in FTIE"); wpa_hexdump(MSG_DEBUG, "FT: Received ANonce", - ftie->anonce, WPA_NONCE_LEN); + anonce, WPA_NONCE_LEN); wpa_hexdump(MSG_DEBUG, "FT: Expected ANonce", sm->anonce, WPA_NONCE_LEN); return -1; @@ -765,14 +955,22 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, count = 3; if (parse.ric) count += ieee802_11_ie_count(parse.ric, parse.ric_len); - if (ftie->mic_control[1] != count) { + if (fte_elem_count != count) { wpa_printf(MSG_DEBUG, "FT: Unexpected IE count in MIC " "Control: received %u expected %u", - ftie->mic_control[1], count); + fte_elem_count, count); return -1; } - if (wpa_ft_mic(sm->ptk.kck, sm->ptk.kck_len, sm->own_addr, src_addr, 6, + if (wpa_key_mgmt_fils(sm->key_mgmt)) { + kck = sm->ptk.kck2; + kck_len = sm->ptk.kck2_len; + } else { + kck = sm->ptk.kck; + kck_len = sm->ptk.kck_len; + } + + if (wpa_ft_mic(kck, kck_len, sm->own_addr, src_addr, 6, parse.mdie - 2, parse.mdie_len + 2, parse.ftie - 2, parse.ftie_len + 2, parse.rsn - 2, parse.rsn_len + 2, @@ -782,13 +980,32 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, return -1; } - if (os_memcmp_const(mic, ftie->mic, 16) != 0) { + if (os_memcmp_const(mic, fte_mic, 16) != 0) { wpa_printf(MSG_DEBUG, "FT: Invalid MIC in FTIE"); - wpa_hexdump(MSG_MSGDUMP, "FT: Received MIC", ftie->mic, 16); + wpa_hexdump(MSG_MSGDUMP, "FT: Received MIC", fte_mic, 16); wpa_hexdump(MSG_MSGDUMP, "FT: Calculated MIC", mic, 16); return -1; } +#ifdef CONFIG_OCV + if (wpa_sm_ocv_enabled(sm)) { + struct wpa_channel_info ci; + + if (wpa_sm_channel_info(sm, &ci) != 0) { + wpa_printf(MSG_WARNING, + "Failed to get channel info to validate received OCI in (Re)Assoc Response"); + return -1; + } + + if (ocv_verify_tx_params(parse.oci, parse.oci_len, &ci, + channel_width_to_int(ci.chanwidth), + ci.seg1_idx) != 0) { + wpa_printf(MSG_WARNING, "%s", ocv_errorstr); + return -1; + } + } +#endif /* CONFIG_OCV */ + sm->ft_reassoc_completed = 1; if (wpa_ft_process_gtk_subelem(sm, parse.gtk, parse.gtk_len) < 0) diff --git a/freebsd/contrib/wpa/src/rsn_supp/wpa_i.h b/freebsd/contrib/wpa/src/rsn_supp/wpa_i.h index 56f88dcd..0c5955c6 100644 --- a/freebsd/contrib/wpa/src/rsn_supp/wpa_i.h +++ b/freebsd/contrib/wpa/src/rsn_supp/wpa_i.h @@ -1,6 +1,6 @@ /* * Internal WPA/RSN supplicant state machine definitions - * Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi> + * Copyright (c) 2004-2018, Jouni Malinen <j@w1.fi> * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -11,7 +11,6 @@ #include "utils/list.h" -struct wpa_peerkey; struct wpa_tdls_peer; struct wpa_eapol_key; @@ -57,7 +56,6 @@ struct wpa_sm { int fast_reauth; /* whether EAP fast re-authentication is enabled */ void *network_ctx; - int peerkey_enabled; int allowed_pairwise_cipher; /* bitfield of WPA_CIPHER_* */ int proactive_key_caching; int eap_workaround; @@ -88,15 +86,13 @@ struct wpa_sm { int rsn_enabled; /* Whether RSN is enabled in configuration */ int mfp; /* 0 = disabled, 1 = optional, 2 = mandatory */ + int ocv; /* Operating Channel Validation */ u8 *assoc_wpa_ie; /* Own WPA/RSN IE from (Re)AssocReq */ size_t assoc_wpa_ie_len; u8 *ap_wpa_ie, *ap_rsn_ie; size_t ap_wpa_ie_len, ap_rsn_ie_len; -#ifdef CONFIG_PEERKEY - struct wpa_peerkey *peerkey; -#endif /* CONFIG_PEERKEY */ #ifdef CONFIG_TDLS struct wpa_tdls_peer *tdls; int tdls_prohibited; @@ -117,18 +113,22 @@ struct wpa_sm { #endif /* CONFIG_TDLS */ #ifdef CONFIG_IEEE80211R - u8 xxkey[PMK_LEN]; /* PSK or the second 256 bits of MSK */ + u8 xxkey[PMK_LEN_MAX]; /* PSK or the second 256 bits of MSK, or the + * first 384 bits of MSK */ size_t xxkey_len; - u8 pmk_r0[PMK_LEN]; + u8 pmk_r0[PMK_LEN_MAX]; + size_t pmk_r0_len; u8 pmk_r0_name[WPA_PMK_NAME_LEN]; - u8 pmk_r1[PMK_LEN]; + u8 pmk_r1[PMK_LEN_MAX]; + size_t pmk_r1_len; u8 pmk_r1_name[WPA_PMK_NAME_LEN]; u8 mobility_domain[MOBILITY_DOMAIN_ID_LEN]; u8 r0kh_id[FT_R0KH_ID_MAX_LEN]; size_t r0kh_id_len; u8 r1kh_id[FT_R1KH_ID_LEN]; - int ft_completed; - int ft_reassoc_completed; + unsigned int ft_completed:1; + unsigned int ft_reassoc_completed:1; + unsigned int ft_protocol:1; int over_the_ds_in_progress; u8 target_ap[ETH_ALEN]; /* over-the-DS target AP */ int set_ptk_after_assoc; @@ -144,6 +144,35 @@ struct wpa_sm { #ifdef CONFIG_TESTING_OPTIONS struct wpabuf *test_assoc_ie; #endif /* CONFIG_TESTING_OPTIONS */ + +#ifdef CONFIG_FILS + u8 fils_nonce[FILS_NONCE_LEN]; + u8 fils_session[FILS_SESSION_LEN]; + u8 fils_anonce[FILS_NONCE_LEN]; + u8 fils_key_auth_ap[FILS_MAX_KEY_AUTH_LEN]; + u8 fils_key_auth_sta[FILS_MAX_KEY_AUTH_LEN]; + size_t fils_key_auth_len; + unsigned int fils_completed:1; + unsigned int fils_erp_pmkid_set:1; + unsigned int fils_cache_id_set:1; + u8 fils_erp_pmkid[PMKID_LEN]; + u8 fils_cache_id[FILS_CACHE_ID_LEN]; + struct crypto_ecdh *fils_ecdh; + int fils_dh_group; + size_t fils_dh_elem_len; + struct wpabuf *fils_ft_ies; + u8 fils_ft[FILS_FT_MAX_LEN]; + size_t fils_ft_len; +#endif /* CONFIG_FILS */ + +#ifdef CONFIG_OWE + struct crypto_ecdh *owe_ecdh; + u16 owe_group; +#endif /* CONFIG_OWE */ + +#ifdef CONFIG_DPP2 + struct wpabuf *dpp_z; +#endif /* CONFIG_DPP2 */ }; @@ -215,18 +244,23 @@ static inline u8 * wpa_sm_alloc_eapol(struct wpa_sm *sm, u8 type, msg_len, data_pos); } -static inline int wpa_sm_add_pmkid(struct wpa_sm *sm, const u8 *bssid, - const u8 *pmkid) +static inline int wpa_sm_add_pmkid(struct wpa_sm *sm, void *network_ctx, + const u8 *bssid, const u8 *pmkid, + const u8 *cache_id, const u8 *pmk, + size_t pmk_len) { WPA_ASSERT(sm->ctx->add_pmkid); - return sm->ctx->add_pmkid(sm->ctx->ctx, bssid, pmkid); + return sm->ctx->add_pmkid(sm->ctx->ctx, network_ctx, bssid, pmkid, + cache_id, pmk, pmk_len); } -static inline int wpa_sm_remove_pmkid(struct wpa_sm *sm, const u8 *bssid, - const u8 *pmkid) +static inline int wpa_sm_remove_pmkid(struct wpa_sm *sm, void *network_ctx, + const u8 *bssid, const u8 *pmkid, + const u8 *cache_id) { WPA_ASSERT(sm->ctx->remove_pmkid); - return sm->ctx->remove_pmkid(sm->ctx->ctx, bssid, pmkid); + return sm->ctx->remove_pmkid(sm->ctx->ctx, network_ctx, bssid, pmkid, + cache_id); } static inline int wpa_sm_mlme_setprotection(struct wpa_sm *sm, const u8 *addr, @@ -359,7 +393,24 @@ static inline int wpa_sm_key_mgmt_set_pmk(struct wpa_sm *sm, return sm->ctx->key_mgmt_set_pmk(sm->ctx->ctx, pmk, pmk_len); } -int wpa_eapol_key_send(struct wpa_sm *sm, const u8 *kck, size_t kck_len, +static inline void wpa_sm_fils_hlp_rx(struct wpa_sm *sm, + const u8 *dst, const u8 *src, + const u8 *pkt, size_t pkt_len) +{ + if (sm->ctx->fils_hlp_rx) + sm->ctx->fils_hlp_rx(sm->ctx->ctx, dst, src, pkt, pkt_len); +} + +static inline int wpa_sm_channel_info(struct wpa_sm *sm, + struct wpa_channel_info *ci) +{ + if (!sm->ctx->channel_info) + return -1; + return sm->ctx->channel_info(sm->ctx->ctx, ci); +} + + +int wpa_eapol_key_send(struct wpa_sm *sm, struct wpa_ptk *ptk, int ver, const u8 *dest, u16 proto, u8 *msg, size_t msg_len, u8 *key_mic); int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst, diff --git a/freebsd/contrib/wpa/src/rsn_supp/wpa_ie.c b/freebsd/contrib/wpa/src/rsn_supp/wpa_ie.c index 4caf9c6b..6c803ece 100644 --- a/freebsd/contrib/wpa/src/rsn_supp/wpa_ie.c +++ b/freebsd/contrib/wpa/src/rsn_supp/wpa_ie.c @@ -2,7 +2,7 @@ /* * wpa_supplicant - WPA/RSN IE and KDE processing - * Copyright (c) 2003-2015, Jouni Malinen <j@w1.fi> + * Copyright (c) 2003-2018, Jouni Malinen <j@w1.fi> * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -163,6 +163,10 @@ static int wpa_gen_wpa_ie_rsn(u8 *rsn_ie, size_t rsn_ie_len, #ifdef CONFIG_IEEE80211R } else if (key_mgmt == WPA_KEY_MGMT_FT_IEEE8021X) { RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_802_1X); +#ifdef CONFIG_SHA384 + } else if (key_mgmt == WPA_KEY_MGMT_FT_IEEE8021X_SHA384) { + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_802_1X_SHA384); +#endif /* CONFIG_SHA384 */ } else if (key_mgmt == WPA_KEY_MGMT_FT_PSK) { RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_PSK); #endif /* CONFIG_IEEE80211R */ @@ -182,6 +186,30 @@ static int wpa_gen_wpa_ie_rsn(u8 *rsn_ie, size_t rsn_ie_len, RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192); } else if (key_mgmt == WPA_KEY_MGMT_IEEE8021X_SUITE_B) { RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SUITE_B); +#ifdef CONFIG_FILS + } else if (key_mgmt & WPA_KEY_MGMT_FILS_SHA256) { + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FILS_SHA256); + } else if (key_mgmt & WPA_KEY_MGMT_FILS_SHA384) { + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FILS_SHA384); +#ifdef CONFIG_IEEE80211R + } else if (key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA256) { + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_FILS_SHA256); + } else if (key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA384) { + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_FILS_SHA384); +#endif /* CONFIG_IEEE80211R */ +#endif /* CONFIG_FILS */ +#ifdef CONFIG_OWE + } else if (key_mgmt & WPA_KEY_MGMT_OWE) { + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_OWE); +#endif /* CONFIG_OWE */ +#ifdef CONFIG_DPP + } else if (key_mgmt & WPA_KEY_MGMT_DPP) { + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_DPP); +#endif /* CONFIG_DPP */ +#ifdef CONFIG_HS20 + } else if (key_mgmt & WPA_KEY_MGMT_OSEN) { + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_OSEN); +#endif /* CONFIG_HS20 */ } else { wpa_printf(MSG_WARNING, "Invalid key management type (%d).", key_mgmt); @@ -197,6 +225,8 @@ static int wpa_gen_wpa_ie_rsn(u8 *rsn_ie, size_t rsn_ie_len, if (sm->mfp == 2) capab |= WPA_CAPABILITY_MFPR; #endif /* CONFIG_IEEE80211W */ + if (sm->ocv) + capab |= WPA_CAPABILITY_OCVC; WPA_PUT_LE16(pos, capab); pos += 2; @@ -407,44 +437,6 @@ static int wpa_parse_generic(const u8 *pos, const u8 *end, return 0; } -#ifdef CONFIG_PEERKEY - if (pos[1] > RSN_SELECTOR_LEN + 2 && - RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_SMK) { - ie->smk = pos + 2 + RSN_SELECTOR_LEN; - ie->smk_len = pos[1] - RSN_SELECTOR_LEN; - wpa_hexdump_key(MSG_DEBUG, "WPA: SMK in EAPOL-Key", - pos, pos[1] + 2); - return 0; - } - - if (pos[1] > RSN_SELECTOR_LEN + 2 && - RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_NONCE) { - ie->nonce = pos + 2 + RSN_SELECTOR_LEN; - ie->nonce_len = pos[1] - RSN_SELECTOR_LEN; - wpa_hexdump(MSG_DEBUG, "WPA: Nonce in EAPOL-Key", - pos, pos[1] + 2); - return 0; - } - - if (pos[1] > RSN_SELECTOR_LEN + 2 && - RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_LIFETIME) { - ie->lifetime = pos + 2 + RSN_SELECTOR_LEN; - ie->lifetime_len = pos[1] - RSN_SELECTOR_LEN; - wpa_hexdump(MSG_DEBUG, "WPA: Lifetime in EAPOL-Key", - pos, pos[1] + 2); - return 0; - } - - if (pos[1] > RSN_SELECTOR_LEN + 2 && - RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_ERROR) { - ie->error = pos + 2 + RSN_SELECTOR_LEN; - ie->error_len = pos[1] - RSN_SELECTOR_LEN; - wpa_hexdump(MSG_DEBUG, "WPA: Error in EAPOL-Key", - pos, pos[1] + 2); - return 0; - } -#endif /* CONFIG_PEERKEY */ - #ifdef CONFIG_IEEE80211W if (pos[1] > RSN_SELECTOR_LEN + 2 && RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_IGTK) { @@ -475,6 +467,17 @@ static int wpa_parse_generic(const u8 *pos, const u8 *end, } #endif /* CONFIG_P2P */ +#ifdef CONFIG_OCV + if (pos[1] >= RSN_SELECTOR_LEN + 1 && + RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_OCI) { + ie->oci = pos + 2 + RSN_SELECTOR_LEN; + ie->oci_len = pos[1] - RSN_SELECTOR_LEN; + wpa_hexdump(MSG_DEBUG, "WPA: OCI KDE in EAPOL-Key", + pos, pos[1] + 2); + return 0; + } +#endif /* CONFIG_OCV */ + return 0; } diff --git a/freebsd/contrib/wpa/src/rsn_supp/wpa_ie.h b/freebsd/contrib/wpa/src/rsn_supp/wpa_ie.h index fe95af0a..9d53973a 100644 --- a/freebsd/contrib/wpa/src/rsn_supp/wpa_ie.h +++ b/freebsd/contrib/wpa/src/rsn_supp/wpa_ie.h @@ -21,16 +21,6 @@ struct wpa_eapol_ie_parse { size_t gtk_len; const u8 *mac_addr; size_t mac_addr_len; -#ifdef CONFIG_PEERKEY - const u8 *smk; - size_t smk_len; - const u8 *nonce; - size_t nonce_len; - const u8 *lifetime; - size_t lifetime_len; - const u8 *error; - size_t error_len; -#endif /* CONFIG_PEERKEY */ #ifdef CONFIG_IEEE80211W const u8 *igtk; size_t igtk_len; @@ -63,6 +53,10 @@ struct wpa_eapol_ie_parse { const u8 *ip_addr_req; const u8 *ip_addr_alloc; #endif /* CONFIG_P2P */ +#ifdef CONFIG_OCV + const u8 *oci; + size_t oci_len; +#endif /* CONFIG_OCV */ }; int wpa_supplicant_parse_ies(const u8 *buf, size_t len, diff --git a/freebsd/contrib/wpa/src/tls/tlsv1_client.h b/freebsd/contrib/wpa/src/tls/tlsv1_client.h index 40fa6c7f..7fcc256f 100644 --- a/freebsd/contrib/wpa/src/tls/tlsv1_client.h +++ b/freebsd/contrib/wpa/src/tls/tlsv1_client.h @@ -1,6 +1,6 @@ /* * TLS v1.0/v1.1/v1.2 client (RFC 2246, RFC 4346, RFC 5246) - * Copyright (c) 2006-2011, Jouni Malinen <j@w1.fi> + * Copyright (c) 2006-2019, Jouni Malinen <j@w1.fi> * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -19,6 +19,7 @@ struct tlsv1_client * tlsv1_client_init(void); void tlsv1_client_deinit(struct tlsv1_client *conn); int tlsv1_client_established(struct tlsv1_client *conn); int tlsv1_client_prf(struct tlsv1_client *conn, const char *label, + const u8 *context, size_t context_len, int server_random_first, u8 *out, size_t out_len); u8 * tlsv1_client_handshake(struct tlsv1_client *conn, const u8 *in_data, size_t in_len, diff --git a/freebsd/contrib/wpa/src/tls/tlsv1_server.h b/freebsd/contrib/wpa/src/tls/tlsv1_server.h index 10e76993..c9c0875c 100644 --- a/freebsd/contrib/wpa/src/tls/tlsv1_server.h +++ b/freebsd/contrib/wpa/src/tls/tlsv1_server.h @@ -1,6 +1,6 @@ /* * TLS v1.0/v1.1/v1.2 server (RFC 2246, RFC 4346, RFC 5246) - * Copyright (c) 2006-2011, Jouni Malinen <j@w1.fi> + * Copyright (c) 2006-2019, Jouni Malinen <j@w1.fi> * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -19,6 +19,7 @@ struct tlsv1_server * tlsv1_server_init(struct tlsv1_credentials *cred); void tlsv1_server_deinit(struct tlsv1_server *conn); int tlsv1_server_established(struct tlsv1_server *conn); int tlsv1_server_prf(struct tlsv1_server *conn, const char *label, + const u8 *context, size_t context_len, int server_random_first, u8 *out, size_t out_len); u8 * tlsv1_server_handshake(struct tlsv1_server *conn, const u8 *in_data, size_t in_len, size_t *out_len); @@ -48,6 +49,10 @@ void tlsv1_server_set_session_ticket_cb(struct tlsv1_server *conn, void tlsv1_server_set_log_cb(struct tlsv1_server *conn, void (*cb)(void *ctx, const char *msg), void *ctx); +int tlsv1_server_get_failed(struct tlsv1_server *conn); +int tlsv1_server_get_read_alerts(struct tlsv1_server *conn); +int tlsv1_server_get_write_alerts(struct tlsv1_server *conn); + void tlsv1_server_set_test_flags(struct tlsv1_server *conn, u32 flags); #endif /* TLSV1_SERVER_H */ diff --git a/freebsd/contrib/wpa/src/utils/base64.c b/freebsd/contrib/wpa/src/utils/base64.c index 4127950f..a1807605 100644 --- a/freebsd/contrib/wpa/src/utils/base64.c +++ b/freebsd/contrib/wpa/src/utils/base64.c @@ -2,42 +2,39 @@ /* * Base64 encoding/decoding (RFC1341) - * Copyright (c) 2005-2011, Jouni Malinen <j@w1.fi> + * Copyright (c) 2005-2019, Jouni Malinen <j@w1.fi> * * This software may be distributed under the terms of the BSD license. * See README for more details. */ #include "includes.h" +#include <stdint.h> #include "os.h" #include "base64.h" static const unsigned char base64_table[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +static const unsigned char base64_url_table[65] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; -/** - * base64_encode - Base64 encode - * @src: Data to be encoded - * @len: Length of the data to be encoded - * @out_len: Pointer to output length variable, or %NULL if not used - * Returns: Allocated buffer of out_len bytes of encoded data, - * or %NULL on failure - * - * Caller is responsible for freeing the returned buffer. Returned buffer is - * nul terminated to make it easier to use as a C string. The nul terminator is - * not included in out_len. - */ -unsigned char * base64_encode(const unsigned char *src, size_t len, - size_t *out_len) + +static unsigned char * base64_gen_encode(const unsigned char *src, size_t len, + size_t *out_len, + const unsigned char *table, + int add_pad) { unsigned char *out, *pos; const unsigned char *end, *in; size_t olen; int line_len; + if (len >= SIZE_MAX / 4) + return NULL; olen = len * 4 / 3 + 4; /* 3-byte blocks to 4-byte */ - olen += olen / 72; /* line feeds */ + if (add_pad) + olen += olen / 72; /* line feeds */ olen++; /* nul termination */ if (olen < len) return NULL; /* integer overflow */ @@ -50,35 +47,35 @@ unsigned char * base64_encode(const unsigned char *src, size_t len, pos = out; line_len = 0; while (end - in >= 3) { - *pos++ = base64_table[(in[0] >> 2) & 0x3f]; - *pos++ = base64_table[(((in[0] & 0x03) << 4) | - (in[1] >> 4)) & 0x3f]; - *pos++ = base64_table[(((in[1] & 0x0f) << 2) | - (in[2] >> 6)) & 0x3f]; - *pos++ = base64_table[in[2] & 0x3f]; + *pos++ = table[(in[0] >> 2) & 0x3f]; + *pos++ = table[(((in[0] & 0x03) << 4) | (in[1] >> 4)) & 0x3f]; + *pos++ = table[(((in[1] & 0x0f) << 2) | (in[2] >> 6)) & 0x3f]; + *pos++ = table[in[2] & 0x3f]; in += 3; line_len += 4; - if (line_len >= 72) { + if (add_pad && line_len >= 72) { *pos++ = '\n'; line_len = 0; } } if (end - in) { - *pos++ = base64_table[(in[0] >> 2) & 0x3f]; + *pos++ = table[(in[0] >> 2) & 0x3f]; if (end - in == 1) { - *pos++ = base64_table[((in[0] & 0x03) << 4) & 0x3f]; - *pos++ = '='; + *pos++ = table[((in[0] & 0x03) << 4) & 0x3f]; + if (add_pad) + *pos++ = '='; } else { - *pos++ = base64_table[(((in[0] & 0x03) << 4) | - (in[1] >> 4)) & 0x3f]; - *pos++ = base64_table[((in[1] & 0x0f) << 2) & 0x3f]; + *pos++ = table[(((in[0] & 0x03) << 4) | + (in[1] >> 4)) & 0x3f]; + *pos++ = table[((in[1] & 0x0f) << 2) & 0x3f]; } - *pos++ = '='; + if (add_pad) + *pos++ = '='; line_len += 4; } - if (line_len) + if (add_pad && line_len) *pos++ = '\n'; *pos = '\0'; @@ -88,26 +85,18 @@ unsigned char * base64_encode(const unsigned char *src, size_t len, } -/** - * base64_decode - Base64 decode - * @src: Data to be decoded - * @len: Length of the data to be decoded - * @out_len: Pointer to output length variable - * Returns: Allocated buffer of out_len bytes of decoded data, - * or %NULL on failure - * - * Caller is responsible for freeing the returned buffer. - */ -unsigned char * base64_decode(const unsigned char *src, size_t len, - size_t *out_len) +static unsigned char * base64_gen_decode(const unsigned char *src, size_t len, + size_t *out_len, + const unsigned char *table) { unsigned char dtable[256], *out, *pos, block[4], tmp; size_t i, count, olen; int pad = 0; + size_t extra_pad; os_memset(dtable, 0x80, 256); for (i = 0; i < sizeof(base64_table) - 1; i++) - dtable[base64_table[i]] = (unsigned char) i; + dtable[table[i]] = (unsigned char) i; dtable['='] = 0; count = 0; @@ -116,21 +105,28 @@ unsigned char * base64_decode(const unsigned char *src, size_t len, count++; } - if (count == 0 || count % 4) + if (count == 0) return NULL; + extra_pad = (4 - count % 4) % 4; - olen = count / 4 * 3; + olen = (count + extra_pad) / 4 * 3; pos = out = os_malloc(olen); if (out == NULL) return NULL; count = 0; - for (i = 0; i < len; i++) { - tmp = dtable[src[i]]; + for (i = 0; i < len + extra_pad; i++) { + unsigned char val; + + if (i >= len) + val = '='; + else + val = src[i]; + tmp = dtable[val]; if (tmp == 0x80) continue; - if (src[i] == '=') + if (val == '=') pad++; block[count] = tmp; count++; @@ -157,3 +153,53 @@ unsigned char * base64_decode(const unsigned char *src, size_t len, *out_len = pos - out; return out; } + + +/** + * base64_encode - Base64 encode + * @src: Data to be encoded + * @len: Length of the data to be encoded + * @out_len: Pointer to output length variable, or %NULL if not used + * Returns: Allocated buffer of out_len bytes of encoded data, + * or %NULL on failure + * + * Caller is responsible for freeing the returned buffer. Returned buffer is + * nul terminated to make it easier to use as a C string. The nul terminator is + * not included in out_len. + */ +unsigned char * base64_encode(const unsigned char *src, size_t len, + size_t *out_len) +{ + return base64_gen_encode(src, len, out_len, base64_table, 1); +} + + +unsigned char * base64_url_encode(const unsigned char *src, size_t len, + size_t *out_len, int add_pad) +{ + return base64_gen_encode(src, len, out_len, base64_url_table, add_pad); +} + + +/** + * base64_decode - Base64 decode + * @src: Data to be decoded + * @len: Length of the data to be decoded + * @out_len: Pointer to output length variable + * Returns: Allocated buffer of out_len bytes of decoded data, + * or %NULL on failure + * + * Caller is responsible for freeing the returned buffer. + */ +unsigned char * base64_decode(const unsigned char *src, size_t len, + size_t *out_len) +{ + return base64_gen_decode(src, len, out_len, base64_table); +} + + +unsigned char * base64_url_decode(const unsigned char *src, size_t len, + size_t *out_len) +{ + return base64_gen_decode(src, len, out_len, base64_url_table); +} diff --git a/freebsd/contrib/wpa/src/utils/base64.h b/freebsd/contrib/wpa/src/utils/base64.h index aa21fd0f..5a72c3eb 100644 --- a/freebsd/contrib/wpa/src/utils/base64.h +++ b/freebsd/contrib/wpa/src/utils/base64.h @@ -13,5 +13,9 @@ unsigned char * base64_encode(const unsigned char *src, size_t len, size_t *out_len); unsigned char * base64_decode(const unsigned char *src, size_t len, size_t *out_len); +unsigned char * base64_url_encode(const unsigned char *src, size_t len, + size_t *out_len, int add_pad); +unsigned char * base64_url_decode(const unsigned char *src, size_t len, + size_t *out_len); #endif /* BASE64_H */ diff --git a/freebsd/contrib/wpa/src/utils/bitfield.c b/freebsd/contrib/wpa/src/utils/bitfield.c new file mode 100644 index 00000000..ef7b0676 --- /dev/null +++ b/freebsd/contrib/wpa/src/utils/bitfield.c @@ -0,0 +1,91 @@ +#include <machine/rtems-bsd-user-space.h> + +/* + * Bitfield + * Copyright (c) 2013, Jouni Malinen <j@w1.fi> + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "includes.h" + +#include "common.h" +#include "bitfield.h" + + +struct bitfield { + u8 *bits; + size_t max_bits; +}; + + +struct bitfield * bitfield_alloc(size_t max_bits) +{ + struct bitfield *bf; + + bf = os_zalloc(sizeof(*bf) + (max_bits + 7) / 8); + if (bf == NULL) + return NULL; + bf->bits = (u8 *) (bf + 1); + bf->max_bits = max_bits; + return bf; +} + + +void bitfield_free(struct bitfield *bf) +{ + os_free(bf); +} + + +void bitfield_set(struct bitfield *bf, size_t bit) +{ + if (bit >= bf->max_bits) + return; + bf->bits[bit / 8] |= BIT(bit % 8); +} + + +void bitfield_clear(struct bitfield *bf, size_t bit) +{ + if (bit >= bf->max_bits) + return; + bf->bits[bit / 8] &= ~BIT(bit % 8); +} + + +int bitfield_is_set(struct bitfield *bf, size_t bit) +{ + if (bit >= bf->max_bits) + return 0; + return !!(bf->bits[bit / 8] & BIT(bit % 8)); +} + + +static int first_zero(u8 val) +{ + int i; + for (i = 0; i < 8; i++) { + if (!(val & 0x01)) + return i; + val >>= 1; + } + return -1; +} + + +int bitfield_get_first_zero(struct bitfield *bf) +{ + size_t i; + for (i = 0; i < (bf->max_bits + 7) / 8; i++) { + if (bf->bits[i] != 0xff) + break; + } + if (i == (bf->max_bits + 7) / 8) + return -1; + i = i * 8 + first_zero(bf->bits[i]); + if (i >= bf->max_bits) + return -1; + return i; +} diff --git a/freebsd/contrib/wpa/src/utils/common.c b/freebsd/contrib/wpa/src/utils/common.c index 4d414bfa..a1fdfae7 100644 --- a/freebsd/contrib/wpa/src/utils/common.c +++ b/freebsd/contrib/wpa/src/utils/common.c @@ -2,7 +2,7 @@ /* * wpa_supplicant/hostapd / common helper functions, etc. - * Copyright (c) 2002-2007, Jouni Malinen <j@w1.fi> + * Copyright (c) 2002-2019, Jouni Malinen <j@w1.fi> * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -1075,7 +1075,8 @@ size_t utf8_unescape(const char *inp, size_t in_size, in_size--; } - while (in_size--) { + while (in_size) { + in_size--; if (res_size >= out_size) return 0; @@ -1086,8 +1087,9 @@ size_t utf8_unescape(const char *inp, size_t in_size, return res_size; case '\\': - if (!in_size--) + if (!in_size) return 0; + in_size--; inp++; /* fall through */ @@ -1118,7 +1120,8 @@ size_t utf8_escape(const char *inp, size_t in_size, if (!in_size) in_size = os_strlen(inp); - while (in_size--) { + while (in_size) { + in_size--; if (res_size++ >= out_size) return 0; @@ -1202,3 +1205,49 @@ int str_starts(const char *str, const char *start) { return os_strncmp(str, start, os_strlen(start)) == 0; } + + +/** + * rssi_to_rcpi - Convert RSSI to RCPI + * @rssi: RSSI to convert + * Returns: RCPI corresponding to the given RSSI value, or 255 if not available. + * + * It's possible to estimate RCPI based on RSSI in dBm. This calculation will + * not reflect the correct value for high rates, but it's good enough for Action + * frames which are transmitted with up to 24 Mbps rates. + */ +u8 rssi_to_rcpi(int rssi) +{ + if (!rssi) + return 255; /* not available */ + if (rssi < -110) + return 0; + if (rssi > 0) + return 220; + return (rssi + 110) * 2; +} + + +char * get_param(const char *cmd, const char *param) +{ + const char *pos, *end; + char *val; + size_t len; + + pos = os_strstr(cmd, param); + if (!pos) + return NULL; + + pos += os_strlen(param); + end = os_strchr(pos, ' '); + if (end) + len = end - pos; + else + len = os_strlen(pos); + val = os_malloc(len + 1); + if (!val) + return NULL; + os_memcpy(val, pos, len); + val[len] = '\0'; + return val; +} diff --git a/freebsd/contrib/wpa/src/utils/common.h b/freebsd/contrib/wpa/src/utils/common.h index 77856774..924a8fee 100644 --- a/freebsd/contrib/wpa/src/utils/common.h +++ b/freebsd/contrib/wpa/src/utils/common.h @@ -17,7 +17,7 @@ #endif /* __linux__ */ #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || \ - defined(__OpenBSD__) + defined(__OpenBSD__) || defined(__rtems__) #include <sys/types.h> #include <sys/endian.h> #define __BYTE_ORDER _BYTE_ORDER @@ -33,7 +33,8 @@ #define bswap_64 bswap64 #endif /* __OpenBSD__ */ #endif /* defined(__FreeBSD__) || defined(__NetBSD__) || - * defined(__DragonFly__) || defined(__OpenBSD__) */ + * defined(__DragonFly__) || defined(__OpenBSD__) || + * defined(__rtems__) */ #ifdef __APPLE__ #include <sys/types.h> @@ -141,6 +142,7 @@ static inline unsigned int wpa_swap_32(unsigned int v) #define host_to_le32(n) (n) #define be_to_host32(n) wpa_swap_32(n) #define host_to_be32(n) wpa_swap_32(n) +#define host_to_le64(n) (n) #define WPA_BYTE_SWAP_DEFINED @@ -331,6 +333,9 @@ static inline void WPA_PUT_LE64(u8 *a, u64 val) #ifndef ETH_P_RRB #define ETH_P_RRB 0x890D #endif /* ETH_P_RRB */ +#ifndef ETH_P_OUI +#define ETH_P_OUI 0x88B7 +#endif /* ETH_P_OUI */ #ifdef __GNUC__ @@ -423,6 +428,7 @@ void perror(const char *s); #define __bitwise __attribute__((bitwise)) #else #define __force +#undef __bitwise #define __bitwise #endif @@ -552,6 +558,8 @@ int is_ctrl_char(char c); int str_starts(const char *str, const char *start); +u8 rssi_to_rcpi(int rssi); +char * get_param(const char *cmd, const char *param); /* * gcc 4.4 ends up generating strict-aliasing warnings about some very common diff --git a/freebsd/contrib/wpa/src/utils/const_time.h b/freebsd/contrib/wpa/src/utils/const_time.h new file mode 100644 index 00000000..ab8f611e --- /dev/null +++ b/freebsd/contrib/wpa/src/utils/const_time.h @@ -0,0 +1,191 @@ +/* + * Helper functions for constant time operations + * Copyright (c) 2019, The Linux Foundation + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + * + * These helper functions can be used to implement logic that needs to minimize + * externally visible differences in execution path by avoiding use of branches, + * avoiding early termination or other time differences, and forcing same memory + * access pattern regardless of values. + */ + +#ifndef CONST_TIME_H +#define CONST_TIME_H + + +#if defined(__clang__) +#define NO_UBSAN_UINT_OVERFLOW \ + __attribute__((no_sanitize("unsigned-integer-overflow"))) +#else +#define NO_UBSAN_UINT_OVERFLOW +#endif + + +/** + * const_time_fill_msb - Fill all bits with MSB value + * @val: Input value + * Returns: Value with all the bits set to the MSB of the input val + */ +static inline unsigned int const_time_fill_msb(unsigned int val) +{ + /* Move the MSB to LSB and multiple by -1 to fill in all bits. */ + return (val >> (sizeof(val) * 8 - 1)) * ~0U; +} + + +/* Returns: -1 if val is zero; 0 if val is not zero */ +static inline unsigned int const_time_is_zero(unsigned int val) + NO_UBSAN_UINT_OVERFLOW +{ + /* Set MSB to 1 for 0 and fill rest of bits with the MSB value */ + return const_time_fill_msb(~val & (val - 1)); +} + + +/* Returns: -1 if a == b; 0 if a != b */ +static inline unsigned int const_time_eq(unsigned int a, unsigned int b) +{ + return const_time_is_zero(a ^ b); +} + + +/* Returns: -1 if a == b; 0 if a != b */ +static inline u8 const_time_eq_u8(unsigned int a, unsigned int b) +{ + return (u8) const_time_eq(a, b); +} + + +/** + * const_time_eq_bin - Constant time memory comparison + * @a: First buffer to compare + * @b: Second buffer to compare + * @len: Number of octets to compare + * Returns: -1 if buffers are equal, 0 if not + * + * This function is meant for comparing passwords or hash values where + * difference in execution time or memory access pattern could provide external + * observer information about the location of the difference in the memory + * buffers. The return value does not behave like memcmp(), i.e., + * const_time_eq_bin() cannot be used to sort items into a defined order. Unlike + * memcmp(), the execution time of const_time_eq_bin() does not depend on the + * contents of the compared memory buffers, but only on the total compared + * length. + */ +static inline unsigned int const_time_eq_bin(const void *a, const void *b, + size_t len) +{ + const u8 *aa = a; + const u8 *bb = b; + size_t i; + u8 res = 0; + + for (i = 0; i < len; i++) + res |= aa[i] ^ bb[i]; + + return const_time_is_zero(res); +} + + +/** + * const_time_select - Constant time unsigned int selection + * @mask: 0 (false) or -1 (true) to identify which value to select + * @true_val: Value to select for the true case + * @false_val: Value to select for the false case + * Returns: true_val if mask == -1, false_val if mask == 0 + */ +static inline unsigned int const_time_select(unsigned int mask, + unsigned int true_val, + unsigned int false_val) +{ + return (mask & true_val) | (~mask & false_val); +} + + +/** + * const_time_select_int - Constant time int selection + * @mask: 0 (false) or -1 (true) to identify which value to select + * @true_val: Value to select for the true case + * @false_val: Value to select for the false case + * Returns: true_val if mask == -1, false_val if mask == 0 + */ +static inline int const_time_select_int(unsigned int mask, int true_val, + int false_val) +{ + return (int) const_time_select(mask, (unsigned int) true_val, + (unsigned int) false_val); +} + + +/** + * const_time_select_u8 - Constant time u8 selection + * @mask: 0 (false) or -1 (true) to identify which value to select + * @true_val: Value to select for the true case + * @false_val: Value to select for the false case + * Returns: true_val if mask == -1, false_val if mask == 0 + */ +static inline u8 const_time_select_u8(u8 mask, u8 true_val, u8 false_val) +{ + return (u8) const_time_select(mask, true_val, false_val); +} + + +/** + * const_time_select_s8 - Constant time s8 selection + * @mask: 0 (false) or -1 (true) to identify which value to select + * @true_val: Value to select for the true case + * @false_val: Value to select for the false case + * Returns: true_val if mask == -1, false_val if mask == 0 + */ +static inline s8 const_time_select_s8(u8 mask, s8 true_val, s8 false_val) +{ + return (s8) const_time_select(mask, (unsigned int) true_val, + (unsigned int) false_val); +} + + +/** + * const_time_select_bin - Constant time binary buffer selection copy + * @mask: 0 (false) or -1 (true) to identify which value to copy + * @true_val: Buffer to copy for the true case + * @false_val: Buffer to copy for the false case + * @len: Number of octets to copy + * @dst: Destination buffer for the copy + * + * This function copies the specified buffer into the destination buffer using + * operations with identical memory access pattern regardless of which buffer + * is being copied. + */ +static inline void const_time_select_bin(u8 mask, const u8 *true_val, + const u8 *false_val, size_t len, + u8 *dst) +{ + size_t i; + + for (i = 0; i < len; i++) + dst[i] = const_time_select_u8(mask, true_val[i], false_val[i]); +} + + +static inline int const_time_memcmp(const void *a, const void *b, size_t len) +{ + const u8 *aa = a; + const u8 *bb = b; + int diff, res = 0; + unsigned int mask; + + if (len == 0) + return 0; + do { + len--; + diff = (int) aa[len] - (int) bb[len]; + mask = const_time_is_zero((unsigned int) diff); + res = const_time_select_int(mask, res, diff); + } while (len); + + return res; +} + +#endif /* CONST_TIME_H */ diff --git a/freebsd/contrib/wpa/src/utils/eloop.c b/freebsd/contrib/wpa/src/utils/eloop.c index 2ec86ff6..41de0f79 100644 --- a/freebsd/contrib/wpa/src/utils/eloop.c +++ b/freebsd/contrib/wpa/src/utils/eloop.c @@ -226,22 +226,25 @@ static int eloop_sock_queue(int sock, eloop_event_type type) #ifdef CONFIG_ELOOP_KQUEUE -static int eloop_sock_queue(int sock, eloop_event_type type) -{ - int filter; - struct kevent ke; +static short event_type_kevent_filter(eloop_event_type type) +{ switch (type) { case EVENT_TYPE_READ: - filter = EVFILT_READ; - break; + return EVFILT_READ; case EVENT_TYPE_WRITE: - filter = EVFILT_WRITE; - break; + return EVFILT_WRITE; default: - filter = 0; + return 0; } - EV_SET(&ke, sock, filter, EV_ADD, 0, 0, 0); +} + + +static int eloop_sock_queue(int sock, eloop_event_type type) +{ + struct kevent ke; + + EV_SET(&ke, sock, event_type_kevent_filter(type), EV_ADD, 0, 0, 0); if (kevent(eloop.kqueuefd, &ke, 1, NULL, 0, NULL) == -1) { wpa_printf(MSG_ERROR, "%s: kevent(ADD) for fd=%d failed: %s", __func__, sock, strerror(errno)); @@ -249,6 +252,7 @@ static int eloop_sock_queue(int sock, eloop_event_type type) } return 0; } + #endif /* CONFIG_ELOOP_KQUEUE */ @@ -303,7 +307,7 @@ static int eloop_sock_table_add_sock(struct eloop_sock_table *table, #endif /* CONFIG_ELOOP_POLL */ #if defined(CONFIG_ELOOP_EPOLL) || defined(CONFIG_ELOOP_KQUEUE) if (new_max_sock >= eloop.max_fd) { - next = eloop.max_fd == 0 ? 16 : eloop.max_fd * 2; + next = new_max_sock + 16; temp_table = os_realloc_array(eloop.fd_table, next, sizeof(struct eloop_sock)); if (temp_table == NULL) @@ -413,7 +417,8 @@ static void eloop_sock_table_remove_sock(struct eloop_sock_table *table, os_memset(&eloop.fd_table[sock], 0, sizeof(struct eloop_sock)); #endif /* CONFIG_ELOOP_EPOLL */ #ifdef CONFIG_ELOOP_KQUEUE - EV_SET(&ke, sock, 0, EV_DELETE, 0, 0, 0); + EV_SET(&ke, sock, event_type_kevent_filter(table->type), EV_DELETE, 0, + 0, 0); if (kevent(eloop.kqueuefd, &ke, 1, NULL, 0, NULL) < 0) { wpa_printf(MSG_ERROR, "%s: kevent(DEL) for fd=%d failed: %s", __func__, sock, strerror(errno)); diff --git a/freebsd/contrib/wpa/src/utils/eloop.h b/freebsd/contrib/wpa/src/utils/eloop.h index 97af16f0..04ee6d18 100644 --- a/freebsd/contrib/wpa/src/utils/eloop.h +++ b/freebsd/contrib/wpa/src/utils/eloop.h @@ -45,16 +45,16 @@ typedef void (*eloop_sock_handler)(int sock, void *eloop_ctx, void *sock_ctx); /** * eloop_event_handler - eloop generic event callback type * @eloop_ctx: Registered callback context data (eloop_data) - * @sock_ctx: Registered callback context data (user_data) + * @user_ctx: Registered callback context data (user_data) */ -typedef void (*eloop_event_handler)(void *eloop_data, void *user_ctx); +typedef void (*eloop_event_handler)(void *eloop_ctx, void *user_ctx); /** * eloop_timeout_handler - eloop timeout event callback type * @eloop_ctx: Registered callback context data (eloop_data) - * @sock_ctx: Registered callback context data (user_data) + * @user_ctx: Registered callback context data (user_data) */ -typedef void (*eloop_timeout_handler)(void *eloop_data, void *user_ctx); +typedef void (*eloop_timeout_handler)(void *eloop_ctx, void *user_ctx); /** * eloop_signal_handler - eloop signal event callback type diff --git a/freebsd/contrib/wpa/src/utils/list.h b/freebsd/contrib/wpa/src/utils/list.h index ee2f4856..85aa5e39 100644 --- a/freebsd/contrib/wpa/src/utils/list.h +++ b/freebsd/contrib/wpa/src/utils/list.h @@ -1,6 +1,6 @@ /* * Doubly-linked list - * Copyright (c) 2009, Jouni Malinen <j@w1.fi> + * Copyright (c) 2009-2019, Jouni Malinen <j@w1.fi> * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -76,8 +76,8 @@ static inline unsigned int dl_list_len(struct dl_list *list) dl_list_entry((list)->prev, type, member)) #define dl_list_for_each(item, list, type, member) \ - for (item = dl_list_entry((list)->next, type, member); \ - &item->member != (list); \ + for (item = dl_list_first((list), type, member); \ + item && item != dl_list_entry((list), type, member); \ item = dl_list_entry(item->member.next, type, member)) #define dl_list_for_each_safe(item, n, list, type, member) \ diff --git a/freebsd/contrib/wpa/src/utils/os.h b/freebsd/contrib/wpa/src/utils/os.h index e8f0b792..21ba5c3f 100644 --- a/freebsd/contrib/wpa/src/utils/os.h +++ b/freebsd/contrib/wpa/src/utils/os.h @@ -614,6 +614,18 @@ size_t os_strlcpy(char *dest, const char *src, size_t siz); */ int os_memcmp_const(const void *a, const void *b, size_t len); + +/** + * os_memdup - Allocate duplicate of passed memory chunk + * @src: Source buffer to duplicate + * @len: Length of source buffer + * Returns: %NULL if allocation failed, copy of src buffer otherwise + * + * This function allocates a memory block like os_malloc() would, and + * copies the given source buffer into it. + */ +void * os_memdup(const void *src, size_t len); + /** * os_exec - Execute an external program * @program: Path to the program diff --git a/freebsd/contrib/wpa/src/utils/os_unix.c b/freebsd/contrib/wpa/src/utils/os_unix.c index b5879dc8..1d763968 100644 --- a/freebsd/contrib/wpa/src/utils/os_unix.c +++ b/freebsd/contrib/wpa/src/utils/os_unix.c @@ -2,7 +2,7 @@ /* * OS specific functions for UNIX/POSIX systems - * Copyright (c) 2005-2009, Jouni Malinen <j@w1.fi> + * Copyright (c) 2005-2019, Jouni Malinen <j@w1.fi> * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -87,6 +87,9 @@ int os_get_reltime(struct os_reltime *t) struct timespec ts; int res; + if (TEST_FAIL()) + return -1; + while (1) { res = clock_gettime(clock_id, &ts); if (res == 0) { @@ -281,6 +284,13 @@ void os_daemonize_terminate(const char *pid_file) int os_get_random(unsigned char *buf, size_t len) { +#ifdef TEST_FUZZ + size_t i; + + for (i = 0; i < len; i++) + buf[i] = i & 0xff; + return 0; +#else /* TEST_FUZZ */ FILE *f; size_t rc; @@ -302,6 +312,7 @@ int os_get_random(unsigned char *buf, size_t len) return rc != len ? -1 : 0; #endif /* __rtems__ */ +#endif /* TEST_FUZZ */ } @@ -544,6 +555,16 @@ int os_memcmp_const(const void *a, const void *b, size_t len) } +void * os_memdup(const void *src, size_t len) +{ + void *r = os_malloc(len); + + if (r && src) + os_memcpy(r, src, len); + return r; +} + + #ifdef WPA_TRACE #if defined(WPA_TRACE_BFD) && defined(CONFIG_TESTING_OPTIONS) @@ -576,6 +597,8 @@ static int testing_fail_alloc(void) i++; if (i < res && os_strcmp(func[i], "os_strdup") == 0) i++; + if (i < res && os_strcmp(func[i], "os_memdup") == 0) + i++; pos = wpa_trace_fail_func; diff --git a/freebsd/contrib/wpa/src/utils/uuid.c b/freebsd/contrib/wpa/src/utils/uuid.c index a1dedf6e..a51c0f42 100644 --- a/freebsd/contrib/wpa/src/utils/uuid.c +++ b/freebsd/contrib/wpa/src/utils/uuid.c @@ -11,6 +11,7 @@ #include "includes.h" #include "common.h" +#include "crypto/sha256.h" #include "uuid.h" int uuid_str2bin(const char *str, u8 *bin) @@ -71,3 +72,27 @@ int is_nil_uuid(const u8 *uuid) return 0; return 1; } + + +int uuid_random(u8 *uuid) +{ + struct os_time t; + u8 hash[SHA256_MAC_LEN]; + + /* Use HMAC-SHA256 and timestamp as context to avoid exposing direct + * os_get_random() output in the UUID field. */ + os_get_time(&t); + if (os_get_random(uuid, UUID_LEN) < 0 || + hmac_sha256(uuid, UUID_LEN, (const u8 *) &t, sizeof(t), hash) < 0) + return -1; + + os_memcpy(uuid, hash, UUID_LEN); + + /* Version: 4 = random */ + uuid[6] = (4 << 4) | (uuid[6] & 0x0f); + + /* Variant specified in RFC 4122 */ + uuid[8] = 0x80 | (uuid[8] & 0x3f); + + return 0; +} diff --git a/freebsd/contrib/wpa/src/utils/uuid.h b/freebsd/contrib/wpa/src/utils/uuid.h index 5e860cbc..6e20210f 100644 --- a/freebsd/contrib/wpa/src/utils/uuid.h +++ b/freebsd/contrib/wpa/src/utils/uuid.h @@ -14,5 +14,6 @@ int uuid_str2bin(const char *str, u8 *bin); int uuid_bin2str(const u8 *bin, char *str, size_t max_len); int is_nil_uuid(const u8 *uuid); +int uuid_random(u8 *uuid); #endif /* UUID_H */ diff --git a/freebsd/contrib/wpa/src/utils/wpa_debug.c b/freebsd/contrib/wpa/src/utils/wpa_debug.c index 68100490..66596999 100644 --- a/freebsd/contrib/wpa/src/utils/wpa_debug.c +++ b/freebsd/contrib/wpa/src/utils/wpa_debug.c @@ -15,7 +15,7 @@ #ifdef CONFIG_DEBUG_SYSLOG #include <syslog.h> -static int wpa_debug_syslog = 0; +int wpa_debug_syslog = 0; #endif /* CONFIG_DEBUG_SYSLOG */ #ifdef CONFIG_DEBUG_LINUX_TRACING @@ -60,6 +60,10 @@ static int wpa_to_android_level(int level) #ifndef CONFIG_NO_STDOUT_DEBUG #ifdef CONFIG_DEBUG_FILE +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + static FILE *out_file = NULL; #endif /* CONFIG_DEBUG_FILE */ @@ -420,6 +424,12 @@ static void _wpa_hexdump_ascii(int level, const char *title, const void *buf, #ifdef CONFIG_ANDROID_LOG _wpa_hexdump(level, title, buf, len, show); #else /* CONFIG_ANDROID_LOG */ +#ifdef CONFIG_DEBUG_SYSLOG + if (wpa_debug_syslog) { + _wpa_hexdump(level, title, buf, len, show); + return; + } +#endif /* CONFIG_DEBUG_SYSLOG */ wpa_debug_print_timestamp(); #ifdef CONFIG_DEBUG_FILE if (out_file) { @@ -541,6 +551,8 @@ int wpa_debug_reopen_file(void) int wpa_debug_open_file(const char *path) { #ifdef CONFIG_DEBUG_FILE + int out_fd; + if (!path) return 0; @@ -550,10 +562,28 @@ int wpa_debug_open_file(const char *path) last_path = os_strdup(path); } - out_file = fopen(path, "a"); + out_fd = open(path, O_CREAT | O_APPEND | O_WRONLY, + S_IRUSR | S_IWUSR | S_IRGRP); + if (out_fd < 0) { + wpa_printf(MSG_ERROR, + "%s: Failed to open output file descriptor, using standard output", + __func__); + return -1; + } + +#ifdef __linux__ + if (fcntl(out_fd, F_SETFD, FD_CLOEXEC) < 0) { + wpa_printf(MSG_DEBUG, + "%s: Failed to set FD_CLOEXEC - continue without: %s", + __func__, strerror(errno)); + } +#endif /* __linux__ */ + + out_file = fdopen(out_fd, "a"); if (out_file == NULL) { wpa_printf(MSG_ERROR, "wpa_debug_open_file: Failed to open " "output file, using standard output"); + close(out_fd); return -1; } #ifndef _WIN32 diff --git a/freebsd/contrib/wpa/src/utils/wpa_debug.h b/freebsd/contrib/wpa/src/utils/wpa_debug.h index 17d8f963..1fe0b7db 100644 --- a/freebsd/contrib/wpa/src/utils/wpa_debug.h +++ b/freebsd/contrib/wpa/src/utils/wpa_debug.h @@ -14,6 +14,9 @@ extern int wpa_debug_level; extern int wpa_debug_show_keys; extern int wpa_debug_timestamp; +#ifdef CONFIG_DEBUG_SYSLOG +extern int wpa_debug_syslog; +#endif /* CONFIG_DEBUG_SYSLOG */ /* Debugging function - conditional printf and hex dump. Driver wrappers can * use these for debugging purposes. */ diff --git a/freebsd/contrib/wpa/src/utils/wpabuf.c b/freebsd/contrib/wpa/src/utils/wpabuf.c index 26e2e8bb..3959f7bc 100644 --- a/freebsd/contrib/wpa/src/utils/wpabuf.c +++ b/freebsd/contrib/wpa/src/utils/wpabuf.c @@ -246,15 +246,13 @@ struct wpabuf * wpabuf_concat(struct wpabuf *a, struct wpabuf *b) if (a) len += wpabuf_len(a); - if (b) - len += wpabuf_len(b); + len += wpabuf_len(b); n = wpabuf_alloc(len); if (n) { if (a) wpabuf_put_buf(n, a); - if (b) - wpabuf_put_buf(n, b); + wpabuf_put_buf(n, b); } wpabuf_free(a); diff --git a/freebsd/contrib/wpa/src/wps/wps.c b/freebsd/contrib/wpa/src/wps/wps.c index c0caca91..89351fe3 100644 --- a/freebsd/contrib/wpa/src/wps/wps.c +++ b/freebsd/contrib/wpa/src/wps/wps.c @@ -53,12 +53,11 @@ struct wps_data * wps_init(const struct wps_config *cfg) } if (cfg->pin) { data->dev_pw_id = cfg->dev_pw_id; - data->dev_password = os_malloc(cfg->pin_len); + data->dev_password = os_memdup(cfg->pin, cfg->pin_len); if (data->dev_password == NULL) { os_free(data); return NULL; } - os_memcpy(data->dev_password, cfg->pin, cfg->pin_len); data->dev_password_len = cfg->pin_len; wpa_hexdump_key(MSG_DEBUG, "WPS: AP PIN dev_password", data->dev_password, data->dev_password_len); @@ -77,14 +76,12 @@ struct wps_data * wps_init(const struct wps_config *cfg) data->dev_pw_id = cfg->wps->ap_nfc_dev_pw_id; data->dev_password = - os_malloc(wpabuf_len(cfg->wps->ap_nfc_dev_pw)); + os_memdup(wpabuf_head(cfg->wps->ap_nfc_dev_pw), + wpabuf_len(cfg->wps->ap_nfc_dev_pw)); if (data->dev_password == NULL) { os_free(data); return NULL; } - os_memcpy(data->dev_password, - wpabuf_head(cfg->wps->ap_nfc_dev_pw), - wpabuf_len(cfg->wps->ap_nfc_dev_pw)); data->dev_password_len = wpabuf_len(cfg->wps->ap_nfc_dev_pw); wpa_hexdump_key(MSG_DEBUG, "WPS: NFC dev_password", data->dev_password, data->dev_password_len); @@ -126,15 +123,14 @@ struct wps_data * wps_init(const struct wps_config *cfg) if (cfg->new_ap_settings) { data->new_ap_settings = - os_malloc(sizeof(*data->new_ap_settings)); + os_memdup(cfg->new_ap_settings, + sizeof(*data->new_ap_settings)); if (data->new_ap_settings == NULL) { bin_clear_free(data->dev_password, data->dev_password_len); os_free(data); return NULL; } - os_memcpy(data->new_ap_settings, cfg->new_ap_settings, - sizeof(*data->new_ap_settings)); } if (cfg->peer_addr) @@ -151,6 +147,8 @@ struct wps_data * wps_init(const struct wps_config *cfg) data->peer_pubkey_hash_set = 1; } + data->multi_ap_backhaul_sta = cfg->multi_ap_backhaul_sta; + return data; } @@ -436,7 +434,7 @@ struct wpabuf * wps_build_assoc_req_ie(enum wps_request_type req_type) if (wps_build_version(ie) || wps_build_req_type(ie, req_type) || - wps_build_wfa_ext(ie, 0, NULL, 0)) { + wps_build_wfa_ext(ie, 0, NULL, 0, 0)) { wpabuf_free(ie); return NULL; } @@ -470,7 +468,7 @@ struct wpabuf * wps_build_assoc_resp_ie(void) if (wps_build_version(ie) || wps_build_resp_type(ie, WPS_RESP_AP) || - wps_build_wfa_ext(ie, 0, NULL, 0)) { + wps_build_wfa_ext(ie, 0, NULL, 0, 0)) { wpabuf_free(ie); return NULL; } @@ -522,7 +520,7 @@ struct wpabuf * wps_build_probe_req_ie(u16 pw_id, struct wps_device_data *dev, wps_build_model_name(dev, ie) || wps_build_model_number(dev, ie) || wps_build_dev_name(dev, ie) || - wps_build_wfa_ext(ie, req_type == WPS_REQ_ENROLLEE, NULL, 0) || + wps_build_wfa_ext(ie, req_type == WPS_REQ_ENROLLEE, NULL, 0, 0) || wps_build_req_dev_type(dev, ie, num_req_dev_types, req_dev_types) || wps_build_secondary_dev_type(dev, ie) diff --git a/freebsd/contrib/wpa/src/wps/wps.h b/freebsd/contrib/wpa/src/wps/wps.h index 2505d2d9..14ce8632 100644 --- a/freebsd/contrib/wpa/src/wps/wps.h +++ b/freebsd/contrib/wpa/src/wps/wps.h @@ -100,6 +100,7 @@ struct wps_device_data { struct wpabuf *vendor_ext[MAX_WPS_VENDOR_EXTENSIONS]; int p2p; + u8 multi_ap_ext; }; /** @@ -187,6 +188,12 @@ struct wps_config { * peer_pubkey_hash - Peer public key hash or %NULL if not known */ const u8 *peer_pubkey_hash; + + /** + * multi_ap_backhaul_sta - Whether this is a Multi-AP backhaul STA + * enrollee + */ + int multi_ap_backhaul_sta; }; struct wps_data * wps_init(const struct wps_config *cfg); @@ -395,6 +402,37 @@ struct wps_registrar_config { * PSK is set for a network. */ int force_per_enrollee_psk; + + /** + * multi_ap_backhaul_ssid - SSID to supply to a Multi-AP backhaul + * enrollee + * + * This SSID is used by the Registrar to fill in information for + * Credentials when the enrollee advertises it is a Multi-AP backhaul + * STA. + */ + const u8 *multi_ap_backhaul_ssid; + + /** + * multi_ap_backhaul_ssid_len - Length of multi_ap_backhaul_ssid in + * octets + */ + size_t multi_ap_backhaul_ssid_len; + + /** + * multi_ap_backhaul_network_key - The Network Key (PSK) for the + * Multi-AP backhaul enrollee. + * + * This key can be either the ASCII passphrase (8..63 characters) or the + * 32-octet PSK (64 hex characters). + */ + const u8 *multi_ap_backhaul_network_key; + + /** + * multi_ap_backhaul_network_key_len - Length of + * multi_ap_backhaul_network_key in octets + */ + size_t multi_ap_backhaul_network_key_len; }; diff --git a/freebsd/contrib/wpa/src/wps/wps_attr_build.c b/freebsd/contrib/wpa/src/wps/wps_attr_build.c index e7083388..a66502f8 100644 --- a/freebsd/contrib/wpa/src/wps/wps_attr_build.c +++ b/freebsd/contrib/wpa/src/wps/wps_attr_build.c @@ -62,7 +62,8 @@ int wps_build_public_key(struct wps_data *wps, struct wpabuf *msg) } wps->dh_privkey = wpabuf_dup(wps->wps->ap_nfc_dh_privkey); pubkey = wpabuf_dup(wps->wps->ap_nfc_dh_pubkey); - wps->dh_ctx = dh5_init_fixed(wps->dh_privkey, pubkey); + if (wps->dh_privkey && pubkey) + wps->dh_ctx = dh5_init_fixed(wps->dh_privkey, pubkey); #endif /* CONFIG_WPS_NFC */ } else { wpa_printf(MSG_DEBUG, "WPS: Generate new DH keys"); @@ -205,7 +206,8 @@ int wps_build_version(struct wpabuf *msg) int wps_build_wfa_ext(struct wpabuf *msg, int req_to_enroll, - const u8 *auth_macs, size_t auth_macs_count) + const u8 *auth_macs, size_t auth_macs_count, + u8 multi_ap_subelem) { u8 *len; @@ -246,6 +248,14 @@ int wps_build_wfa_ext(struct wpabuf *msg, int req_to_enroll, MAC2STR(&auth_macs[i * ETH_ALEN])); } + if (multi_ap_subelem) { + wpa_printf(MSG_DEBUG, "WPS: * Multi-AP (0x%x)", + multi_ap_subelem); + wpabuf_put_u8(msg, WFA_ELEM_MULTI_AP); + wpabuf_put_u8(msg, 1); /* length */ + wpabuf_put_u8(msg, multi_ap_subelem); + } + WPA_PUT_BE16(len, (u8 *) wpabuf_put(msg, 0) - len - 2); #ifdef CONFIG_WPS_TESTING diff --git a/freebsd/contrib/wpa/src/wps/wps_attr_parse.c b/freebsd/contrib/wpa/src/wps/wps_attr_parse.c index edcfb58b..17fff46c 100644 --- a/freebsd/contrib/wpa/src/wps/wps_attr_parse.c +++ b/freebsd/contrib/wpa/src/wps/wps_attr_parse.c @@ -69,6 +69,17 @@ static int wps_set_vendor_ext_wfa_subelem(struct wps_parse_attr *attr, } attr->registrar_configuration_methods = pos; break; + case WFA_ELEM_MULTI_AP: + if (len != 1) { + wpa_printf(MSG_DEBUG, + "WPS: Invalid Multi-AP Extension length %u", + len); + return -1; + } + attr->multi_ap_ext = *pos; + wpa_printf(MSG_DEBUG, "WPS: Multi-AP Extension 0x%02x", + attr->multi_ap_ext); + break; default: wpa_printf(MSG_MSGDUMP, "WPS: Skipped unknown WFA Vendor " "Extension subelement %u", id); diff --git a/freebsd/contrib/wpa/src/wps/wps_attr_parse.h b/freebsd/contrib/wpa/src/wps/wps_attr_parse.h index 8188fe91..4de27b26 100644 --- a/freebsd/contrib/wpa/src/wps/wps_attr_parse.h +++ b/freebsd/contrib/wpa/src/wps/wps_attr_parse.h @@ -97,6 +97,7 @@ struct wps_parse_attr { const u8 *cred[MAX_CRED_COUNT]; const u8 *req_dev_type[MAX_REQ_DEV_TYPE_COUNT]; const u8 *vendor_ext[MAX_WPS_PARSE_VENDOR_EXT]; + u8 multi_ap_ext; }; int wps_parse_msg(const struct wpabuf *msg, struct wps_parse_attr *attr); diff --git a/freebsd/contrib/wpa/src/wps/wps_common.c b/freebsd/contrib/wpa/src/wps/wps_common.c index d7ac00b7..a729e8e4 100644 --- a/freebsd/contrib/wpa/src/wps/wps_common.c +++ b/freebsd/contrib/wpa/src/wps/wps_common.c @@ -376,7 +376,7 @@ struct wpabuf * wps_get_oob_cred(struct wps_context *wps, int rf_band, (rf_band && wps_build_rf_bands_attr(plain, rf_band)) || (channel && wps_build_ap_channel(plain, channel)) || wps_build_mac_addr(plain, wps->dev.mac_addr) || - wps_build_wfa_ext(plain, 0, NULL, 0)) { + wps_build_wfa_ext(plain, 0, NULL, 0, 0)) { os_free(data.new_psk); wpabuf_clear_free(plain); return NULL; @@ -423,7 +423,7 @@ struct wpabuf * wps_build_nfc_pw_token(u16 dev_pw_id, if (wps_build_oob_dev_pw(data, dev_pw_id, pubkey, wpabuf_head(dev_pw), wpabuf_len(dev_pw)) || - wps_build_wfa_ext(data, 0, NULL, 0)) { + wps_build_wfa_ext(data, 0, NULL, 0, 0)) { wpa_printf(MSG_ERROR, "WPS: Failed to build NFC password " "token"); wpabuf_clear_free(data); @@ -588,7 +588,7 @@ struct wpabuf * wps_build_wsc_ack(struct wps_data *wps) wps_build_msg_type(msg, WPS_WSC_ACK) || wps_build_enrollee_nonce(wps, msg) || wps_build_registrar_nonce(wps, msg) || - wps_build_wfa_ext(msg, 0, NULL, 0)) { + wps_build_wfa_ext(msg, 0, NULL, 0, 0)) { wpabuf_free(msg); return NULL; } @@ -612,7 +612,7 @@ struct wpabuf * wps_build_wsc_nack(struct wps_data *wps) wps_build_enrollee_nonce(wps, msg) || wps_build_registrar_nonce(wps, msg) || wps_build_config_error(msg, wps->config_error) || - wps_build_wfa_ext(msg, 0, NULL, 0)) { + wps_build_wfa_ext(msg, 0, NULL, 0, 0)) { wpabuf_free(msg); return NULL; } @@ -656,6 +656,7 @@ int wps_nfc_gen_dh(struct wpabuf **pubkey, struct wpabuf **privkey) pub = wpabuf_zeropad(pub, 192); if (pub == NULL) { wpabuf_free(priv); + dh5_free(dh_ctx); return -1; } wpa_hexdump_buf(MSG_DEBUG, "WPS: Generated new DH pubkey", pub); @@ -727,7 +728,7 @@ struct wpabuf * wps_build_nfc_handover_req(struct wps_context *ctx, if (wps_build_oob_dev_pw(msg, DEV_PW_NFC_CONNECTION_HANDOVER, nfc_dh_pubkey, NULL, 0) || wps_build_uuid_e(msg, ctx->uuid) || - wps_build_wfa_ext(msg, 0, NULL, 0)) { + wps_build_wfa_ext(msg, 0, NULL, 0, 0)) { wpabuf_free(msg); return NULL; } @@ -810,7 +811,7 @@ struct wpabuf * wps_build_nfc_handover_sel(struct wps_context *ctx, wps_build_ssid(msg, ctx) || wps_build_ap_freq(msg, freq) || (bssid && wps_build_mac_addr(msg, bssid)) || - wps_build_wfa_ext(msg, 0, NULL, 0)) { + wps_build_wfa_ext(msg, 0, NULL, 0, 0)) { wpabuf_free(msg); return NULL; } @@ -849,7 +850,7 @@ struct wpabuf * wps_build_nfc_handover_req_p2p(struct wps_context *ctx, wps_build_rf_bands(&ctx->dev, msg, 0) || wps_build_serial_number(&ctx->dev, msg) || wps_build_uuid_e(msg, ctx->uuid) || - wps_build_wfa_ext(msg, 0, NULL, 0)) { + wps_build_wfa_ext(msg, 0, NULL, 0, 0)) { wpabuf_free(msg); return NULL; } @@ -901,7 +902,7 @@ struct wpabuf * wps_build_nfc_handover_sel_p2p(struct wps_context *ctx, wps_build_rf_bands(&ctx->dev, msg, 0) || wps_build_serial_number(&ctx->dev, msg) || wps_build_uuid_e(msg, ctx->uuid) || - wps_build_wfa_ext(msg, 0, NULL, 0)) { + wps_build_wfa_ext(msg, 0, NULL, 0, 0)) { wpabuf_free(msg); return NULL; } diff --git a/freebsd/contrib/wpa/src/wps/wps_defs.h b/freebsd/contrib/wpa/src/wps/wps_defs.h index 301864da..9fccb4ee 100644 --- a/freebsd/contrib/wpa/src/wps/wps_defs.h +++ b/freebsd/contrib/wpa/src/wps/wps_defs.h @@ -152,7 +152,8 @@ enum { WFA_ELEM_NETWORK_KEY_SHAREABLE = 0x02, WFA_ELEM_REQUEST_TO_ENROLL = 0x03, WFA_ELEM_SETTINGS_DELAY_TIME = 0x04, - WFA_ELEM_REGISTRAR_CONFIGURATION_METHODS = 0x05 + WFA_ELEM_REGISTRAR_CONFIGURATION_METHODS = 0x05, + WFA_ELEM_MULTI_AP = 0x06 }; /* Device Password ID */ diff --git a/freebsd/contrib/wpa/src/wps/wps_dev_attr.c b/freebsd/contrib/wpa/src/wps/wps_dev_attr.c index 1cc6cee8..0748db70 100644 --- a/freebsd/contrib/wpa/src/wps/wps_dev_attr.c +++ b/freebsd/contrib/wpa/src/wps/wps_dev_attr.c @@ -392,6 +392,14 @@ int wps_process_os_version(struct wps_device_data *dev, const u8 *ver) } +void wps_process_vendor_ext_m1(struct wps_device_data *dev, const u8 ext) +{ + dev->multi_ap_ext = ext; + wpa_printf(MSG_DEBUG, "WPS: Multi-AP extension value %02x", + dev->multi_ap_ext); +} + + int wps_process_rf_bands(struct wps_device_data *dev, const u8 *bands) { if (bands == NULL) { diff --git a/freebsd/contrib/wpa/src/wps/wps_dev_attr.h b/freebsd/contrib/wpa/src/wps/wps_dev_attr.h index c9034add..a4b4173c 100644 --- a/freebsd/contrib/wpa/src/wps/wps_dev_attr.h +++ b/freebsd/contrib/wpa/src/wps/wps_dev_attr.h @@ -29,6 +29,7 @@ int wps_build_dev_name(struct wps_device_data *dev, struct wpabuf *msg); int wps_process_device_attrs(struct wps_device_data *dev, struct wps_parse_attr *attr); int wps_process_os_version(struct wps_device_data *dev, const u8 *ver); +void wps_process_vendor_ext_m1(struct wps_device_data *dev, const u8 ext); int wps_process_rf_bands(struct wps_device_data *dev, const u8 *bands); void wps_device_data_free(struct wps_device_data *dev); int wps_build_vendor_ext(struct wps_device_data *dev, struct wpabuf *msg); diff --git a/freebsd/contrib/wpa/src/wps/wps_enrollee.c b/freebsd/contrib/wpa/src/wps/wps_enrollee.c index 2260b506..74cf5bc5 100644 --- a/freebsd/contrib/wpa/src/wps/wps_enrollee.c +++ b/freebsd/contrib/wpa/src/wps/wps_enrollee.c @@ -107,6 +107,7 @@ static struct wpabuf * wps_build_m1(struct wps_data *wps) { struct wpabuf *msg; u16 config_methods; + u8 multi_ap_backhaul_sta = 0; if (random_get_bytes(wps->nonce_e, WPS_NONCE_LEN) < 0) return NULL; @@ -136,6 +137,9 @@ static struct wpabuf * wps_build_m1(struct wps_data *wps) WPS_CONFIG_PHY_PUSHBUTTON); } + if (wps->multi_ap_backhaul_sta) + multi_ap_backhaul_sta = MULTI_AP_BACKHAUL_STA; + if (wps_build_version(msg) || wps_build_msg_type(msg, WPS_M1) || wps_build_uuid_e(msg, wps->uuid_e) || @@ -154,7 +158,7 @@ static struct wpabuf * wps_build_m1(struct wps_data *wps) wps_build_dev_password_id(msg, wps->dev_pw_id) || wps_build_config_error(msg, WPS_CFG_NO_ERROR) || wps_build_os_version(&wps->wps->dev, msg) || - wps_build_wfa_ext(msg, 0, NULL, 0) || + wps_build_wfa_ext(msg, 0, NULL, 0, multi_ap_backhaul_sta) || wps_build_vendor_ext_m1(&wps->wps->dev, msg)) { wpabuf_free(msg); return NULL; @@ -192,7 +196,7 @@ static struct wpabuf * wps_build_m3(struct wps_data *wps) wps_build_msg_type(msg, WPS_M3) || wps_build_registrar_nonce(wps, msg) || wps_build_e_hash(wps, msg) || - wps_build_wfa_ext(msg, 0, NULL, 0) || + wps_build_wfa_ext(msg, 0, NULL, 0, 0) || wps_build_authenticator(wps, msg)) { wpabuf_free(msg); return NULL; @@ -225,7 +229,7 @@ static struct wpabuf * wps_build_m5(struct wps_data *wps) wps_build_e_snonce1(wps, plain) || wps_build_key_wrap_auth(wps, plain) || wps_build_encr_settings(wps, msg, plain) || - wps_build_wfa_ext(msg, 0, NULL, 0) || + wps_build_wfa_ext(msg, 0, NULL, 0, 0) || wps_build_authenticator(wps, msg)) { wpabuf_clear_free(plain); wpabuf_free(msg); @@ -395,7 +399,7 @@ static struct wpabuf * wps_build_m7(struct wps_data *wps) (wps->wps->ap && wps_build_ap_settings(wps, plain)) || wps_build_key_wrap_auth(wps, plain) || wps_build_encr_settings(wps, msg, plain) || - wps_build_wfa_ext(msg, 0, NULL, 0) || + wps_build_wfa_ext(msg, 0, NULL, 0, 0) || wps_build_authenticator(wps, msg)) { wpabuf_clear_free(plain); wpabuf_free(msg); @@ -432,7 +436,7 @@ static struct wpabuf * wps_build_wsc_done(struct wps_data *wps) wps_build_msg_type(msg, WPS_WSC_DONE) || wps_build_enrollee_nonce(wps, msg) || wps_build_registrar_nonce(wps, msg) || - wps_build_wfa_ext(msg, 0, NULL, 0)) { + wps_build_wfa_ext(msg, 0, NULL, 0, 0)) { wpabuf_free(msg); return NULL; } diff --git a/freebsd/contrib/wpa/src/wps/wps_i.h b/freebsd/contrib/wpa/src/wps/wps_i.h index fe0c60bd..2cf22d4b 100644 --- a/freebsd/contrib/wpa/src/wps/wps_i.h +++ b/freebsd/contrib/wpa/src/wps/wps_i.h @@ -125,6 +125,8 @@ struct wps_data { int pbc_in_m1; struct wps_nfc_pw_token *nfc_pw_token; + + int multi_ap_backhaul_sta; }; @@ -163,7 +165,8 @@ int wps_build_encr_settings(struct wps_data *wps, struct wpabuf *msg, struct wpabuf *plain); int wps_build_version(struct wpabuf *msg); int wps_build_wfa_ext(struct wpabuf *msg, int req_to_enroll, - const u8 *auth_macs, size_t auth_macs_count); + const u8 *auth_macs, size_t auth_macs_count, + u8 multi_ap_subelem); int wps_build_msg_type(struct wpabuf *msg, enum wps_msg_type msg_type); int wps_build_enrollee_nonce(struct wps_data *wps, struct wpabuf *msg); int wps_build_registrar_nonce(struct wps_data *wps, struct wpabuf *msg); diff --git a/freebsd/contrib/wpa/src/wps/wps_registrar.c b/freebsd/contrib/wpa/src/wps/wps_registrar.c index 803569ea..df30cfb4 100644 --- a/freebsd/contrib/wpa/src/wps/wps_registrar.c +++ b/freebsd/contrib/wpa/src/wps/wps_registrar.c @@ -190,6 +190,37 @@ struct wps_registrar { #ifdef WPS_WORKAROUNDS struct os_reltime pbc_ignore_start; #endif /* WPS_WORKAROUNDS */ + + /** + * multi_ap_backhaul_ssid - SSID to supply to a Multi-AP backhaul + * enrollee + * + * This SSID is used by the Registrar to fill in information for + * Credentials when the enrollee advertises it is a Multi-AP backhaul + * STA. + */ + u8 multi_ap_backhaul_ssid[SSID_MAX_LEN]; + + /** + * multi_ap_backhaul_ssid_len - Length of multi_ap_backhaul_ssid in + * octets + */ + size_t multi_ap_backhaul_ssid_len; + + /** + * multi_ap_backhaul_network_key - The Network Key (PSK) for the + * Multi-AP backhaul enrollee. + * + * This key can be either the ASCII passphrase (8..63 characters) or the + * 32-octet PSK (64 hex characters). + */ + u8 *multi_ap_backhaul_network_key; + + /** + * multi_ap_backhaul_network_key_len - Length of + * multi_ap_backhaul_network_key in octets + */ + size_t multi_ap_backhaul_network_key_len; }; @@ -669,6 +700,22 @@ wps_registrar_init(struct wps_context *wps, reg->dualband = cfg->dualband; reg->force_per_enrollee_psk = cfg->force_per_enrollee_psk; + if (cfg->multi_ap_backhaul_ssid) { + os_memcpy(reg->multi_ap_backhaul_ssid, + cfg->multi_ap_backhaul_ssid, + cfg->multi_ap_backhaul_ssid_len); + reg->multi_ap_backhaul_ssid_len = + cfg->multi_ap_backhaul_ssid_len; + } + if (cfg->multi_ap_backhaul_network_key) { + reg->multi_ap_backhaul_network_key = + os_memdup(cfg->multi_ap_backhaul_network_key, + cfg->multi_ap_backhaul_network_key_len); + if (reg->multi_ap_backhaul_network_key) + reg->multi_ap_backhaul_network_key_len = + cfg->multi_ap_backhaul_network_key_len; + } + if (wps_set_ie(reg)) { wps_registrar_deinit(reg); return NULL; @@ -706,6 +753,8 @@ void wps_registrar_deinit(struct wps_registrar *reg) eloop_cancel_timeout(wps_registrar_set_selected_timeout, reg, NULL); wps_registrar_flush(reg); wpabuf_clear_free(reg->extra_cred); + bin_clear_free(reg->multi_ap_backhaul_network_key, + reg->multi_ap_backhaul_network_key_len); os_free(reg); } @@ -750,12 +799,11 @@ int wps_registrar_add_pin(struct wps_registrar *reg, const u8 *addr, p->wildcard_uuid = 1; else os_memcpy(p->uuid, uuid, WPS_UUID_LEN); - p->pin = os_malloc(pin_len); + p->pin = os_memdup(pin, pin_len); if (p->pin == NULL) { os_free(p); return -1; } - os_memcpy(p->pin, pin, pin_len); p->pin_len = pin_len; if (timeout) { @@ -883,6 +931,7 @@ static const u8 * wps_registrar_get_pin(struct wps_registrar *reg, const u8 *uuid, size_t *pin_len) { struct wps_uuid_pin *pin, *found = NULL; + int wildcard = 0; wps_registrar_expire_pins(reg); @@ -902,7 +951,7 @@ static const u8 * wps_registrar_get_pin(struct wps_registrar *reg, pin->wildcard_uuid == 2) { wpa_printf(MSG_DEBUG, "WPS: Found a wildcard " "PIN. Assigned it for this UUID-E"); - pin->wildcard_uuid++; + wildcard = 1; os_memcpy(pin->uuid, uuid, WPS_UUID_LEN); found = pin; break; @@ -924,6 +973,8 @@ static const u8 * wps_registrar_get_pin(struct wps_registrar *reg, } *pin_len = found->pin_len; found->flags |= PIN_LOCKED; + if (wildcard) + found->wildcard_uuid++; return found->pin; } @@ -1281,7 +1332,7 @@ static int wps_set_ie(struct wps_registrar *reg) wps_build_sel_reg_config_methods(reg, beacon) || wps_build_sel_pbc_reg_uuid_e(reg, beacon) || (reg->dualband && wps_build_rf_bands(®->wps->dev, beacon, 0)) || - wps_build_wfa_ext(beacon, 0, auth_macs, count) || + wps_build_wfa_ext(beacon, 0, auth_macs, count, 0) || wps_build_vendor_ext(®->wps->dev, beacon)) { wpabuf_free(beacon); wpabuf_free(probe); @@ -1311,7 +1362,7 @@ static int wps_set_ie(struct wps_registrar *reg) wps_build_device_attrs(®->wps->dev, probe) || wps_build_probe_config_methods(reg, probe) || (reg->dualband && wps_build_rf_bands(®->wps->dev, probe, 0)) || - wps_build_wfa_ext(probe, 0, auth_macs, count) || + wps_build_wfa_ext(probe, 0, auth_macs, count, 0) || wps_build_vendor_ext(®->wps->dev, probe)) { wpabuf_free(beacon); wpabuf_free(probe); @@ -1406,10 +1457,9 @@ static int wps_get_dev_password(struct wps_data *wps) return -1; } - wps->dev_password = os_malloc(pin_len); + wps->dev_password = os_memdup(pin, pin_len); if (wps->dev_password == NULL) return -1; - os_memcpy(wps->dev_password, pin, pin_len); wps->dev_password_len = pin_len; return 0; @@ -1593,6 +1643,7 @@ int wps_build_credential_wrap(struct wpabuf *msg, int wps_build_cred(struct wps_data *wps, struct wpabuf *msg) { struct wpabuf *cred; + struct wps_registrar *reg = wps->wps->registrar; if (wps->wps->registrar->skip_cred_build) goto skip_cred_build; @@ -1604,6 +1655,29 @@ int wps_build_cred(struct wps_data *wps, struct wpabuf *msg) } os_memset(&wps->cred, 0, sizeof(wps->cred)); + if (wps->peer_dev.multi_ap_ext == MULTI_AP_BACKHAUL_STA && + reg->multi_ap_backhaul_ssid_len) { + wpa_printf(MSG_DEBUG, "WPS: Use backhaul STA credentials"); + os_memcpy(wps->cred.ssid, reg->multi_ap_backhaul_ssid, + reg->multi_ap_backhaul_ssid_len); + wps->cred.ssid_len = reg->multi_ap_backhaul_ssid_len; + /* Backhaul is always WPA2PSK */ + wps->cred.auth_type = WPS_AUTH_WPA2PSK; + wps->cred.encr_type = WPS_ENCR_AES; + /* Set MAC address in the Credential to be the Enrollee's MAC + * address + */ + os_memcpy(wps->cred.mac_addr, wps->mac_addr_e, ETH_ALEN); + if (reg->multi_ap_backhaul_network_key) { + os_memcpy(wps->cred.key, + reg->multi_ap_backhaul_network_key, + reg->multi_ap_backhaul_network_key_len); + wps->cred.key_len = + reg->multi_ap_backhaul_network_key_len; + } + goto use_provided; + } + os_memcpy(wps->cred.ssid, wps->wps->ssid, wps->wps->ssid_len); wps->cred.ssid_len = wps->wps->ssid_len; @@ -1846,7 +1920,7 @@ static struct wpabuf * wps_build_m2(struct wps_data *wps) wps_build_config_error(msg, WPS_CFG_NO_ERROR) || wps_build_dev_password_id(msg, wps->dev_pw_id) || wps_build_os_version(&wps->wps->dev, msg) || - wps_build_wfa_ext(msg, 0, NULL, 0)) { + wps_build_wfa_ext(msg, 0, NULL, 0, 0)) { wpabuf_free(msg); return NULL; } @@ -1914,7 +1988,7 @@ static struct wpabuf * wps_build_m2d(struct wps_data *wps) wps_build_assoc_state(wps, msg) || wps_build_config_error(msg, err) || wps_build_os_version(&wps->wps->dev, msg) || - wps_build_wfa_ext(msg, 0, NULL, 0)) { + wps_build_wfa_ext(msg, 0, NULL, 0, 0)) { wpabuf_free(msg); return NULL; } @@ -1950,7 +2024,7 @@ static struct wpabuf * wps_build_m4(struct wps_data *wps) wps_build_r_snonce1(wps, plain) || wps_build_key_wrap_auth(wps, plain) || wps_build_encr_settings(wps, msg, plain) || - wps_build_wfa_ext(msg, 0, NULL, 0) || + wps_build_wfa_ext(msg, 0, NULL, 0, 0) || wps_build_authenticator(wps, msg)) { wpabuf_clear_free(plain); wpabuf_free(msg); @@ -1985,7 +2059,7 @@ static struct wpabuf * wps_build_m6(struct wps_data *wps) wps_build_r_snonce2(wps, plain) || wps_build_key_wrap_auth(wps, plain) || wps_build_encr_settings(wps, msg, plain) || - wps_build_wfa_ext(msg, 0, NULL, 0) || + wps_build_wfa_ext(msg, 0, NULL, 0, 0) || wps_build_authenticator(wps, msg)) { wpabuf_clear_free(plain); wpabuf_free(msg); @@ -2022,7 +2096,7 @@ static struct wpabuf * wps_build_m8(struct wps_data *wps) (!wps->wps->ap && !wps->er && wps_build_ap_settings(wps, plain)) || wps_build_key_wrap_auth(wps, plain) || wps_build_encr_settings(wps, msg, plain) || - wps_build_wfa_ext(msg, 0, NULL, 0) || + wps_build_wfa_ext(msg, 0, NULL, 0, 0) || wps_build_authenticator(wps, msg)) { wpabuf_clear_free(plain); wpabuf_clear_free(msg); @@ -2706,6 +2780,7 @@ static enum wps_process_res wps_process_m1(struct wps_data *wps, wps->use_psk_key = 1; } #endif /* WPS_WORKAROUNDS */ + wps_process_vendor_ext_m1(&wps->peer_dev, attr->multi_ap_ext); wps->state = SEND_M2; return WPS_CONTINUE; diff --git a/freebsd/contrib/wpa/src/wps/wps_upnp.c b/freebsd/contrib/wpa/src/wps/wps_upnp.c index b69d2026..71c46739 100644 --- a/freebsd/contrib/wpa/src/wps/wps_upnp.c +++ b/freebsd/contrib/wpa/src/wps/wps_upnp.c @@ -601,7 +601,7 @@ static struct wpabuf * build_fake_wsc_ack(void) wpabuf_put_be16(msg, ATTR_REGISTRAR_NONCE); wpabuf_put_be16(msg, WPS_NONCE_LEN); wpabuf_put(msg, WPS_NONCE_LEN); - if (wps_build_wfa_ext(msg, 0, NULL, 0)) { + if (wps_build_wfa_ext(msg, 0, NULL, 0, 0)) { wpabuf_free(msg); return NULL; } diff --git a/freebsd/contrib/wpa/wpa_supplicant/ap.h b/freebsd/contrib/wpa/wpa_supplicant/ap.h index 5a59ddcc..447b5518 100644 --- a/freebsd/contrib/wpa/wpa_supplicant/ap.h +++ b/freebsd/contrib/wpa/wpa_supplicant/ap.h @@ -85,17 +85,20 @@ int wpas_ap_stop_ap(struct wpa_supplicant *wpa_s); int wpas_ap_pmksa_cache_list(struct wpa_supplicant *wpa_s, char *buf, size_t len); void wpas_ap_pmksa_cache_flush(struct wpa_supplicant *wpa_s); +int wpas_ap_pmksa_cache_list_mesh(struct wpa_supplicant *wpa_s, const u8 *addr, + char *buf, size_t len); +int wpas_ap_pmksa_cache_add_external(struct wpa_supplicant *wpa_s, char *cmd); -void wpas_event_dfs_radar_detected(struct wpa_supplicant *wpa_s, +void wpas_ap_event_dfs_radar_detected(struct wpa_supplicant *wpa_s, + struct dfs_event *radar); +void wpas_ap_event_dfs_cac_started(struct wpa_supplicant *wpa_s, struct dfs_event *radar); -void wpas_event_dfs_cac_started(struct wpa_supplicant *wpa_s, - struct dfs_event *radar); -void wpas_event_dfs_cac_finished(struct wpa_supplicant *wpa_s, - struct dfs_event *radar); -void wpas_event_dfs_cac_aborted(struct wpa_supplicant *wpa_s, - struct dfs_event *radar); -void wpas_event_dfs_cac_nop_finished(struct wpa_supplicant *wpa_s, - struct dfs_event *radar); +void wpas_ap_event_dfs_cac_finished(struct wpa_supplicant *wpa_s, + struct dfs_event *radar); +void wpas_ap_event_dfs_cac_aborted(struct wpa_supplicant *wpa_s, + struct dfs_event *radar); +void wpas_ap_event_dfs_cac_nop_finished(struct wpa_supplicant *wpa_s, + struct dfs_event *radar); void ap_periodic(struct wpa_supplicant *wpa_s); diff --git a/freebsd/contrib/wpa/wpa_supplicant/bss.c b/freebsd/contrib/wpa/wpa_supplicant/bss.c index 4f805b1b..f9b703bb 100644 --- a/freebsd/contrib/wpa/wpa_supplicant/bss.c +++ b/freebsd/contrib/wpa/wpa_supplicant/bss.c @@ -2,7 +2,7 @@ /* * BSS table - * Copyright (c) 2009-2015, Jouni Malinen <j@w1.fi> + * Copyright (c) 2009-2019, Jouni Malinen <j@w1.fi> * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -95,6 +95,7 @@ static struct wpa_bss_anqp * wpa_bss_anqp_clone(struct wpa_bss_anqp *anqp) ANQP_DUP(nai_realm); ANQP_DUP(anqp_3gpp); ANQP_DUP(domain_name); + ANQP_DUP(fils_realm_info); #endif /* CONFIG_INTERWORKING */ #ifdef CONFIG_HS20 ANQP_DUP(hs20_capability_list); @@ -103,6 +104,8 @@ static struct wpa_bss_anqp * wpa_bss_anqp_clone(struct wpa_bss_anqp *anqp) ANQP_DUP(hs20_connection_capability); ANQP_DUP(hs20_operating_class); ANQP_DUP(hs20_osu_providers_list); + ANQP_DUP(hs20_operator_icon_metadata); + ANQP_DUP(hs20_osu_providers_nai_list); #endif /* CONFIG_HS20 */ #undef ANQP_DUP @@ -170,6 +173,7 @@ static void wpa_bss_anqp_free(struct wpa_bss_anqp *anqp) wpabuf_free(anqp->nai_realm); wpabuf_free(anqp->anqp_3gpp); wpabuf_free(anqp->domain_name); + wpabuf_free(anqp->fils_realm_info); while ((elem = dl_list_first(&anqp->anqp_elems, struct wpa_bss_anqp_elem, list))) { @@ -185,6 +189,8 @@ static void wpa_bss_anqp_free(struct wpa_bss_anqp *anqp) wpabuf_free(anqp->hs20_connection_capability); wpabuf_free(anqp->hs20_operating_class); wpabuf_free(anqp->hs20_osu_providers_list); + wpabuf_free(anqp->hs20_operator_icon_metadata); + wpabuf_free(anqp->hs20_osu_providers_nai_list); #endif /* CONFIG_HS20 */ os_free(anqp); @@ -269,9 +275,9 @@ struct wpa_bss * wpa_bss_get(struct wpa_supplicant *wpa_s, const u8 *bssid, } -static void calculate_update_time(const struct os_reltime *fetch_time, - unsigned int age_ms, - struct os_reltime *update_time) +void calculate_update_time(const struct os_reltime *fetch_time, + unsigned int age_ms, + struct os_reltime *update_time) { os_time_t usec; @@ -597,6 +603,42 @@ wpa_bss_update(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, { u32 changes; + if (bss->last_update_idx == wpa_s->bss_update_idx) { + struct os_reltime update_time; + + /* + * Some drivers (e.g., cfg80211) include multiple BSS entries + * for the same BSS if that BSS's channel changes. The BSS list + * implementation in wpa_supplicant does not do that and we need + * to filter out the obsolete results here to make sure only the + * most current BSS information remains in the table. + */ + wpa_printf(MSG_DEBUG, "BSS: " MACSTR + " has multiple entries in the scan results - select the most current one", + MAC2STR(bss->bssid)); + calculate_update_time(fetch_time, res->age, &update_time); + wpa_printf(MSG_DEBUG, + "Previous last_update: %u.%06u (freq %d%s)", + (unsigned int) bss->last_update.sec, + (unsigned int) bss->last_update.usec, + bss->freq, + (bss->flags & WPA_BSS_ASSOCIATED) ? " assoc" : ""); + wpa_printf(MSG_DEBUG, "New last_update: %u.%06u (freq %d%s)", + (unsigned int) update_time.sec, + (unsigned int) update_time.usec, + res->freq, + (res->flags & WPA_SCAN_ASSOCIATED) ? " assoc" : ""); + if ((bss->flags & WPA_BSS_ASSOCIATED) || + (!(res->flags & WPA_SCAN_ASSOCIATED) && + !os_reltime_before(&bss->last_update, &update_time))) { + wpa_printf(MSG_DEBUG, + "Ignore this BSS entry since the previous update looks more current"); + return bss; + } + wpa_printf(MSG_DEBUG, + "Accept this BSS entry since it looks more current than the previous update"); + } + changes = wpa_bss_compare_res(bss, res); if (changes & WPA_BSS_FREQ_CHANGED_FLAG) wpa_printf(MSG_DEBUG, "BSS: " MACSTR " changed freq %d --> %d", @@ -1281,3 +1323,26 @@ int wpa_bss_get_bit_rates(const struct wpa_bss *bss, u8 **rates) *rates = r; return len; } + + +#ifdef CONFIG_FILS +const u8 * wpa_bss_get_fils_cache_id(struct wpa_bss *bss) +{ + const u8 *ie; + + if (bss) { + ie = wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION); + if (ie && ie[1] >= 4 && WPA_GET_LE16(ie + 2) & BIT(7)) + return ie + 4; + } + + return NULL; +} +#endif /* CONFIG_FILS */ + + +int wpa_bss_ext_capab(const struct wpa_bss *bss, unsigned int capab) +{ + return ieee802_11_ext_capab(wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB), + capab); +} diff --git a/freebsd/contrib/wpa/wpa_supplicant/bss.h b/freebsd/contrib/wpa/wpa_supplicant/bss.h index 84e8fb07..3ce8cd3f 100644 --- a/freebsd/contrib/wpa/wpa_supplicant/bss.h +++ b/freebsd/contrib/wpa/wpa_supplicant/bss.h @@ -1,6 +1,6 @@ /* * BSS table - * Copyright (c) 2009-2015, Jouni Malinen <j@w1.fi> + * Copyright (c) 2009-2019, Jouni Malinen <j@w1.fi> * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -40,6 +40,7 @@ struct wpa_bss_anqp { struct wpabuf *nai_realm; struct wpabuf *anqp_3gpp; struct wpabuf *domain_name; + struct wpabuf *fils_realm_info; struct dl_list anqp_elems; /* list of struct wpa_bss_anqp_elem */ #endif /* CONFIG_INTERWORKING */ #ifdef CONFIG_HS20 @@ -49,6 +50,8 @@ struct wpa_bss_anqp { struct wpabuf *hs20_connection_capability; struct wpabuf *hs20_operating_class; struct wpabuf *hs20_osu_providers_list; + struct wpabuf *hs20_operator_icon_metadata; + struct wpabuf *hs20_osu_providers_nai_list; #endif /* CONFIG_HS20 */ }; @@ -144,6 +147,8 @@ int wpa_bss_get_max_rate(const struct wpa_bss *bss); int wpa_bss_get_bit_rates(const struct wpa_bss *bss, u8 **rates); struct wpa_bss_anqp * wpa_bss_anqp_alloc(void); int wpa_bss_anqp_unshare_alloc(struct wpa_bss *bss); +const u8 * wpa_bss_get_fils_cache_id(struct wpa_bss *bss); +int wpa_bss_ext_capab(const struct wpa_bss *bss, unsigned int capab); static inline int bss_is_dmg(const struct wpa_bss *bss) { @@ -167,4 +172,8 @@ static inline void wpa_bss_update_level(struct wpa_bss *bss, int new_level) bss->level = new_level; } +void calculate_update_time(const struct os_reltime *fetch_time, + unsigned int age_ms, + struct os_reltime *update_time); + #endif /* BSS_H */ diff --git a/freebsd/contrib/wpa/wpa_supplicant/config.c b/freebsd/contrib/wpa/wpa_supplicant/config.c index cf9da641..0eac7a9e 100644 --- a/freebsd/contrib/wpa/wpa_supplicant/config.c +++ b/freebsd/contrib/wpa/wpa_supplicant/config.c @@ -2,7 +2,7 @@ /* * WPA Supplicant / Configuration parser and common functions - * Copyright (c) 2003-2015, Jouni Malinen <j@w1.fi> + * Copyright (c) 2003-2018, Jouni Malinen <j@w1.fi> * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -13,6 +13,7 @@ #include "common.h" #include "utils/uuid.h" #include "utils/ip_addr.h" +#include "common/ieee802_1x_defs.h" #include "crypto/sha1.h" #include "rsn_supp/wpa.h" #include "eap_peer/eap.h" @@ -398,6 +399,50 @@ static char * wpa_config_write_bssid(const struct parse_data *data, #endif /* NO_CONFIG_WRITE */ +static int wpa_config_parse_bssid_hint(const struct parse_data *data, + struct wpa_ssid *ssid, int line, + const char *value) +{ + if (value[0] == '\0' || os_strcmp(value, "\"\"") == 0 || + os_strcmp(value, "any") == 0) { + ssid->bssid_hint_set = 0; + wpa_printf(MSG_MSGDUMP, "BSSID hint any"); + return 0; + } + if (hwaddr_aton(value, ssid->bssid_hint)) { + wpa_printf(MSG_ERROR, "Line %d: Invalid BSSID hint '%s'.", + line, value); + return -1; + } + ssid->bssid_hint_set = 1; + wpa_hexdump(MSG_MSGDUMP, "BSSID hint", ssid->bssid_hint, ETH_ALEN); + return 0; +} + + +#ifndef NO_CONFIG_WRITE +static char * wpa_config_write_bssid_hint(const struct parse_data *data, + struct wpa_ssid *ssid) +{ + char *value; + int res; + + if (!ssid->bssid_hint_set) + return NULL; + + value = os_malloc(20); + if (!value) + return NULL; + res = os_snprintf(value, 20, MACSTR, MAC2STR(ssid->bssid_hint)); + if (os_snprintf_error(20, res)) { + os_free(value); + return NULL; + } + return value; +} +#endif /* NO_CONFIG_WRITE */ + + static int wpa_config_parse_bssid_blacklist(const struct parse_data *data, struct wpa_ssid *ssid, int line, const char *value) @@ -692,6 +737,10 @@ static int wpa_config_parse_key_mgmt(const struct parse_data *data, val |= WPA_KEY_MGMT_FT_PSK; else if (os_strcmp(start, "FT-EAP") == 0) val |= WPA_KEY_MGMT_FT_IEEE8021X; +#ifdef CONFIG_SHA384 + else if (os_strcmp(start, "FT-EAP-SHA384") == 0) + val |= WPA_KEY_MGMT_FT_IEEE8021X_SHA384; +#endif /* CONFIG_SHA384 */ #endif /* CONFIG_IEEE80211R */ #ifdef CONFIG_IEEE80211W else if (os_strcmp(start, "WPA-PSK-SHA256") == 0) @@ -721,6 +770,26 @@ static int wpa_config_parse_key_mgmt(const struct parse_data *data, else if (os_strcmp(start, "WPA-EAP-SUITE-B-192") == 0) val |= WPA_KEY_MGMT_IEEE8021X_SUITE_B_192; #endif /* CONFIG_SUITEB192 */ +#ifdef CONFIG_FILS + else if (os_strcmp(start, "FILS-SHA256") == 0) + val |= WPA_KEY_MGMT_FILS_SHA256; + else if (os_strcmp(start, "FILS-SHA384") == 0) + val |= WPA_KEY_MGMT_FILS_SHA384; +#ifdef CONFIG_IEEE80211R + else if (os_strcmp(start, "FT-FILS-SHA256") == 0) + val |= WPA_KEY_MGMT_FT_FILS_SHA256; + else if (os_strcmp(start, "FT-FILS-SHA384") == 0) + val |= WPA_KEY_MGMT_FT_FILS_SHA384; +#endif /* CONFIG_IEEE80211R */ +#endif /* CONFIG_FILS */ +#ifdef CONFIG_OWE + else if (os_strcmp(start, "OWE") == 0) + val |= WPA_KEY_MGMT_OWE; +#endif /* CONFIG_OWE */ +#ifdef CONFIG_DPP + else if (os_strcmp(start, "DPP") == 0) + val |= WPA_KEY_MGMT_DPP; +#endif /* CONFIG_DPP */ else { wpa_printf(MSG_ERROR, "Line %d: invalid key_mgmt '%s'", line, start); @@ -829,6 +898,18 @@ static char * wpa_config_write_key_mgmt(const struct parse_data *data, } pos += ret; } + +#ifdef CONFIG_SHA384 + if (ssid->key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X_SHA384) { + ret = os_snprintf(pos, end - pos, "%sFT-EAP-SHA384", + pos == buf ? "" : " "); + if (os_snprintf_error(end - pos, ret)) { + end[-1] = '\0'; + return buf; + } + pos += ret; + } +#endif /* CONFIG_SHA384 */ #endif /* CONFIG_IEEE80211R */ #ifdef CONFIG_IEEE80211W @@ -923,6 +1004,71 @@ static char * wpa_config_write_key_mgmt(const struct parse_data *data, } #endif /* CONFIG_SUITEB192 */ +#ifdef CONFIG_FILS + if (ssid->key_mgmt & WPA_KEY_MGMT_FILS_SHA256) { + ret = os_snprintf(pos, end - pos, "%sFILS-SHA256", + pos == buf ? "" : " "); + if (os_snprintf_error(end - pos, ret)) { + end[-1] = '\0'; + return buf; + } + pos += ret; + } + if (ssid->key_mgmt & WPA_KEY_MGMT_FILS_SHA384) { + ret = os_snprintf(pos, end - pos, "%sFILS-SHA384", + pos == buf ? "" : " "); + if (os_snprintf_error(end - pos, ret)) { + end[-1] = '\0'; + return buf; + } + pos += ret; + } +#ifdef CONFIG_IEEE80211R + if (ssid->key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA256) { + ret = os_snprintf(pos, end - pos, "%sFT-FILS-SHA256", + pos == buf ? "" : " "); + if (os_snprintf_error(end - pos, ret)) { + end[-1] = '\0'; + return buf; + } + pos += ret; + } + if (ssid->key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA384) { + ret = os_snprintf(pos, end - pos, "%sFT-FILS-SHA384", + pos == buf ? "" : " "); + if (os_snprintf_error(end - pos, ret)) { + end[-1] = '\0'; + return buf; + } + pos += ret; + } +#endif /* CONFIG_IEEE80211R */ +#endif /* CONFIG_FILS */ + +#ifdef CONFIG_DPP + if (ssid->key_mgmt & WPA_KEY_MGMT_DPP) { + ret = os_snprintf(pos, end - pos, "%sDPP", + pos == buf ? "" : " "); + if (os_snprintf_error(end - pos, ret)) { + end[-1] = '\0'; + return buf; + } + pos += ret; + } +#endif /* CONFIG_DPP */ + +#ifdef CONFIG_OWE + if (ssid->key_mgmt & WPA_KEY_MGMT_OWE) { + ret = os_snprintf(pos, end - pos, "%sOWE", + pos == buf ? "" : " "); + if (os_snprintf_error(end - pos, ret)) { + end[-1] = '\0'; + return buf; + } + pos += ret; + } +#endif /* CONFIG_OWE */ + if (pos == buf) { os_free(buf); buf = NULL; @@ -1044,6 +1190,40 @@ static char * wpa_config_write_group(const struct parse_data *data, #endif /* NO_CONFIG_WRITE */ +static int wpa_config_parse_group_mgmt(const struct parse_data *data, + struct wpa_ssid *ssid, int line, + const char *value) +{ + int val; + + val = wpa_config_parse_cipher(line, value); + if (val == -1) + return -1; + + if (val & ~WPA_ALLOWED_GROUP_MGMT_CIPHERS) { + wpa_printf(MSG_ERROR, + "Line %d: not allowed group management cipher (0x%x).", + line, val); + return -1; + } + + if (ssid->group_mgmt_cipher == val) + return 1; + wpa_printf(MSG_MSGDUMP, "group_mgmt: 0x%x", val); + ssid->group_mgmt_cipher = val; + return 0; +} + + +#ifndef NO_CONFIG_WRITE +static char * wpa_config_write_group_mgmt(const struct parse_data *data, + struct wpa_ssid *ssid) +{ + return wpa_config_write_cipher(ssid->group_mgmt_cipher); +} +#endif /* NO_CONFIG_WRITE */ + + static int wpa_config_parse_auth_alg(const struct parse_data *data, struct wpa_ssid *ssid, int line, const char *value) @@ -1818,6 +1998,140 @@ static char * wpa_config_write_mesh_basic_rates(const struct parse_data *data, #endif /* CONFIG_MESH */ +#ifdef CONFIG_MACSEC + +static int wpa_config_parse_mka_cak(const struct parse_data *data, + struct wpa_ssid *ssid, int line, + const char *value) +{ + size_t len; + + len = os_strlen(value); + if (len > 2 * MACSEC_CAK_MAX_LEN || + (len != 2 * 16 && len != 2 * 32) || + hexstr2bin(value, ssid->mka_cak, len / 2)) { + wpa_printf(MSG_ERROR, "Line %d: Invalid MKA-CAK '%s'.", + line, value); + return -1; + } + ssid->mka_cak_len = len / 2; + ssid->mka_psk_set |= MKA_PSK_SET_CAK; + + wpa_hexdump_key(MSG_MSGDUMP, "MKA-CAK", ssid->mka_cak, + ssid->mka_cak_len); + return 0; +} + + +static int wpa_config_parse_mka_ckn(const struct parse_data *data, + struct wpa_ssid *ssid, int line, + const char *value) +{ + size_t len; + + len = os_strlen(value); + if (len > 2 * MACSEC_CKN_MAX_LEN || /* too long */ + len < 2 || /* too short */ + len % 2 != 0 /* not an integral number of bytes */) { + wpa_printf(MSG_ERROR, "Line %d: Invalid MKA-CKN '%s'.", + line, value); + return -1; + } + ssid->mka_ckn_len = len / 2; + if (hexstr2bin(value, ssid->mka_ckn, ssid->mka_ckn_len)) { + wpa_printf(MSG_ERROR, "Line %d: Invalid MKA-CKN '%s'.", + line, value); + return -1; + } + + ssid->mka_psk_set |= MKA_PSK_SET_CKN; + + wpa_hexdump_key(MSG_MSGDUMP, "MKA-CKN", ssid->mka_ckn, + ssid->mka_ckn_len); + return 0; +} + + +#ifndef NO_CONFIG_WRITE + +static char * wpa_config_write_mka_cak(const struct parse_data *data, + struct wpa_ssid *ssid) +{ + if (!(ssid->mka_psk_set & MKA_PSK_SET_CAK)) + return NULL; + + return wpa_config_write_string_hex(ssid->mka_cak, ssid->mka_cak_len); +} + + +static char * wpa_config_write_mka_ckn(const struct parse_data *data, + struct wpa_ssid *ssid) +{ + if (!(ssid->mka_psk_set & MKA_PSK_SET_CKN)) + return NULL; + return wpa_config_write_string_hex(ssid->mka_ckn, ssid->mka_ckn_len); +} + +#endif /* NO_CONFIG_WRITE */ + +#endif /* CONFIG_MACSEC */ + + +#ifdef CONFIG_OCV + +static int wpa_config_parse_ocv(const struct parse_data *data, + struct wpa_ssid *ssid, int line, + const char *value) +{ + char *end; + + ssid->ocv = strtol(value, &end, 0); + if (*end || ssid->ocv < 0 || ssid->ocv > 1) { + wpa_printf(MSG_ERROR, "Line %d: Invalid ocv value '%s'.", + line, value); + return -1; + } + if (ssid->ocv && ssid->ieee80211w == NO_MGMT_FRAME_PROTECTION) + ssid->ieee80211w = MGMT_FRAME_PROTECTION_OPTIONAL; + return 0; +} + + +#ifndef NO_CONFIG_WRITE +static char * wpa_config_write_ocv(const struct parse_data *data, + struct wpa_ssid *ssid) +{ + char *value = os_malloc(20); + + if (!value) + return NULL; + os_snprintf(value, 20, "%d", ssid->ocv); + value[20 - 1] = '\0'; + return value; +} +#endif /* NO_CONFIG_WRITE */ + +#endif /* CONFIG_OCV */ + + +static int wpa_config_parse_peerkey(const struct parse_data *data, + struct wpa_ssid *ssid, int line, + const char *value) +{ + wpa_printf(MSG_INFO, "NOTE: Obsolete peerkey parameter ignored"); + return 0; +} + + +#ifndef NO_CONFIG_WRITE +static char * wpa_config_write_peerkey(const struct parse_data *data, + struct wpa_ssid *ssid) +{ + return NULL; +} +#endif /* NO_CONFIG_WRITE */ + + /* Helper macros for network block parser */ #ifdef OFFSET @@ -1909,24 +2223,34 @@ static const struct parse_data ssid_fields[] = { { STR_RANGE(ssid, 0, SSID_MAX_LEN) }, { INT_RANGE(scan_ssid, 0, 1) }, { FUNC(bssid) }, + { FUNC(bssid_hint) }, { FUNC(bssid_blacklist) }, { FUNC(bssid_whitelist) }, { FUNC_KEY(psk) }, { INT(mem_only_psk) }, + { STR_KEY(sae_password) }, + { STR(sae_password_id) }, { FUNC(proto) }, { FUNC(key_mgmt) }, { INT(bg_scan_period) }, { FUNC(pairwise) }, { FUNC(group) }, + { FUNC(group_mgmt) }, { FUNC(auth_alg) }, { FUNC(scan_freq) }, { FUNC(freq_list) }, + { INT_RANGE(ht, 0, 1) }, + { INT_RANGE(vht, 0, 1) }, + { INT_RANGE(ht40, -1, 1) }, { INT_RANGE(max_oper_chwidth, VHT_CHANWIDTH_USE_HT, VHT_CHANWIDTH_80P80MHZ) }, + { INT(vht_center_freq1) }, + { INT(vht_center_freq2) }, #ifdef IEEE8021X_EAPOL { FUNC(eap) }, { STR_LENe(identity) }, { STR_LENe(anonymous_identity) }, + { STR_LENe(imsi_identity) }, { FUNC_KEY(password) }, { STRe(ca_cert) }, { STRe(ca_path) }, @@ -1935,6 +2259,7 @@ static const struct parse_data ssid_fields[] = { { STR_KEYe(private_key_passwd) }, { STRe(dh_file) }, { STRe(subject_match) }, + { STRe(check_cert_subject) }, { STRe(altsubject_match) }, { STRe(domain_suffix_match) }, { STRe(domain_match) }, @@ -1945,6 +2270,7 @@ static const struct parse_data ssid_fields[] = { { STR_KEYe(private_key2_passwd) }, { STRe(dh_file2) }, { STRe(subject_match2) }, + { STRe(check_cert_subject2) }, { STRe(altsubject_match2) }, { STRe(domain_suffix_match2) }, { STRe(domain_match2) }, @@ -1983,6 +2309,7 @@ static const struct parse_data ssid_fields[] = { #ifdef CONFIG_MESH { INT_RANGE(mode, 0, 5) }, { INT_RANGE(no_auto_peer, 0, 1) }, + { INT_RANGE(mesh_rssi_threshold, -255, 1) }, #else /* CONFIG_MESH */ { INT_RANGE(mode, 0, 4) }, #endif /* CONFIG_MESH */ @@ -1992,7 +2319,10 @@ static const struct parse_data ssid_fields[] = { #ifdef CONFIG_IEEE80211W { INT_RANGE(ieee80211w, 0, 2) }, #endif /* CONFIG_IEEE80211W */ - { INT_RANGE(peerkey, 0, 1) }, +#ifdef CONFIG_OCV + { FUNC(ocv) }, +#endif /* CONFIG_OCV */ + { FUNC(peerkey) /* obsolete - removed */ }, { INT_RANGE(mixed_cell, 0, 1) }, { INT_RANGE(frequency, 0, 65000) }, { INT_RANGE(fixed_freq, 0, 1) }, @@ -2021,6 +2351,8 @@ static const struct parse_data ssid_fields[] = { { INT_RANGE(disable_sgi, 0, 1) }, { INT_RANGE(disable_ldpc, 0, 1) }, { INT_RANGE(ht40_intolerant, 0, 1) }, + { INT_RANGE(tx_stbc, -1, 1) }, + { INT_RANGE(rx_stbc, -1, 3) }, { INT_RANGE(disable_max_amsdu, -1, 1) }, { INT_RANGE(ampdu_factor, -1, 3) }, { INT_RANGE(ampdu_density, -1, 7) }, @@ -2052,13 +2384,31 @@ static const struct parse_data ssid_fields[] = { { INT(beacon_int) }, #ifdef CONFIG_MACSEC { INT_RANGE(macsec_policy, 0, 1) }, + { INT_RANGE(macsec_integ_only, 0, 1) }, + { INT_RANGE(macsec_replay_protect, 0, 1) }, + { INT(macsec_replay_window) }, + { INT_RANGE(macsec_port, 1, 65534) }, + { INT_RANGE(mka_priority, 0, 255) }, + { FUNC_KEY(mka_cak) }, + { FUNC_KEY(mka_ckn) }, #endif /* CONFIG_MACSEC */ #ifdef CONFIG_HS20 { INT(update_identifier) }, + { STR_RANGE(roaming_consortium_selection, 0, MAX_ROAMING_CONS_OI_LEN) }, #endif /* CONFIG_HS20 */ { INT_RANGE(mac_addr, 0, 2) }, { INT_RANGE(pbss, 0, 2) }, { INT_RANGE(wps_disabled, 0, 1) }, + { INT_RANGE(fils_dh_group, 0, 65535) }, +#ifdef CONFIG_DPP + { STR(dpp_connector) }, + { STR_LEN(dpp_netaccesskey) }, + { INT(dpp_netaccesskey_expiry) }, + { STR_LEN(dpp_csign) }, +#endif /* CONFIG_DPP */ + { INT_RANGE(owe_group, 0, 65535) }, + { INT_RANGE(owe_only, 0, 1) }, + { INT_RANGE(multi_ap_backhaul_sta, 0, 1) }, }; #undef OFFSET @@ -2170,6 +2520,7 @@ static void eap_peer_config_free(struct eap_peer_config *eap) os_free(eap->eap_methods); bin_clear_free(eap->identity, eap->identity_len); os_free(eap->anonymous_identity); + os_free(eap->imsi_identity); bin_clear_free(eap->password, eap->password_len); os_free(eap->ca_cert); os_free(eap->ca_path); @@ -2178,6 +2529,7 @@ static void eap_peer_config_free(struct eap_peer_config *eap) str_clear_free(eap->private_key_passwd); os_free(eap->dh_file); os_free(eap->subject_match); + os_free(eap->check_cert_subject); os_free(eap->altsubject_match); os_free(eap->domain_suffix_match); os_free(eap->domain_match); @@ -2188,6 +2540,7 @@ static void eap_peer_config_free(struct eap_peer_config *eap) str_clear_free(eap->private_key2_passwd); os_free(eap->dh_file2); os_free(eap->subject_match2); + os_free(eap->check_cert_subject2); os_free(eap->altsubject_match2); os_free(eap->domain_suffix_match2); os_free(eap->domain_match2); @@ -2228,6 +2581,8 @@ void wpa_config_free_ssid(struct wpa_ssid *ssid) os_free(ssid->ssid); str_clear_free(ssid->passphrase); os_free(ssid->ext_psk); + str_clear_free(ssid->sae_password); + os_free(ssid->sae_password_id); #ifdef IEEE8021X_EAPOL eap_peer_config_free(&ssid->eap); #endif /* IEEE8021X_EAPOL */ @@ -2244,6 +2599,12 @@ void wpa_config_free_ssid(struct wpa_ssid *ssid) #ifdef CONFIG_MESH os_free(ssid->mesh_basic_rates); #endif /* CONFIG_MESH */ +#ifdef CONFIG_HS20 + os_free(ssid->roaming_consortium_selection); +#endif /* CONFIG_HS20 */ + os_free(ssid->dpp_connector); + bin_clear_free(ssid->dpp_netaccesskey, ssid->dpp_netaccesskey_len); + os_free(ssid->dpp_csign); while ((psk = dl_list_first(&ssid->psk_list, struct psk_list_entry, list))) { dl_list_del(&psk->list); @@ -2497,6 +2858,7 @@ void wpa_config_set_network_defaults(struct wpa_ssid *ssid) ssid->group_cipher = DEFAULT_GROUP; ssid->key_mgmt = DEFAULT_KEY_MGMT; ssid->bg_scan_period = DEFAULT_BG_SCAN_PERIOD; + ssid->ht = 1; #ifdef IEEE8021X_EAPOL ssid->eapol_flags = DEFAULT_EAPOL_FLAGS; ssid->eap_workaround = DEFAULT_EAP_WORKAROUND; @@ -2508,12 +2870,15 @@ void wpa_config_set_network_defaults(struct wpa_ssid *ssid) ssid->dot11MeshRetryTimeout = DEFAULT_MESH_RETRY_TIMEOUT; ssid->dot11MeshConfirmTimeout = DEFAULT_MESH_CONFIRM_TIMEOUT; ssid->dot11MeshHoldingTimeout = DEFAULT_MESH_HOLDING_TIMEOUT; + ssid->mesh_rssi_threshold = DEFAULT_MESH_RSSI_THRESHOLD; #endif /* CONFIG_MESH */ #ifdef CONFIG_HT_OVERRIDES ssid->disable_ht = DEFAULT_DISABLE_HT; ssid->disable_ht40 = DEFAULT_DISABLE_HT40; ssid->disable_sgi = DEFAULT_DISABLE_SGI; ssid->disable_ldpc = DEFAULT_DISABLE_LDPC; + ssid->tx_stbc = DEFAULT_TX_STBC; + ssid->rx_stbc = DEFAULT_RX_STBC; ssid->disable_max_amsdu = DEFAULT_DISABLE_MAX_AMSDU; ssid->ampdu_factor = DEFAULT_AMPDU_FACTOR; ssid->ampdu_density = DEFAULT_AMPDU_DENSITY; @@ -2540,7 +2905,11 @@ void wpa_config_set_network_defaults(struct wpa_ssid *ssid) #ifdef CONFIG_IEEE80211W ssid->ieee80211w = MGMT_FRAME_PROTECTION_DEFAULT; #endif /* CONFIG_IEEE80211W */ +#ifdef CONFIG_MACSEC + ssid->mka_priority = DEFAULT_PRIO_NOT_KEY_SERVER; +#endif /* CONFIG_MACSEC */ ssid->mac_addr = -1; + ssid->max_oper_chwidth = DEFAULT_MAX_OPER_CHWIDTH; } @@ -2851,11 +3220,64 @@ static int wpa_config_set_cred_req_conn_capab(struct wpa_cred *cred, } +static int wpa_config_set_cred_roaming_consortiums(struct wpa_cred *cred, + const char *value) +{ + u8 roaming_consortiums[MAX_ROAMING_CONS][MAX_ROAMING_CONS_OI_LEN]; + size_t roaming_consortiums_len[MAX_ROAMING_CONS]; + unsigned int num_roaming_consortiums = 0; + const char *pos, *end; + size_t len; + + os_memset(roaming_consortiums, 0, sizeof(roaming_consortiums)); + os_memset(roaming_consortiums_len, 0, sizeof(roaming_consortiums_len)); + + for (pos = value;;) { + end = os_strchr(pos, ','); + len = end ? (size_t) (end - pos) : os_strlen(pos); + if (!end && len == 0) + break; + if (len == 0 || (len & 1) != 0 || + len / 2 > MAX_ROAMING_CONS_OI_LEN || + hexstr2bin(pos, + roaming_consortiums[num_roaming_consortiums], + len / 2) < 0) { + wpa_printf(MSG_INFO, + "Invalid roaming_consortiums entry: %s", + pos); + return -1; + } + roaming_consortiums_len[num_roaming_consortiums] = len / 2; + num_roaming_consortiums++; + + if (!end) + break; + + if (num_roaming_consortiums >= MAX_ROAMING_CONS) { + wpa_printf(MSG_INFO, + "Too many roaming_consortiums OIs"); + return -1; + } + + pos = end + 1; + } + + os_memcpy(cred->roaming_consortiums, roaming_consortiums, + sizeof(roaming_consortiums)); + os_memcpy(cred->roaming_consortiums_len, roaming_consortiums_len, + sizeof(roaming_consortiums_len)); + cred->num_roaming_consortiums = num_roaming_consortiums; + + return 0; +} + + int wpa_config_set_cred(struct wpa_cred *cred, const char *var, const char *value, int line) { char *val; size_t len; + int res; if (os_strcmp(var, "temporary") == 0) { cred->temporary = atoi(value); @@ -3078,6 +3500,16 @@ int wpa_config_set_cred(struct wpa_cred *cred, const char *var, return 0; } + if (os_strcmp(var, "roaming_consortiums") == 0) { + res = wpa_config_set_cred_roaming_consortiums(cred, val); + if (res < 0) + wpa_printf(MSG_ERROR, + "Line %d: invalid roaming_consortiums", + line); + os_free(val); + return res; + } + if (os_strcmp(var, "excluded_ssid") == 0) { struct excluded_ssid *e; @@ -3389,6 +3821,31 @@ char * wpa_config_get_cred_no_key(struct wpa_cred *cred, const char *var) return buf; } + if (os_strcmp(var, "roaming_consortiums") == 0) { + size_t buflen; + char *buf, *pos; + size_t i; + + if (!cred->num_roaming_consortiums) + return NULL; + buflen = cred->num_roaming_consortiums * + MAX_ROAMING_CONS_OI_LEN * 2 + 1; + buf = os_malloc(buflen); + if (!buf) + return NULL; + pos = buf; + for (i = 0; i < cred->num_roaming_consortiums; i++) { + if (i > 0) + *pos++ = ','; + pos += wpa_snprintf_hex( + pos, buf + buflen - pos, + cred->roaming_consortiums[i], + cred->roaming_consortiums_len[i]); + } + *pos = '\0'; + return buf; + } + if (os_strcmp(var, "excluded_ssid") == 0) { unsigned int i; char *buf, *end, *pos; @@ -3646,6 +4103,7 @@ struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface, config->bss_expiration_age = DEFAULT_BSS_EXPIRATION_AGE; config->bss_expiration_scan_count = DEFAULT_BSS_EXPIRATION_SCAN_COUNT; config->max_num_sta = DEFAULT_MAX_NUM_STA; + config->ap_isolate = DEFAULT_AP_ISOLATE; config->access_network_type = DEFAULT_ACCESS_NETWORK_TYPE; config->scan_cur_freq = DEFAULT_SCAN_CUR_FREQ; config->wmm_ac_params[0] = ac_be; @@ -3660,12 +4118,16 @@ struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface, #ifdef CONFIG_MBO config->mbo_cell_capa = DEFAULT_MBO_CELL_CAPA; + config->disassoc_imminent_rssi_threshold = + DEFAULT_DISASSOC_IMMINENT_RSSI_THRESHOLD; + config->oce = DEFAULT_OCE_SUPPORT; #endif /* CONFIG_MBO */ if (ctrl_interface) config->ctrl_interface = os_strdup(ctrl_interface); if (driver_param) config->driver_param = os_strdup(driver_param); + config->gas_rand_addr_lifetime = DEFAULT_RAND_ADDR_LIFETIME; return config; } @@ -4072,6 +4534,21 @@ static int wpa_config_process_p2p_no_go_freq( return 0; } + +static int wpa_config_process_p2p_device_persistent_mac_addr( + const struct global_parse_data *data, + struct wpa_config *config, int line, const char *pos) +{ + if (hwaddr_aton2(pos, config->p2p_device_persistent_mac_addr) < 0) { + wpa_printf(MSG_ERROR, + "Line %d: Invalid p2p_device_persistent_mac_addr '%s'", + line, pos); + return -1; + } + + return 0; +} + #endif /* CONFIG_P2P */ @@ -4271,6 +4748,7 @@ static const struct global_parse_data global_fields[] = { { FUNC_NO_VAR(load_dynamic_eap), 0 }, #ifdef CONFIG_WPS { FUNC(uuid), CFG_CHANGED_UUID }, + { INT_RANGE(auto_uuid, 0, 1), 0 }, { STR_RANGE(device_name, 0, WPS_DEV_NAME_MAX_LEN), CFG_CHANGED_DEVICE_NAME }, { STR_RANGE(manufacturer, 0, 64), CFG_CHANGED_WPS_STRING }, @@ -4281,6 +4759,7 @@ static const struct global_parse_data global_fields[] = { { FUNC(os_version), CFG_CHANGED_OS_VERSION }, { STR(config_methods), CFG_CHANGED_CONFIG_METHODS }, { INT_RANGE(wps_cred_processing, 0, 2), 0 }, + { INT_RANGE(wps_cred_add_sae, 0, 1), 0 }, { FUNC(wps_vendor_ext_m1), CFG_CHANGED_VENDOR_EXTENSION }, #endif /* CONFIG_WPS */ #ifdef CONFIG_P2P @@ -4303,6 +4782,7 @@ static const struct global_parse_data global_fields[] = { { INT_RANGE(p2p_optimize_listen_chan, 0, 1), 0 }, { INT(p2p_go_ht40), 0 }, { INT(p2p_go_vht), 0 }, + { INT(p2p_go_he), 0 }, { INT(p2p_disabled), 0 }, { INT_RANGE(p2p_go_ctwindow, 0, 127), 0 }, { INT(p2p_no_group_iface), 0 }, @@ -4312,6 +4792,9 @@ static const struct global_parse_data global_fields[] = { { IPV4(ip_addr_start), 0 }, { IPV4(ip_addr_end), 0 }, { INT_RANGE(p2p_cli_probe, 0, 1), 0 }, + { INT(p2p_device_random_mac_addr), 0 }, + { FUNC(p2p_device_persistent_mac_addr), 0 }, + { INT(p2p_interface_random_mac_addr), 0 }, #endif /* CONFIG_P2P */ { FUNC(country), CFG_CHANGED_COUNTRY }, { INT(bss_max_count), 0 }, @@ -4320,6 +4803,7 @@ static const struct global_parse_data global_fields[] = { { INT_RANGE(filter_ssids, 0, 1), 0 }, { INT_RANGE(filter_rssi, -100, 0), 0 }, { INT(max_num_sta), 0 }, + { INT_RANGE(ap_isolate, 0, 1), 0 }, { INT_RANGE(disassoc_low_ack, 0, 1), 0 }, #ifdef CONFIG_HS20 { INT_RANGE(hs20, 0, 1), 0 }, @@ -4327,6 +4811,11 @@ static const struct global_parse_data global_fields[] = { { INT_RANGE(interworking, 0, 1), 0 }, { FUNC(hessid), 0 }, { INT_RANGE(access_network_type, 0, 15), 0 }, + { INT_RANGE(go_interworking, 0, 1), 0 }, + { INT_RANGE(go_access_network_type, 0, 15), 0 }, + { INT_RANGE(go_internet, 0, 1), 0 }, + { INT_RANGE(go_venue_group, 0, 255), 0 }, + { INT_RANGE(go_venue_type, 0, 255), 0 }, { INT_RANGE(pbc_in_m1, 0, 1), 0 }, { STR(autoscan), 0 }, { INT_RANGE(wps_nfc_dev_pw_id, 0x10, 0xffff), @@ -4347,9 +4836,10 @@ static const struct global_parse_data global_fields[] = { { FUNC(freq_list), 0 }, { INT(scan_cur_freq), 0 }, { INT(sched_scan_interval), 0 }, + { INT(sched_scan_start_delay), 0 }, { INT(tdls_external_control), 0}, { STR(osu_dir), 0 }, - { STR(wowlan_triggers), 0 }, + { STR(wowlan_triggers), CFG_CHANGED_WOWLAN_TRIGGERS }, { INT(p2p_search_delay), 0}, { INT(mac_addr), 0 }, { INT(rand_addr_lifetime), 0 }, @@ -4363,16 +4853,23 @@ static const struct global_parse_data global_fields[] = { { INT_RANGE(fst_priority, 1, FST_MAX_PRIO_VALUE), 0 }, { INT_RANGE(fst_llt, 1, FST_MAX_LLT_MS), 0 }, #endif /* CONFIG_FST */ + { INT_RANGE(cert_in_cb, 0, 1), 0 }, { INT_RANGE(wpa_rsc_relaxation, 0, 1), 0 }, { STR(sched_scan_plans), CFG_CHANGED_SCHED_SCAN_PLANS }, #ifdef CONFIG_MBO { STR(non_pref_chan), 0 }, { INT_RANGE(mbo_cell_capa, MBO_CELL_CAPA_AVAILABLE, MBO_CELL_CAPA_NOT_SUPPORTED), 0 }, -#endif /*CONFIG_MBO */ + { INT_RANGE(disassoc_imminent_rssi_threshold, -120, 0), 0 }, + { INT_RANGE(oce, 0, 3), 0 }, +#endif /* CONFIG_MBO */ { INT(gas_address3), 0 }, { INT_RANGE(ftm_responder, 0, 1), 0 }, { INT_RANGE(ftm_initiator, 0, 1), 0 }, + { INT(gas_rand_addr_lifetime), 0 }, + { INT_RANGE(gas_rand_mac_addr, 0, 2), 0 }, + { INT_RANGE(dpp_config_processing, 0, 2), 0 }, + { INT_RANGE(coloc_intf_reporting, 0, 1), 0 }, }; #undef FUNC diff --git a/freebsd/contrib/wpa/wpa_supplicant/config.h b/freebsd/contrib/wpa/wpa_supplicant/config.h index 9d41fd17..a617ea18 100644 --- a/freebsd/contrib/wpa/wpa_supplicant/config.h +++ b/freebsd/contrib/wpa/wpa_supplicant/config.h @@ -32,6 +32,7 @@ #define DEFAULT_BSS_EXPIRATION_AGE 180 #define DEFAULT_BSS_EXPIRATION_SCAN_COUNT 2 #define DEFAULT_MAX_NUM_STA 128 +#define DEFAULT_AP_ISOLATE 0 #define DEFAULT_ACCESS_NETWORK_TYPE 15 #define DEFAULT_SCAN_CUR_FREQ 0 #define DEFAULT_P2P_SEARCH_DELAY 500 @@ -41,6 +42,8 @@ #define DEFAULT_P2P_GO_CTWINDOW 0 #define DEFAULT_WPA_RSC_RELAXATION 1 #define DEFAULT_MBO_CELL_CAPA MBO_CELL_CAPA_NOT_SUPPORTED +#define DEFAULT_DISASSOC_IMMINENT_RSSI_THRESHOLD -75 +#define DEFAULT_OCE_SUPPORT OCE_STA #include "config_ssid.h" #include "wps/wps.h" @@ -51,6 +54,9 @@ #include <machine/rtems-bsd-commands.h> #endif /* __rtems__ */ +#define MAX_ROAMING_CONS 36 +#define MAX_ROAMING_CONS_OI_LEN 15 + struct wpa_cred { /** * next - Next credential in the list @@ -225,10 +231,43 @@ struct wpa_cred { */ size_t roaming_consortium_len; + /** + * required_roaming_consortium - Required Roaming Consortium OI + * + * If required_roaming_consortium_len is non-zero, this field contains + * the Roaming Consortium OI that is required to be advertised by the AP + * for the credential to be considered matching. + */ u8 required_roaming_consortium[15]; + + /** + * required_roaming_consortium_len - Length of required_roaming_consortium + */ size_t required_roaming_consortium_len; /** + * roaming_consortiums - Roaming Consortium OI(s) memberships + * + * This field contains one or more OIs identifying the roaming + * consortiums of which the provider is a member. The list is sorted + * from the most preferred one to the least preferred one. A match + * between the Roaming Consortium OIs advertised by an AP and the OIs + * in this list indicates that successful authentication is possible. + * (Hotspot 2.0 PerProviderSubscription/<X+>/HomeSP/RoamingConsortiumOI) + */ + u8 roaming_consortiums[MAX_ROAMING_CONS][MAX_ROAMING_CONS_OI_LEN]; + + /** + * roaming_consortiums_len - Length on roaming_consortiums[i] + */ + size_t roaming_consortiums_len[MAX_ROAMING_CONS]; + + /** + * num_roaming_consortiums - Number of entries in roaming_consortiums + */ + unsigned int num_roaming_consortiums; + + /** * eap_method - EAP method to use * * Pre-configured EAP method to use with this credential or %NULL to @@ -337,6 +376,7 @@ struct wpa_cred { #define CFG_CHANGED_NFC_PASSWORD_TOKEN BIT(15) #define CFG_CHANGED_P2P_PASSPHRASE_LEN BIT(16) #define CFG_CHANGED_SCHED_SCAN_PLANS BIT(17) +#define CFG_CHANGED_WOWLAN_TRIGGERS BIT(18) /** * struct wpa_config - wpa_supplicant configuration data @@ -628,6 +668,13 @@ struct wpa_config { u8 uuid[16]; /** + * auto_uuid - Automatic UUID behavior + * 0 = generate static value based on the local MAC address (default) + * 1 = generate a random UUID every time wpa_supplicant starts + */ + int auto_uuid; + + /** * device_name - Device Name (WPS) * User-friendly description of device; up to 32 octets encoded in * UTF-8 @@ -701,6 +748,16 @@ struct wpa_config { */ int wps_cred_processing; + /** + * wps_cred_add_sae - Whether to enable SAE automatically for WPS + * + * 0 = only add the explicitly listed WPA2-PSK configuration + * 1 = add both the WPA2-PSK and SAE configuration and enable PMF so + * that the station gets configured in WPA3-Personal transition mode + * (supports both WPA2-Personal (PSK) and WPA3-Personal (SAE) APs). + */ + int wps_cred_add_sae; + #define MAX_SEC_DEVICE_TYPES 5 /** * sec_device_types - Secondary Device Types (P2P) @@ -836,6 +893,20 @@ struct wpa_config { unsigned int max_num_sta; /** + * ap_isolate - Whether to use client isolation feature + * + * Client isolation can be used to prevent low-level bridging of + * frames between associated stations in the BSS. By default, + * this bridging is allowed (ap_isolate=0); except in P2P GO case, + * where p2p_intra_bss parameter is used to determine whether to allow + * intra-BSS forwarding (ap_isolate = !p2p_intra_bss). + * + * 0 = do not enable AP isolation + * 1 = enable AP isolation + */ + int ap_isolate; + + /** * freq_list - Array of allowed scan frequencies or %NULL for all * * This is an optional zero-terminated array of frequencies in @@ -857,7 +928,7 @@ struct wpa_config { unsigned int changed_parameters; /** - * disassoc_low_ack - Disassocicate stations with massive packet loss + * disassoc_low_ack - Disassociate stations with massive packet loss */ int disassoc_low_ack; @@ -875,6 +946,34 @@ struct wpa_config { */ int access_network_type; + /** + * go_interworking - Whether Interworking for P2P GO is enabled + */ + int go_interworking; + + /** + * go_access_network_type - P2P GO Access Network Type + * + * This indicates which access network type to advertise if Interworking + * is enabled for P2P GO. + */ + int go_access_network_type; + + /** + * go_internet - Interworking: Internet connectivity (0 or 1) + */ + int go_internet; + + /** + * go_venue_group - Interworking: Venue group + */ + int go_venue_group; + + /** + * go_venue_type: Interworking: Venue type + */ + int go_venue_type; + /** * hessid - Homogenous ESS identifier * @@ -993,6 +1092,16 @@ struct wpa_config { int p2p_go_vht; /** + * p2p_go_he - Default mode for 11ax HE enable when operating as GO + * + * This will take effect for p2p_group_add, p2p_connect, and p2p_invite. + * Note that regulatory constraints and driver capabilities are + * consulted anyway, so setting it to 1 can't do real harm. + * By default: 0 (disabled) + */ + int p2p_go_he; + + /** * p2p_go_ctwindow - CTWindow to use when operating as GO * * By default: 0 (no CTWindow). Values 0-127 can be used to indicate @@ -1099,6 +1208,15 @@ struct wpa_config { unsigned int sched_scan_interval; /** + * sched_scan_start_delay - Schedule scan start delay before first scan + * + * Delay (in seconds) before scheduling first scan plan cycle. The + * driver may ignore this parameter and start immediately (or at any + * other time), if this feature is not supported. + */ + unsigned int sched_scan_start_delay; + + /** * tdls_external_control - External control for TDLS setup requests * * Enable TDLS mode where external programs are given the control @@ -1294,6 +1412,19 @@ struct wpa_config { * mbo_cell_capa - Cellular capabilities for MBO */ enum mbo_cellular_capa mbo_cell_capa; + + /** + * disassoc_imminent_rssi_threshold - RSSI threshold of candidate AP + * when disassociation imminent is set. + */ + int disassoc_imminent_rssi_threshold; + + /** + * oce - Enable OCE in STA and/or STA-CFON mode + * - Set BIT(0) to enable OCE in non-AP STA mode + * - Set BIT(1) to enable OCE in STA-CFON mode + */ + unsigned int oce; #endif /* CONFIG_MBO */ /** @@ -1331,6 +1462,74 @@ struct wpa_config { * wpa_supplicant. */ int ftm_initiator; + + /** + * gas_rand_addr_lifetime - Lifetime of random MAC address for ANQP in + * seconds + */ + unsigned int gas_rand_addr_lifetime; + + /** + * gas_rand_mac_addr - GAS MAC address policy + * + * 0 = use permanent MAC address + * 1 = use random MAC address + * 2 = like 1, but maintain OUI (with local admin bit set) + */ + int gas_rand_mac_addr; + + /** + * dpp_config_processing - How to process DPP configuration + * + * 0 = report received configuration to an external program for + * processing; do not generate any network profile internally + * 1 = report received configuration to an external program and generate + * a network profile internally, but do not automatically connect + * to the created (disabled) profile; the network profile id is + * reported to external programs + * 2 = report received configuration to an external program, generate + * a network profile internally, try to connect to the created + * profile automatically + */ + int dpp_config_processing; + + /** + * coloc_intf_reporting - Colocated interference reporting + * + * dot11CoLocIntfReportingActivated + * 0 = disabled (false) + * 1 = enabled (true) + */ + int coloc_intf_reporting; + + /** + * p2p_device_random_mac_addr - P2P Device MAC address policy default + * + * 0 = use permanent MAC address + * 1 = use random MAC address on creating the interface if there is no + * persistent groups. + * + * By default, permanent MAC address is used. + */ + int p2p_device_random_mac_addr; + + /** + * p2p_device_persistent_mac_addr - Record last used MAC address + * + * If there are saved persistent groups, P2P cannot generate another + * random MAC address, and need to restore to last used MAC address. + */ + u8 p2p_device_persistent_mac_addr[ETH_ALEN]; + + /** + * p2p_interface_random_mac_addr - P2P Interface MAC address policy default + * + * 0 = use permanent MAC address + * 1 = use random MAC address on creating the interface. + * + * By default, permanent MAC address is used. + */ + int p2p_interface_random_mac_addr; }; diff --git a/freebsd/contrib/wpa/wpa_supplicant/config_file.c b/freebsd/contrib/wpa/wpa_supplicant/config_file.c index 09df6c14..e3e17e01 100644 --- a/freebsd/contrib/wpa/wpa_supplicant/config_file.c +++ b/freebsd/contrib/wpa/wpa_supplicant/config_file.c @@ -21,6 +21,7 @@ #include "config.h" #include "base64.h" #include "uuid.h" +#include "common/ieee802_1x_defs.h" #include "p2p/p2p.h" #include "eap_peer/eap_methods.h" #include "eap_peer/eap.h" @@ -138,9 +139,13 @@ static int wpa_config_validate_network(struct wpa_ssid *ssid, int line) wpa_config_update_psk(ssid); } + if (ssid->disabled == 2) + ssid->p2p_persistent_group = 1; + if ((ssid->group_cipher & WPA_CIPHER_CCMP) && - !(ssid->pairwise_cipher & WPA_CIPHER_CCMP) && - !(ssid->pairwise_cipher & WPA_CIPHER_NONE)) { + !(ssid->pairwise_cipher & (WPA_CIPHER_CCMP | WPA_CIPHER_CCMP_256 | + WPA_CIPHER_GCMP | WPA_CIPHER_GCMP_256 | + WPA_CIPHER_NONE))) { /* Group cipher cannot be stronger than the pairwise cipher. */ wpa_printf(MSG_DEBUG, "Line %d: removed CCMP from group cipher" " list since it was not allowed for pairwise " @@ -157,6 +162,15 @@ static int wpa_config_validate_network(struct wpa_ssid *ssid, int line) errors++; } +#ifdef CONFIG_OCV + if (ssid->ocv && ssid->ieee80211w == NO_MGMT_FRAME_PROTECTION) { + wpa_printf(MSG_ERROR, + "Line %d: PMF needs to be enabled whenever using OCV", + line); + errors++; + } +#endif /* CONFIG_OCV */ + return errors; } @@ -310,7 +324,7 @@ static struct wpa_config_blob * wpa_config_read_blob(FILE *f, int *line, encoded_len += len; } - if (!end) { + if (!end || !encoded) { wpa_printf(MSG_ERROR, "Line %d: blob was not terminated " "properly", *line); os_free(encoded); @@ -395,7 +409,8 @@ struct wpa_config * wpa_config_read(const char *name, struct wpa_config *cfgp) if (f == NULL) { wpa_printf(MSG_ERROR, "Failed to open config file '%s', " "error: %s", name, strerror(errno)); - os_free(config); + if (config != cfgp) + os_free(config); return NULL; } @@ -461,7 +476,8 @@ struct wpa_config * wpa_config_read(const char *name, struct wpa_config *cfgp) #ifndef WPA_IGNORE_CONFIG_ERRORS if (errors) { - wpa_config_free(config); + if (config != cfgp) + wpa_config_free(config); config = NULL; head = NULL; } @@ -479,7 +495,7 @@ static void write_str(FILE *f, const char *field, struct wpa_ssid *ssid) if (value == NULL) return; fprintf(f, "\t%s=%s\n", field, value); - os_free(value); + str_clear_free(value); } @@ -501,6 +517,17 @@ static void write_bssid(FILE *f, struct wpa_ssid *ssid) } +static void write_bssid_hint(FILE *f, struct wpa_ssid *ssid) +{ + char *value = wpa_config_get(ssid, "bssid_hint"); + + if (!value) + return; + fprintf(f, "\tbssid_hint=%s\n", value); + os_free(value); +} + + static void write_psk(FILE *f, struct wpa_ssid *ssid) { char *value; @@ -580,6 +607,22 @@ static void write_group(FILE *f, struct wpa_ssid *ssid) } +static void write_group_mgmt(FILE *f, struct wpa_ssid *ssid) +{ + char *value; + + if (!ssid->group_mgmt_cipher) + return; + + value = wpa_config_get(ssid, "group_mgmt"); + if (!value) + return; + if (value[0]) + fprintf(f, "\tgroup_mgmt=%s\n", value); + os_free(value); +} + + static void write_auth_alg(FILE *f, struct wpa_ssid *ssid) { char *value; @@ -664,6 +707,40 @@ static void write_psk_list(FILE *f, struct wpa_ssid *ssid) #endif /* CONFIG_P2P */ +#ifdef CONFIG_MACSEC + +static void write_mka_cak(FILE *f, struct wpa_ssid *ssid) +{ + char *value; + + if (!(ssid->mka_psk_set & MKA_PSK_SET_CAK)) + return; + + value = wpa_config_get(ssid, "mka_cak"); + if (!value) + return; + fprintf(f, "\tmka_cak=%s\n", value); + os_free(value); +} + + +static void write_mka_ckn(FILE *f, struct wpa_ssid *ssid) +{ + char *value; + + if (!(ssid->mka_psk_set & MKA_PSK_SET_CKN)) + return; + + value = wpa_config_get(ssid, "mka_ckn"); + if (!value) + return; + fprintf(f, "\tmka_ckn=%s\n", value); + os_free(value); +} + +#endif /* CONFIG_MACSEC */ + + static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid) { int i; @@ -677,15 +754,19 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid) STR(ssid); INT(scan_ssid); write_bssid(f, ssid); + write_bssid_hint(f, ssid); write_str(f, "bssid_blacklist", ssid); write_str(f, "bssid_whitelist", ssid); write_psk(f, ssid); INT(mem_only_psk); + STR(sae_password); + STR(sae_password_id); write_proto(f, ssid); write_key_mgmt(f, ssid); INT_DEF(bg_scan_period, DEFAULT_BG_SCAN_PERIOD); write_pairwise(f, ssid); write_group(f, ssid); + write_group_mgmt(f, ssid); write_auth_alg(f, ssid); STR(bgscan); STR(autoscan); @@ -694,6 +775,7 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid) write_eap(f, ssid); STR(identity); STR(anonymous_identity); + STR(imsi_identity); STR(password); STR(ca_cert); STR(ca_path); @@ -702,6 +784,7 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid) STR(private_key_passwd); STR(dh_file); STR(subject_match); + STR(check_cert_subject); STR(altsubject_match); STR(domain_suffix_match); STR(domain_match); @@ -712,6 +795,7 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid) STR(private_key2_passwd); STR(dh_file2); STR(subject_match2); + STR(check_cert_subject2); STR(altsubject_match2); STR(domain_suffix_match2); STR(domain_match2); @@ -754,11 +838,16 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid) #endif /* CONFIG_ACS */ write_int(f, "proactive_key_caching", ssid->proactive_key_caching, -1); INT(disabled); - INT(peerkey); INT(mixed_cell); - INT(max_oper_chwidth); + INT(vht); + INT_DEF(ht, 1); + INT(ht40); + INT_DEF(max_oper_chwidth, DEFAULT_MAX_OPER_CHWIDTH); + INT(vht_center_freq1); + INT(vht_center_freq2); INT(pbss); INT(wps_disabled); + INT(fils_dh_group); #ifdef CONFIG_IEEE80211W write_int(f, "ieee80211w", ssid->ieee80211w, MGMT_FRAME_PROTECTION_DEFAULT); @@ -774,9 +863,17 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid) INT(beacon_int); #ifdef CONFIG_MACSEC INT(macsec_policy); + write_mka_cak(f, ssid); + write_mka_ckn(f, ssid); + INT(macsec_integ_only); + INT(macsec_replay_protect); + INT(macsec_replay_window); + INT(macsec_port); + INT_DEF(mka_priority, DEFAULT_PRIO_NOT_KEY_SERVER); #endif /* CONFIG_MACSEC */ #ifdef CONFIG_HS20 INT(update_identifier); + STR(roaming_consortium_selection); #endif /* CONFIG_HS20 */ write_int(f, "mac_addr", ssid->mac_addr, -1); #ifdef CONFIG_MESH @@ -785,16 +882,28 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid) INT_DEF(dot11MeshRetryTimeout, DEFAULT_MESH_RETRY_TIMEOUT); INT_DEF(dot11MeshConfirmTimeout, DEFAULT_MESH_CONFIRM_TIMEOUT); INT_DEF(dot11MeshHoldingTimeout, DEFAULT_MESH_HOLDING_TIMEOUT); + INT_DEF(mesh_rssi_threshold, DEFAULT_MESH_RSSI_THRESHOLD); #endif /* CONFIG_MESH */ INT(wpa_ptk_rekey); INT(group_rekey); INT(ignore_broadcast_ssid); +#ifdef CONFIG_DPP + STR(dpp_connector); + STR(dpp_netaccesskey); + INT(dpp_netaccesskey_expiry); + STR(dpp_csign); +#endif /* CONFIG_DPP */ + INT(owe_group); + INT(owe_only); + INT(multi_ap_backhaul_sta); #ifdef CONFIG_HT_OVERRIDES INT_DEF(disable_ht, DEFAULT_DISABLE_HT); INT_DEF(disable_ht40, DEFAULT_DISABLE_HT40); INT_DEF(disable_sgi, DEFAULT_DISABLE_SGI); INT_DEF(disable_ldpc, DEFAULT_DISABLE_LDPC); INT(ht40_intolerant); + INT_DEF(tx_stbc, DEFAULT_TX_STBC); + INT_DEF(rx_stbc, DEFAULT_RX_STBC); INT_DEF(disable_max_amsdu, DEFAULT_DISABLE_MAX_AMSDU); INT_DEF(ampdu_factor, DEFAULT_AMPDU_FACTOR); INT_DEF(ampdu_density, DEFAULT_AMPDU_DENSITY); @@ -951,6 +1060,20 @@ static void wpa_config_write_cred(FILE *f, struct wpa_cred *cred) fprintf(f, "\n"); } + if (cred->num_roaming_consortiums) { + size_t j; + + fprintf(f, "\troaming_consortiums=\""); + for (i = 0; i < cred->num_roaming_consortiums; i++) { + if (i > 0) + fprintf(f, ","); + for (j = 0; j < cred->roaming_consortiums_len[i]; j++) + fprintf(f, "%02x", + cred->roaming_consortiums[i][j]); + } + fprintf(f, "\"\n"); + } + if (cred->sim_num != DEFAULT_USER_SELECTED_SIM) fprintf(f, "\tsim_num=%d\n", cred->sim_num); } @@ -1041,6 +1164,8 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config) uuid_bin2str(config->uuid, buf, sizeof(buf)); fprintf(f, "uuid=%s\n", buf); } + if (config->auto_uuid) + fprintf(f, "auto_uuid=%d\n", config->auto_uuid); if (config->device_name) fprintf(f, "device_name=%s\n", config->device_name); if (config->manufacturer) @@ -1066,6 +1191,9 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config) if (config->wps_cred_processing) fprintf(f, "wps_cred_processing=%d\n", config->wps_cred_processing); + if (config->wps_cred_add_sae) + fprintf(f, "wps_cred_add_sae=%d\n", + config->wps_cred_add_sae); if (config->wps_vendor_ext_m1) { int i, len = wpabuf_len(config->wps_vendor_ext_m1); const u8 *p = wpabuf_head_u8(config->wps_vendor_ext_m1); @@ -1078,6 +1206,17 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config) } #endif /* CONFIG_WPS */ #ifdef CONFIG_P2P + { + int i; + char _buf[WPS_DEV_TYPE_BUFSIZE], *buf; + + for (i = 0; i < config->num_sec_device_types; i++) { + buf = wps_dev_type_bin2str(config->sec_device_type[i], + _buf, sizeof(_buf)); + if (buf) + fprintf(f, "sec_device_type=%s\n", buf); + } + } if (config->p2p_listen_reg_class) fprintf(f, "p2p_listen_reg_class=%d\n", config->p2p_listen_reg_class); @@ -1130,6 +1269,8 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config) fprintf(f, "p2p_go_ht40=%d\n", config->p2p_go_ht40); if (config->p2p_go_vht) fprintf(f, "p2p_go_vht=%d\n", config->p2p_go_vht); + if (config->p2p_go_he) + fprintf(f, "p2p_go_he=%d\n", config->p2p_go_he); if (config->p2p_go_ctwindow != DEFAULT_P2P_GO_CTWINDOW) fprintf(f, "p2p_go_ctwindow=%d\n", config->p2p_go_ctwindow); if (config->p2p_disabled) @@ -1177,8 +1318,12 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config) config->bss_expiration_scan_count); if (config->filter_ssids) fprintf(f, "filter_ssids=%d\n", config->filter_ssids); + if (config->filter_rssi) + fprintf(f, "filter_rssi=%d\n", config->filter_rssi); if (config->max_num_sta != DEFAULT_MAX_NUM_STA) fprintf(f, "max_num_sta=%u\n", config->max_num_sta); + if (config->ap_isolate != DEFAULT_AP_ISOLATE) + fprintf(f, "ap_isolate=%u\n", config->ap_isolate); if (config->disassoc_low_ack) fprintf(f, "disassoc_low_ack=%d\n", config->disassoc_low_ack); #ifdef CONFIG_HS20 @@ -1193,6 +1338,17 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config) if (config->access_network_type != DEFAULT_ACCESS_NETWORK_TYPE) fprintf(f, "access_network_type=%d\n", config->access_network_type); + if (config->go_interworking) + fprintf(f, "go_interworking=%d\n", config->go_interworking); + if (config->go_access_network_type) + fprintf(f, "go_access_network_type=%d\n", + config->go_access_network_type); + if (config->go_internet) + fprintf(f, "go_internet=%d\n", config->go_internet); + if (config->go_venue_group) + fprintf(f, "go_venue_group=%d\n", config->go_venue_group); + if (config->go_venue_type) + fprintf(f, "go_venue_type=%d\n", config->go_venue_type); #endif /* CONFIG_INTERWORKING */ if (config->pbc_in_m1) fprintf(f, "pbc_in_m1=%d\n", config->pbc_in_m1); @@ -1228,7 +1384,7 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config) if (config->sae_groups) { int i; fprintf(f, "sae_groups="); - for (i = 0; config->sae_groups[i] >= 0; i++) { + for (i = 0; config->sae_groups[i] > 0; i++) { fprintf(f, "%s%d", i > 0 ? " " : "", config->sae_groups[i]); } @@ -1266,6 +1422,10 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config) fprintf(f, "sched_scan_interval=%u\n", config->sched_scan_interval); + if (config->sched_scan_start_delay) + fprintf(f, "sched_scan_start_delay=%u\n", + config->sched_scan_start_delay); + if (config->external_sim) fprintf(f, "external_sim=%d\n", config->external_sim); @@ -1280,6 +1440,9 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config) if (config->bgscan) fprintf(f, "bgscan=\"%s\"\n", config->bgscan); + if (config->autoscan) + fprintf(f, "autoscan=%s\n", config->autoscan); + if (config->p2p_search_delay != DEFAULT_P2P_SEARCH_DELAY) fprintf(f, "p2p_search_delay=%u\n", config->p2p_search_delay); @@ -1337,6 +1500,12 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config) fprintf(f, "non_pref_chan=%s\n", config->non_pref_chan); if (config->mbo_cell_capa != DEFAULT_MBO_CELL_CAPA) fprintf(f, "mbo_cell_capa=%u\n", config->mbo_cell_capa); + if (config->disassoc_imminent_rssi_threshold != + DEFAULT_DISASSOC_IMMINENT_RSSI_THRESHOLD) + fprintf(f, "disassoc_imminent_rssi_threshold=%d\n", + config->disassoc_imminent_rssi_threshold); + if (config->oce != DEFAULT_OCE_SUPPORT) + fprintf(f, "oce=%u\n", config->oce); #endif /* CONFIG_MBO */ if (config->gas_address3) @@ -1346,6 +1515,37 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config) fprintf(f, "ftm_responder=%d\n", config->ftm_responder); if (config->ftm_initiator) fprintf(f, "ftm_initiator=%d\n", config->ftm_initiator); + + if (config->osu_dir) + fprintf(f, "osu_dir=%s\n", config->osu_dir); + + if (config->fst_group_id) + fprintf(f, "fst_group_id=%s\n", config->fst_group_id); + if (config->fst_priority) + fprintf(f, "fst_priority=%d\n", config->fst_priority); + if (config->fst_llt) + fprintf(f, "fst_llt=%d\n", config->fst_llt); + + if (config->gas_rand_addr_lifetime != DEFAULT_RAND_ADDR_LIFETIME) + fprintf(f, "gas_rand_addr_lifetime=%u\n", + config->gas_rand_addr_lifetime); + if (config->gas_rand_mac_addr) + fprintf(f, "gas_rand_mac_addr=%d\n", config->gas_rand_mac_addr); + if (config->dpp_config_processing) + fprintf(f, "dpp_config_processing=%d\n", + config->dpp_config_processing); + if (config->coloc_intf_reporting) + fprintf(f, "coloc_intf_reporting=%d\n", + config->coloc_intf_reporting); + if (config->p2p_device_random_mac_addr) + fprintf(f, "p2p_device_random_mac_addr=%d\n", + config->p2p_device_random_mac_addr); + if (!is_zero_ether_addr(config->p2p_device_persistent_mac_addr)) + fprintf(f, "p2p_device_persistent_mac_addr=" MACSTR "\n", + MAC2STR(config->p2p_device_persistent_mac_addr)); + if (config->p2p_interface_random_mac_addr) + fprintf(f, "p2p_interface_random_mac_addr=%d\n", + config->p2p_interface_random_mac_addr); } #endif /* CONFIG_NO_CONFIG_WRITE */ diff --git a/freebsd/contrib/wpa/wpa_supplicant/config_ssid.h b/freebsd/contrib/wpa/wpa_supplicant/config_ssid.h index 010b594a..1b2b1f1a 100644 --- a/freebsd/contrib/wpa/wpa_supplicant/config_ssid.h +++ b/freebsd/contrib/wpa/wpa_supplicant/config_ssid.h @@ -28,14 +28,18 @@ #define DEFAULT_MESH_RETRY_TIMEOUT 40 #define DEFAULT_MESH_CONFIRM_TIMEOUT 40 #define DEFAULT_MESH_HOLDING_TIMEOUT 40 +#define DEFAULT_MESH_RSSI_THRESHOLD 1 /* no change */ #define DEFAULT_DISABLE_HT 0 #define DEFAULT_DISABLE_HT40 0 #define DEFAULT_DISABLE_SGI 0 #define DEFAULT_DISABLE_LDPC 0 +#define DEFAULT_TX_STBC -1 /* no change */ +#define DEFAULT_RX_STBC -1 /* no change */ #define DEFAULT_DISABLE_MAX_AMSDU -1 /* no change */ #define DEFAULT_AMPDU_FACTOR -1 /* no change */ #define DEFAULT_AMPDU_DENSITY -1 /* no change */ #define DEFAULT_USER_SELECTED_SIM 1 +#define DEFAULT_MAX_OPER_CHWIDTH -1 struct psk_list_entry { struct dl_list list; @@ -146,6 +150,19 @@ struct wpa_ssid { int bssid_set; /** + * bssid_hint - BSSID hint + * + * If set, this is configured to the driver as a preferred initial BSSID + * while connecting to this network. + */ + u8 bssid_hint[ETH_ALEN]; + + /** + * bssid_hint_set - Whether BSSID hint is configured for this network + */ + int bssid_hint_set; + + /** * go_p2p_dev_addr - GO's P2P Device Address or all zeros if not set */ u8 go_p2p_dev_addr[ETH_ALEN]; @@ -170,6 +187,24 @@ struct wpa_ssid { char *passphrase; /** + * sae_password - SAE password + * + * This parameter can be used to set a password for SAE. By default, the + * passphrase value is used if this separate parameter is not used, but + * passphrase follows the WPA-PSK constraints (8..63 characters) even + * though SAE passwords do not have such constraints. + */ + char *sae_password; + + /** + * sae_password_id - SAE password identifier + * + * This parameter can be used to identify a specific SAE password. If + * not included, the default SAE password is used instead. + */ + char *sae_password_id; + + /** * ext_psk - PSK/passphrase name in external storage * * If this is set, PSK/passphrase will be fetched from external storage @@ -196,6 +231,15 @@ struct wpa_ssid { int group_cipher; /** + * group_mgmt_cipher - Bitfield of allowed group management ciphers + * + * This is a bitfield of WPA_CIPHER_AES_128_CMAC and WPA_CIPHER_BIP_* + * values. If 0, no constraint is used for the cipher, i.e., whatever + * the AP uses is accepted. + */ + int group_mgmt_cipher; + + /** * key_mgmt - Bitfield of allowed key management protocols * * WPA_KEY_MGMT_* @@ -392,17 +436,6 @@ struct wpa_ssid { int disabled_for_connect; /** - * peerkey - Whether PeerKey handshake for direct links is allowed - * - * This is only used when both RSN/WPA2 and IEEE 802.11e (QoS) are - * enabled. - * - * 0 = disabled (default) - * 1 = enabled - */ - int peerkey; - - /** * id_str - Network identifier string for external scripts * * This value is passed to external ctrl_iface monitors in @@ -427,6 +460,17 @@ struct wpa_ssid { enum mfp_options ieee80211w; #endif /* CONFIG_IEEE80211W */ +#ifdef CONFIG_OCV + /** + * ocv - Enable/disable operating channel validation + * + * If this parameter is set to 1, stations will exchange OCI element + * to cryptographically verify the operating channel. Setting this + * parameter to 0 disables this option. Default value: 0. + */ + int ocv; +#endif /* CONFIG_OCV */ + /** * frequency - Channel frequency in megahertz (MHz) for IBSS * @@ -470,12 +514,16 @@ struct wpa_ssid { int dot11MeshConfirmTimeout; /* msec */ int dot11MeshHoldingTimeout; /* msec */ + int ht; int ht40; int vht; - u8 max_oper_chwidth; + int he; + int max_oper_chwidth; + + unsigned int vht_center_freq1; unsigned int vht_center_freq2; /** @@ -650,6 +698,22 @@ struct wpa_ssid { * By default (empty string): Use whatever the OS has configured. */ char *ht_mcs; + + /** + * tx_stbc - Indicate STBC support for TX streams + * + * Value: -1..1, by default (-1): use whatever the OS or card has + * configured. See IEEE Std 802.11-2016, 9.4.2.56.2. + */ + int tx_stbc; + + /** + * rx_stbc - Indicate STBC support for RX streams + * + * Value: -1..3, by default (-1): use whatever the OS or card has + * configured. See IEEE Std 802.11-2016, 9.4.2.56.2. + */ + int rx_stbc; #endif /* CONFIG_HT_OVERRIDES */ #ifdef CONFIG_VHT_OVERRIDES @@ -728,10 +792,100 @@ struct wpa_ssid { * determine whether to use a secure session or not. */ int macsec_policy; + + /** + * macsec_integ_only - Determines how MACsec are transmitted + * + * This setting applies only when MACsec is in use, i.e., + * - macsec_policy is enabled + * - the key server has decided to enable MACsec + * + * 0: Encrypt traffic (default) + * 1: Integrity only + */ + int macsec_integ_only; + + /** + * macsec_replay_protect - Enable MACsec replay protection + * + * This setting applies only when MACsec is in use, i.e., + * - macsec_policy is enabled + * - the key server has decided to enable MACsec + * + * 0: Replay protection disabled (default) + * 1: Replay protection enabled + */ + int macsec_replay_protect; + + /** + * macsec_replay_window - MACsec replay protection window + * + * A window in which replay is tolerated, to allow receipt of frames + * that have been misordered by the network. + * + * This setting applies only when MACsec replay protection active, i.e., + * - macsec_replay_protect is enabled + * - the key server has decided to enable MACsec + * + * 0: No replay window, strict check (default) + * 1..2^32-1: number of packets that could be misordered + */ + u32 macsec_replay_window; + + /** + * macsec_port - MACsec port (in SCI) + * + * Port component of the SCI. + * + * Range: 1-65534 (default: 1) + */ + int macsec_port; + + /** + * mka_priority - Priority of MKA Actor + * + * Range: 0-255 (default: 255) + */ + int mka_priority; + + /** + * mka_ckn - MKA pre-shared CKN + */ +#define MACSEC_CKN_MAX_LEN 32 + size_t mka_ckn_len; + u8 mka_ckn[MACSEC_CKN_MAX_LEN]; + + /** + * mka_cak - MKA pre-shared CAK + */ +#define MACSEC_CAK_MAX_LEN 32 + size_t mka_cak_len; + u8 mka_cak[MACSEC_CAK_MAX_LEN]; + +#define MKA_PSK_SET_CKN BIT(0) +#define MKA_PSK_SET_CAK BIT(1) +#define MKA_PSK_SET (MKA_PSK_SET_CKN | MKA_PSK_SET_CAK) + /** + * mka_psk_set - Whether mka_ckn and mka_cak are set + */ + u8 mka_psk_set; #endif /* CONFIG_MACSEC */ #ifdef CONFIG_HS20 int update_identifier; + + /** + * roaming_consortium_selection - Roaming Consortium Selection + * + * The matching Roaming Consortium OI that was used to generate this + * network profile. + */ + u8 *roaming_consortium_selection; + + /** + * roaming_consortium_selection_len - roaming_consortium_selection len + */ + size_t roaming_consortium_selection_len; #endif /* CONFIG_HS20 */ unsigned int wps_run; @@ -758,12 +912,99 @@ struct wpa_ssid { int no_auto_peer; /** + * mesh_rssi_threshold - Set mesh parameter mesh_rssi_threshold (dBm) + * + * -255..-1 = threshold value in dBm + * 0 = not using RSSI threshold + * 1 = do not change driver default + */ + int mesh_rssi_threshold; + + /** * wps_disabled - WPS disabled in AP mode * * 0 = WPS enabled and configured (default) * 1 = WPS disabled */ int wps_disabled; + + /** + * fils_dh_group - FILS DH Group + * + * 0 = PFS disabled with FILS shared key authentication + * 1-65535 DH Group to use for FILS PFS + */ + int fils_dh_group; + + /** + * dpp_connector - DPP Connector (signedConnector as string) + */ + char *dpp_connector; + + /** + * dpp_netaccesskey - DPP netAccessKey (own private key) + */ + u8 *dpp_netaccesskey; + + /** + * dpp_netaccesskey_len - DPP netAccessKey length in octets + */ + size_t dpp_netaccesskey_len; + + /** + * net_access_key_expiry - DPP netAccessKey expiry in UNIX time stamp + * + * 0 indicates no expiration. + */ + unsigned int dpp_netaccesskey_expiry; + + /** + * dpp_csign - C-sign-key (Configurator public key) + */ + u8 *dpp_csign; + + /** + * dpp_csign_len - C-sign-key length in octets + */ + size_t dpp_csign_len; + + /** + * owe_group - OWE DH Group + * + * 0 = use default (19) first and then try all supported groups one by + * one if AP rejects the selected group + * 1-65535 DH Group to use for OWE + * + * Groups 19 (NIST P-256), 20 (NIST P-384), and 21 (NIST P-521) are + * currently supported. + */ + int owe_group; + + /** + * owe_only - OWE-only mode (disable transition mode) + * + * 0 = enable transition mode (allow connection to either OWE or open + * BSS) + * 1 = disable transition mode (allow connection only with OWE) + */ + int owe_only; + + /** + * owe_transition_bss_select_count - OWE transition BSS select count + * + * This is an internally used variable (i.e., not used in external + * configuration) to track the number of selection attempts done for + * OWE BSS in transition mode. This allows fallback to an open BSS if + * the selection attempts for OWE BSS exceed the configured threshold. + */ + int owe_transition_bss_select_count; + + /** + * multi_ap_backhaul_sta - Multi-AP backhaul STA + * 0 = normal (non-Multi-AP) station + * 1 = Multi-AP backhaul station + */ + int multi_ap_backhaul_sta; }; #endif /* CONFIG_SSID_H */ diff --git a/freebsd/contrib/wpa/wpa_supplicant/ctrl_iface.c b/freebsd/contrib/wpa/wpa_supplicant/ctrl_iface.c index 9699c784..c7bcfef1 100644 --- a/freebsd/contrib/wpa/wpa_supplicant/ctrl_iface.c +++ b/freebsd/contrib/wpa/wpa_supplicant/ctrl_iface.c @@ -2,7 +2,7 @@ /* * WPA Supplicant / Control interface (shared code for all backends) - * Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi> + * Copyright (c) 2004-2019, Jouni Malinen <j@w1.fi> * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -22,6 +22,9 @@ #include "common/ieee802_11_defs.h" #include "common/ieee802_11_common.h" #include "common/wpa_ctrl.h" +#ifdef CONFIG_DPP +#include "common/dpp.h" +#endif /* CONFIG_DPP */ #include "crypto/tls.h" #include "ap/hostapd.h" #include "eap_peer/eap.h" @@ -54,6 +57,8 @@ #include "offchannel.h" #include "drivers/driver.h" #include "mesh.h" +#include "dpp_supplicant.h" +#include "sme.h" static int wpa_supplicant_global_iface_list(struct wpa_global *global, char *buf, int len); @@ -63,6 +68,7 @@ static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global, static int * freq_range_to_channel_list(struct wpa_supplicant *wpa_s, char *val); + static int set_bssid_filter(struct wpa_supplicant *wpa_s, char *val) { char *pos; @@ -341,6 +347,75 @@ static int wpas_ctrl_iface_set_lci(struct wpa_supplicant *wpa_s, } +static int +wpas_ctrl_set_relative_rssi(struct wpa_supplicant *wpa_s, const char *cmd) +{ + int relative_rssi; + + if (os_strcmp(cmd, "disable") == 0) { + wpa_s->srp.relative_rssi_set = 0; + return 0; + } + + relative_rssi = atoi(cmd); + if (relative_rssi < 0 || relative_rssi > 100) + return -1; + wpa_s->srp.relative_rssi = relative_rssi; + wpa_s->srp.relative_rssi_set = 1; + return 0; +} + + +static int wpas_ctrl_set_relative_band_adjust(struct wpa_supplicant *wpa_s, + const char *cmd) +{ + char *pos; + int adjust_rssi; + + /* <band>:adjust_value */ + pos = os_strchr(cmd, ':'); + if (!pos) + return -1; + pos++; + adjust_rssi = atoi(pos); + if (adjust_rssi < -100 || adjust_rssi > 100) + return -1; + + if (os_strncmp(cmd, "2G", 2) == 0) + wpa_s->srp.relative_adjust_band = WPA_SETBAND_2G; + else if (os_strncmp(cmd, "5G", 2) == 0) + wpa_s->srp.relative_adjust_band = WPA_SETBAND_5G; + else + return -1; + + wpa_s->srp.relative_adjust_rssi = adjust_rssi; + + return 0; +} + + +static int wpas_ctrl_iface_set_ric_ies(struct wpa_supplicant *wpa_s, + const char *cmd) +{ + struct wpabuf *ric_ies; + + if (*cmd == '\0' || os_strcmp(cmd, "\"\"") == 0) { + wpabuf_free(wpa_s->ric_ies); + wpa_s->ric_ies = NULL; + return 0; + } + + ric_ies = wpabuf_parse_bin(cmd); + if (!ric_ies) + return -1; + + wpabuf_free(wpa_s->ric_ies); + wpa_s->ric_ies = ric_ies; + + return 0; +} + + static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s, char *cmd) { @@ -367,16 +442,29 @@ static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s, -1, -1, -1, atoi(value)); } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKLifetime") == 0) { if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME, - atoi(value))) + atoi(value))) { ret = -1; + } else { + value[-1] = '='; + wpa_config_process_global(wpa_s->conf, cmd, -1); + } } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKReauthThreshold") == 0) { if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD, - atoi(value))) + atoi(value))) { ret = -1; + } else { + value[-1] = '='; + wpa_config_process_global(wpa_s->conf, cmd, -1); + } } else if (os_strcasecmp(cmd, "dot11RSNAConfigSATimeout") == 0) { - if (wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, atoi(value))) + if (wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, + atoi(value))) { ret = -1; + } else { + value[-1] = '='; + wpa_config_process_global(wpa_s->conf, cmd, -1); + } } else if (os_strcasecmp(cmd, "wps_fragment_size") == 0) { wpa_s->wps_fragment_size = atoi(value); #ifdef CONFIG_WPS_TESTING @@ -496,6 +584,59 @@ static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s, ret = set_disallow_aps(wpa_s, value); } else if (os_strcasecmp(cmd, "no_keep_alive") == 0) { wpa_s->no_keep_alive = !!atoi(value); +#ifdef CONFIG_DPP + } else if (os_strcasecmp(cmd, "dpp_configurator_params") == 0) { + os_free(wpa_s->dpp_configurator_params); + wpa_s->dpp_configurator_params = os_strdup(value); + } else if (os_strcasecmp(cmd, "dpp_init_max_tries") == 0) { + wpa_s->dpp_init_max_tries = atoi(value); + } else if (os_strcasecmp(cmd, "dpp_init_retry_time") == 0) { + wpa_s->dpp_init_retry_time = atoi(value); + } else if (os_strcasecmp(cmd, "dpp_resp_wait_time") == 0) { + wpa_s->dpp_resp_wait_time = atoi(value); + } else if (os_strcasecmp(cmd, "dpp_resp_max_tries") == 0) { + wpa_s->dpp_resp_max_tries = atoi(value); + } else if (os_strcasecmp(cmd, "dpp_resp_retry_time") == 0) { + wpa_s->dpp_resp_retry_time = atoi(value); +#ifdef CONFIG_TESTING_OPTIONS + } else if (os_strcasecmp(cmd, "dpp_pkex_own_mac_override") == 0) { + if (hwaddr_aton(value, dpp_pkex_own_mac_override)) + ret = -1; + } else if (os_strcasecmp(cmd, "dpp_pkex_peer_mac_override") == 0) { + if (hwaddr_aton(value, dpp_pkex_peer_mac_override)) + ret = -1; + } else if (os_strcasecmp(cmd, "dpp_pkex_ephemeral_key_override") == 0) { + size_t hex_len = os_strlen(value); + + if (hex_len > + 2 * sizeof(dpp_pkex_ephemeral_key_override)) + ret = -1; + else if (hexstr2bin(value, dpp_pkex_ephemeral_key_override, + hex_len / 2)) + ret = -1; + else + dpp_pkex_ephemeral_key_override_len = hex_len / 2; + } else if (os_strcasecmp(cmd, "dpp_protocol_key_override") == 0) { + size_t hex_len = os_strlen(value); + + if (hex_len > 2 * sizeof(dpp_protocol_key_override)) + ret = -1; + else if (hexstr2bin(value, dpp_protocol_key_override, + hex_len / 2)) + ret = -1; + else + dpp_protocol_key_override_len = hex_len / 2; + } else if (os_strcasecmp(cmd, "dpp_nonce_override") == 0) { + size_t hex_len = os_strlen(value); + + if (hex_len > 2 * sizeof(dpp_nonce_override)) + ret = -1; + else if (hexstr2bin(value, dpp_nonce_override, hex_len / 2)) + ret = -1; + else + dpp_nonce_override_len = hex_len / 2; +#endif /* CONFIG_TESTING_OPTIONS */ +#endif /* CONFIG_DPP */ #ifdef CONFIG_TESTING_OPTIONS } else if (os_strcasecmp(cmd, "ext_mgmt_frame_handling") == 0) { wpa_s->ext_mgmt_frame_handling = !!atoi(value); @@ -517,9 +658,54 @@ static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s, wpa_s->ignore_auth_resp = !!atoi(value); } else if (os_strcasecmp(cmd, "ignore_assoc_disallow") == 0) { wpa_s->ignore_assoc_disallow = !!atoi(value); + wpa_drv_ignore_assoc_disallow(wpa_s, + wpa_s->ignore_assoc_disallow); } else if (os_strcasecmp(cmd, "reject_btm_req_reason") == 0) { wpa_s->reject_btm_req_reason = atoi(value); + } else if (os_strcasecmp(cmd, "get_pref_freq_list_override") == 0) { + os_free(wpa_s->get_pref_freq_list_override); + if (!value[0]) + wpa_s->get_pref_freq_list_override = NULL; + else + wpa_s->get_pref_freq_list_override = os_strdup(value); + } else if (os_strcasecmp(cmd, "sae_commit_override") == 0) { + wpabuf_free(wpa_s->sae_commit_override); + if (value[0] == '\0') + wpa_s->sae_commit_override = NULL; + else + wpa_s->sae_commit_override = wpabuf_parse_bin(value); +#ifdef CONFIG_DPP + } else if (os_strcasecmp(cmd, "dpp_config_obj_override") == 0) { + os_free(wpa_s->dpp_config_obj_override); + if (value[0] == '\0') + wpa_s->dpp_config_obj_override = NULL; + else + wpa_s->dpp_config_obj_override = os_strdup(value); + } else if (os_strcasecmp(cmd, "dpp_discovery_override") == 0) { + os_free(wpa_s->dpp_discovery_override); + if (value[0] == '\0') + wpa_s->dpp_discovery_override = NULL; + else + wpa_s->dpp_discovery_override = os_strdup(value); + } else if (os_strcasecmp(cmd, "dpp_groups_override") == 0) { + os_free(wpa_s->dpp_groups_override); + if (value[0] == '\0') + wpa_s->dpp_groups_override = NULL; + else + wpa_s->dpp_groups_override = os_strdup(value); + } else if (os_strcasecmp(cmd, + "dpp_ignore_netaccesskey_mismatch") == 0) { + wpa_s->dpp_ignore_netaccesskey_mismatch = atoi(value); + } else if (os_strcasecmp(cmd, "dpp_test") == 0) { + dpp_test = atoi(value); +#endif /* CONFIG_DPP */ #endif /* CONFIG_TESTING_OPTIONS */ +#ifdef CONFIG_FILS + } else if (os_strcasecmp(cmd, "disable_fils") == 0) { + wpa_s->disable_fils = !!atoi(value); + wpa_drv_disable_fils(wpa_s, wpa_s->disable_fils); + wpa_supplicant_set_default_scan_ies(wpa_s); +#endif /* CONFIG_FILS */ #ifndef CONFIG_NO_CONFIG_BLOBS } else if (os_strcmp(cmd, "blob") == 0) { ret = wpas_ctrl_set_blob(wpa_s, value); @@ -529,11 +715,53 @@ static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s, #ifdef CONFIG_MBO } else if (os_strcasecmp(cmd, "non_pref_chan") == 0) { ret = wpas_mbo_update_non_pref_chan(wpa_s, value); + if (ret == 0) { + value[-1] = '='; + wpa_config_process_global(wpa_s->conf, cmd, -1); + } } else if (os_strcasecmp(cmd, "mbo_cell_capa") == 0) { wpas_mbo_update_cell_capa(wpa_s, atoi(value)); + } else if (os_strcasecmp(cmd, "oce") == 0) { + wpa_s->conf->oce = atoi(value); + if (wpa_s->conf->oce) { + if ((wpa_s->conf->oce & OCE_STA) && + (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA)) + wpa_s->enable_oce = OCE_STA; + + if ((wpa_s->conf->oce & OCE_STA_CFON) && + (wpa_s->drv_flags & + WPA_DRIVER_FLAGS_OCE_STA_CFON)) { + /* TODO: Need to add STA-CFON support */ + wpa_printf(MSG_ERROR, + "OCE STA-CFON feature is not yet supported"); + return -1; + } + } else { + wpa_s->enable_oce = 0; + } + wpa_supplicant_set_default_scan_ies(wpa_s); #endif /* CONFIG_MBO */ } else if (os_strcasecmp(cmd, "lci") == 0) { ret = wpas_ctrl_iface_set_lci(wpa_s, value); + } else if (os_strcasecmp(cmd, "tdls_trigger_control") == 0) { + ret = wpa_drv_set_tdls_mode(wpa_s, atoi(value)); + } else if (os_strcasecmp(cmd, "relative_rssi") == 0) { + ret = wpas_ctrl_set_relative_rssi(wpa_s, value); + } else if (os_strcasecmp(cmd, "relative_band_adjust") == 0) { + ret = wpas_ctrl_set_relative_band_adjust(wpa_s, value); + } else if (os_strcasecmp(cmd, "ric_ies") == 0) { + ret = wpas_ctrl_iface_set_ric_ies(wpa_s, value); + } else if (os_strcasecmp(cmd, "roaming") == 0) { + ret = wpa_drv_roaming(wpa_s, atoi(value), NULL); +#ifdef CONFIG_WNM + } else if (os_strcasecmp(cmd, "coloc_intf_elems") == 0) { + struct wpabuf *elems; + + elems = wpabuf_parse_bin(value); + if (!elems) + return -1; + wnm_set_coloc_intf_elems(wpa_s, elems); +#endif /* CONFIG_WNM */ } else { value[-1] = '='; ret = wpa_config_process_global(wpa_s->conf, cmd, -1); @@ -579,6 +807,12 @@ static int wpa_supplicant_ctrl_iface_get(struct wpa_supplicant *wpa_s, #endif /* CONFIG_TESTING_GET_GTK */ } else if (os_strcmp(cmd, "tls_library") == 0) { res = tls_get_library_version(buf, buflen); +#ifdef CONFIG_TESTING_OPTIONS + } else if (os_strcmp(cmd, "anonce") == 0) { + return wpa_snprintf_hex(buf, buflen, + wpa_sm_get_anonce(wpa_s->wpa), + WPA_NONCE_LEN); +#endif /* CONFIG_TESTING_OPTIONS */ } else { res = wpa_config_get_value(cmd, wpa_s->conf, buf, buflen); } @@ -612,27 +846,6 @@ static int wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant *wpa_s, #endif /* IEEE8021X_EAPOL */ -#ifdef CONFIG_PEERKEY -/* MLME-STKSTART.request(peer) */ -static int wpa_supplicant_ctrl_iface_stkstart( - struct wpa_supplicant *wpa_s, char *addr) -{ - u8 peer[ETH_ALEN]; - - if (hwaddr_aton(addr, peer)) { - wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART: invalid " - "address '%s'", addr); - return -1; - } - - wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART " MACSTR, - MAC2STR(peer)); - - return wpa_sm_stkstart(wpa_s->wpa, peer); -} -#endif /* CONFIG_PEERKEY */ - - #ifdef CONFIG_TDLS static int wpa_supplicant_ctrl_iface_tdls_discover( @@ -957,8 +1170,11 @@ static int wpa_supplicant_ctrl_iface_wps_pbc(struct wpa_supplicant *wpa_s, #ifdef CONFIG_AP u8 *_p2p_dev_addr = NULL; #endif /* CONFIG_AP */ + char *pos; + int multi_ap = 0; - if (cmd == NULL || os_strcmp(cmd, "any") == 0) { + if (!cmd || os_strcmp(cmd, "any") == 0 || + os_strncmp(cmd, "any ", 4) == 0) { _bssid = NULL; #ifdef CONFIG_P2P } else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) { @@ -970,18 +1186,29 @@ static int wpa_supplicant_ctrl_iface_wps_pbc(struct wpa_supplicant *wpa_s, } _p2p_dev_addr = p2p_dev_addr; #endif /* CONFIG_P2P */ + } else if (os_strncmp(cmd, "multi_ap=", 9) == 0) { + _bssid = NULL; + multi_ap = atoi(cmd + 9); } else if (hwaddr_aton(cmd, bssid)) { wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid BSSID '%s'", cmd); return -1; } + if (cmd) { + pos = os_strstr(cmd, " multi_ap="); + if (pos) { + pos += 10; + multi_ap = atoi(pos); + } + } + #ifdef CONFIG_AP if (wpa_s->ap_iface) return wpa_supplicant_ap_wps_pbc(wpa_s, _bssid, _p2p_dev_addr); #endif /* CONFIG_AP */ - return wpas_wps_start_pbc(wpa_s, _bssid, 0); + return wpas_wps_start_pbc(wpa_s, _bssid, 0, multi_ap); } @@ -1907,6 +2134,18 @@ static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s, pos += ret; } + if (wpa_s->connection_set && + (wpa_s->connection_ht || wpa_s->connection_vht || + wpa_s->connection_he)) { + ret = os_snprintf(pos, end - pos, + "wifi_generation=%u\n", + wpa_s->connection_he ? 6 : + (wpa_s->connection_vht ? 5 : 4)); + if (os_snprintf_error(end - pos, ret)) + return pos - buf; + pos += ret; + } + #ifdef CONFIG_AP if (wpa_s->ap_iface) { pos += ap_ctrl_iface_wpa_get_status(wpa_s, pos, @@ -1916,6 +2155,7 @@ static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s, #endif /* CONFIG_AP */ pos += wpa_sm_get_status(wpa_s->wpa, pos, end - pos, verbose); } +#ifdef CONFIG_SME #ifdef CONFIG_SAE if (wpa_s->wpa_state >= WPA_ASSOCIATED && #ifdef CONFIG_AP @@ -1929,6 +2169,7 @@ static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s, pos += ret; } #endif /* CONFIG_SAE */ +#endif /* CONFIG_SME */ ret = os_snprintf(pos, end - pos, "wpa_state=%s\n", wpa_supplicant_state_txt(wpa_s->wpa_state)); if (os_snprintf_error(end - pos, ret)) @@ -2050,6 +2291,12 @@ static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s, pos += res; } +#ifdef CONFIG_MACSEC + res = ieee802_1x_kay_get_status(wpa_s->kay, pos, end - pos); + if (res > 0) + pos += res; +#endif /* CONFIG_MACSEC */ + sess_id = eapol_sm_get_session_id(wpa_s->eapol, &sess_id_len); if (sess_id) { char *start = pos; @@ -2083,6 +2330,13 @@ static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s, } #endif /* CONFIG_WPS */ + if (wpa_s->ieee80211ac) { + ret = os_snprintf(pos, end - pos, "ieee80211ac=1\n"); + if (os_snprintf_error(end - pos, ret)) + return pos - buf; + pos += ret; + } + #ifdef ANDROID /* * Allow using the STATUS command with default behavior, say for debug, @@ -2439,6 +2693,59 @@ static char * wpa_supplicant_ie_txt(char *pos, char *end, const char *proto, } #endif /* CONFIG_SUITEB192 */ +#ifdef CONFIG_FILS + if (data.key_mgmt & WPA_KEY_MGMT_FILS_SHA256) { + ret = os_snprintf(pos, end - pos, "%sFILS-SHA256", + pos == start ? "" : "+"); + if (os_snprintf_error(end - pos, ret)) + return pos; + pos += ret; + } + if (data.key_mgmt & WPA_KEY_MGMT_FILS_SHA384) { + ret = os_snprintf(pos, end - pos, "%sFILS-SHA384", + pos == start ? "" : "+"); + if (os_snprintf_error(end - pos, ret)) + return pos; + pos += ret; + } +#ifdef CONFIG_IEEE80211R + if (data.key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA256) { + ret = os_snprintf(pos, end - pos, "%sFT-FILS-SHA256", + pos == start ? "" : "+"); + if (os_snprintf_error(end - pos, ret)) + return pos; + pos += ret; + } + if (data.key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA384) { + ret = os_snprintf(pos, end - pos, "%sFT-FILS-SHA384", + pos == start ? "" : "+"); + if (os_snprintf_error(end - pos, ret)) + return pos; + pos += ret; + } +#endif /* CONFIG_IEEE80211R */ +#endif /* CONFIG_FILS */ + +#ifdef CONFIG_OWE + if (data.key_mgmt & WPA_KEY_MGMT_OWE) { + ret = os_snprintf(pos, end - pos, "%sOWE", + pos == start ? "" : "+"); + if (os_snprintf_error(end - pos, ret)) + return pos; + pos += ret; + } +#endif /* CONFIG_OWE */ + +#ifdef CONFIG_DPP + if (data.key_mgmt & WPA_KEY_MGMT_DPP) { + ret = os_snprintf(pos, end - pos, "%sDPP", + pos == start ? "" : "+"); + if (os_snprintf_error(end - pos, ret)) + return pos; + pos += ret; + } +#endif /* CONFIG_DPP */ + if (data.key_mgmt & WPA_KEY_MGMT_OSEN) { ret = os_snprintf(pos, end - pos, "%sOSEN", pos == start ? "" : "+"); @@ -2514,7 +2821,7 @@ static int wpa_supplicant_ctrl_iface_scan_result( { char *pos, *end; int ret; - const u8 *ie, *ie2, *osen_ie, *p2p, *mesh; + const u8 *ie, *ie2, *osen_ie, *p2p, *mesh, *owe; mesh = wpa_bss_get_ie(bss, WLAN_EID_MESH_ID); p2p = wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE); @@ -2545,6 +2852,14 @@ static int wpa_supplicant_ctrl_iface_scan_result( if (osen_ie) pos = wpa_supplicant_ie_txt(pos, end, "OSEN", osen_ie, 2 + osen_ie[1]); + owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE); + if (owe) { + ret = os_snprintf(pos, end - pos, + ie2 ? "[OWE-TRANS]" : "[OWE-TRANS-OPEN]"); + if (os_snprintf_error(end - pos, ret)) + return -1; + pos += ret; + } pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss); if (!ie && !ie2 && !osen_ie && (bss->caps & IEEE80211_CAP_PRIVACY)) { ret = os_snprintf(pos, end - pos, "[WEP]"); @@ -2610,6 +2925,14 @@ static int wpa_supplicant_ctrl_iface_scan_result( pos += ret; } #endif /* CONFIG_HS20 */ +#ifdef CONFIG_FILS + if (wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION)) { + ret = os_snprintf(pos, end - pos, "[FILS]"); + if (os_snprintf_error(end - pos, ret)) + return -1; + pos += ret; + } +#endif /* CONFIG_FILS */ #ifdef CONFIG_FST if (wpa_bss_get_ie(bss, WLAN_EID_MULTI_BAND)) { ret = os_snprintf(pos, end - pos, "[FST]"); @@ -2618,6 +2941,12 @@ static int wpa_supplicant_ctrl_iface_scan_result( pos += ret; } #endif /* CONFIG_FST */ + if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_UTF_8_SSID)) { + ret = os_snprintf(pos, end - pos, "[UTF-8]"); + if (os_snprintf_error(end - pos, ret)) + return -1; + pos += ret; + } ret = os_snprintf(pos, end - pos, "\t%s", wpa_ssid_txt(bss->ssid, bss->ssid_len)); @@ -2837,9 +3166,8 @@ static int wpa_supplicant_ctrl_iface_select_network( if (pos) { int *freqs = freq_range_to_channel_list(wpa_s, pos + 6); if (freqs) { - wpa_s->scan_req = MANUAL_SCAN_REQ; - os_free(wpa_s->manual_scan_freqs); - wpa_s->manual_scan_freqs = freqs; + os_free(wpa_s->select_network_scan_freqs); + wpa_s->select_network_scan_freqs = freqs; } } @@ -3014,6 +3342,7 @@ static int wpa_supplicant_ctrl_iface_update_network( return 0; /* No change to the previously configured value */ if (os_strcmp(name, "bssid") != 0 && + os_strcmp(name, "bssid_hint") != 0 && os_strcmp(name, "priority") != 0) { wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid); @@ -3649,6 +3978,66 @@ static int ctrl_iface_get_capability_key_mgmt(int res, char *strict, pos += ret; } #endif /* CONFIG_SUITEB192 */ +#ifdef CONFIG_OWE + if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_OWE) { + ret = os_snprintf(pos, end - pos, " OWE"); + if (os_snprintf_error(end - pos, ret)) + return pos - buf; + pos += ret; + } +#endif /* CONFIG_OWE */ +#ifdef CONFIG_DPP + if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_DPP) { + ret = os_snprintf(pos, end - pos, " DPP"); + if (os_snprintf_error(end - pos, ret)) + return pos - buf; + pos += ret; + } +#endif /* CONFIG_DPP */ +#ifdef CONFIG_FILS + if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA256) { + ret = os_snprintf(pos, end - pos, " FILS-SHA256"); + if (os_snprintf_error(end - pos, ret)) + return pos - buf; + pos += ret; + } + if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384) { + ret = os_snprintf(pos, end - pos, " FILS-SHA384"); + if (os_snprintf_error(end - pos, ret)) + return pos - buf; + pos += ret; + } +#ifdef CONFIG_IEEE80211R + if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA256) { + ret = os_snprintf(pos, end - pos, " FT-FILS-SHA256"); + if (os_snprintf_error(end - pos, ret)) + return pos - buf; + pos += ret; + } + if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA384) { + ret = os_snprintf(pos, end - pos, " FT-FILS-SHA384"); + if (os_snprintf_error(end - pos, ret)) + return pos - buf; + pos += ret; + } +#endif /* CONFIG_IEEE80211R */ +#endif /* CONFIG_FILS */ +#ifdef CONFIG_IEEE80211R + if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK) { + ret = os_snprintf(pos, end - pos, " FT-PSK"); + if (os_snprintf_error(end - pos, ret)) + return pos - buf; + pos += ret; + } +#endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_SAE + if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SAE) { + ret = os_snprintf(pos, end - pos, " SAE"); + if (os_snprintf_error(end - pos, ret)) + return pos - buf; + pos += ret; + } +#endif /* CONFIG_SAE */ return pos - buf; } @@ -3751,6 +4140,26 @@ static int ctrl_iface_get_capability_auth_alg(struct wpa_supplicant *wpa_s, } #endif /* CONFIG_SAE */ +#ifdef CONFIG_FILS + if (wpa_is_fils_supported(wpa_s)) { + ret = os_snprintf(pos, end - pos, "%sFILS_SK_WITHOUT_PFS", + pos == buf ? "" : " "); + if (os_snprintf_error(end - pos, ret)) + return pos - buf; + pos += ret; + } + +#ifdef CONFIG_FILS_SK_PFS + if (wpa_is_fils_sk_pfs_supported(wpa_s)) { + ret = os_snprintf(pos, end - pos, "%sFILS_SK_WITH_PFS", + pos == buf ? "" : " "); + if (os_snprintf_error(end - pos, ret)) + return pos - buf; + pos += ret; + } +#endif /* CONFIG_FILS_SK_PFS */ +#endif /* CONFIG_FILS */ + return pos - buf; } @@ -4008,6 +4417,47 @@ static int wpa_supplicant_ctrl_iface_get_capability( } #endif /* CONFIG_ACS */ +#ifdef CONFIG_FILS + if (os_strcmp(field, "fils") == 0) { +#ifdef CONFIG_FILS_SK_PFS + if (wpa_is_fils_supported(wpa_s) && + wpa_is_fils_sk_pfs_supported(wpa_s)) { + res = os_snprintf(buf, buflen, "FILS FILS-SK-PFS"); + if (os_snprintf_error(buflen, res)) + return -1; + return res; + } +#endif /* CONFIG_FILS_SK_PFS */ + + if (wpa_is_fils_supported(wpa_s)) { + res = os_snprintf(buf, buflen, "FILS"); + if (os_snprintf_error(buflen, res)) + return -1; + return res; + } + } +#endif /* CONFIG_FILS */ + + if (os_strcmp(field, "multibss") == 0 && wpa_s->multi_bss_support) { + res = os_snprintf(buf, buflen, "MULTIBSS-STA"); + if (os_snprintf_error(buflen, res)) + return -1; + return res; + } + +#ifdef CONFIG_DPP + if (os_strcmp(field, "dpp") == 0) { +#ifdef CONFIG_DPP2 + res = os_snprintf(buf, buflen, "DPP=2"); +#else /* CONFIG_DPP2 */ + res = os_snprintf(buf, buflen, "DPP=1"); +#endif /* CONFIG_DPP2 */ + if (os_snprintf_error(buflen, res)) + return -1; + return res; + } +#endif /* CONFIG_DPP */ + wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'", field); @@ -4050,13 +4500,85 @@ static char * anqp_add_hex(char *pos, char *end, const char *title, #endif /* CONFIG_INTERWORKING */ +#ifdef CONFIG_FILS +static int print_fils_indication(struct wpa_bss *bss, char *pos, char *end) +{ + char *start = pos; + const u8 *ie, *ie_end; + u16 info, realms; + int ret; + + ie = wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION); + if (!ie) + return 0; + ie_end = ie + 2 + ie[1]; + ie += 2; + if (ie_end - ie < 2) + return -1; + + info = WPA_GET_LE16(ie); + ie += 2; + ret = os_snprintf(pos, end - pos, "fils_info=%04x\n", info); + if (os_snprintf_error(end - pos, ret)) + return 0; + pos += ret; + + if (info & BIT(7)) { + /* Cache Identifier Included */ + if (ie_end - ie < 2) + return -1; + ret = os_snprintf(pos, end - pos, "fils_cache_id=%02x%02x\n", + ie[0], ie[1]); + if (os_snprintf_error(end - pos, ret)) + return 0; + pos += ret; + ie += 2; + } + + if (info & BIT(8)) { + /* HESSID Included */ + if (ie_end - ie < ETH_ALEN) + return -1; + ret = os_snprintf(pos, end - pos, "fils_hessid=" MACSTR "\n", + MAC2STR(ie)); + if (os_snprintf_error(end - pos, ret)) + return 0; + pos += ret; + ie += ETH_ALEN; + } + + realms = (info & (BIT(3) | BIT(4) | BIT(5))) >> 3; + if (realms) { + if (ie_end - ie < realms * 2) + return -1; + ret = os_snprintf(pos, end - pos, "fils_realms="); + if (os_snprintf_error(end - pos, ret)) + return 0; + pos += ret; + + ret = wpa_snprintf_hex(pos, end - pos, ie, realms * 2); + if (ret <= 0) + return 0; + pos += ret; + ie += realms * 2; + ret = os_snprintf(pos, end - pos, "\n"); + if (os_snprintf_error(end - pos, ret)) + return 0; + pos += ret; + } + + return pos - start; +} +#endif /* CONFIG_FILS */ + + static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, unsigned long mask, char *buf, size_t buflen) { size_t i; int ret; char *pos, *end; - const u8 *ie, *ie2, *osen_ie; + const u8 *ie, *ie2, *osen_ie, *mesh, *owe; pos = buf; end = buf + buflen; @@ -4165,18 +4687,30 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, return 0; pos += ret; + mesh = wpa_bss_get_ie(bss, WLAN_EID_MESH_ID); + ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE); if (ie) pos = wpa_supplicant_ie_txt(pos, end, "WPA", ie, 2 + ie[1]); ie2 = wpa_bss_get_ie(bss, WLAN_EID_RSN); if (ie2) - pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2, + pos = wpa_supplicant_ie_txt(pos, end, + mesh ? "RSN" : "WPA2", ie2, 2 + ie2[1]); osen_ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE); if (osen_ie) pos = wpa_supplicant_ie_txt(pos, end, "OSEN", osen_ie, 2 + osen_ie[1]); + owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE); + if (owe) { + ret = os_snprintf( + pos, end - pos, + ie2 ? "[OWE-TRANS]" : "[OWE-TRANS-OPEN]"); + if (os_snprintf_error(end - pos, ret)) + return 0; + pos += ret; + } pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss); if (!ie && !ie2 && !osen_ie && (bss->caps & IEEE80211_CAP_PRIVACY)) { @@ -4185,6 +4719,14 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, return 0; pos += ret; } + + if (mesh) { + ret = os_snprintf(pos, end - pos, "[MESH]"); + if (os_snprintf_error(end - pos, ret)) + return 0; + pos += ret; + } + if (bss_is_dmg(bss)) { const char *s; ret = os_snprintf(pos, end - pos, "[DMG]"); @@ -4238,6 +4780,28 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, pos += ret; } #endif /* CONFIG_HS20 */ +#ifdef CONFIG_FILS + if (wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION)) { + ret = os_snprintf(pos, end - pos, "[FILS]"); + if (os_snprintf_error(end - pos, ret)) + return 0; + pos += ret; + } +#endif /* CONFIG_FILS */ +#ifdef CONFIG_FST + if (wpa_bss_get_ie(bss, WLAN_EID_MULTI_BAND)) { + ret = os_snprintf(pos, end - pos, "[FST]"); + if (os_snprintf_error(end - pos, ret)) + return 0; + pos += ret; + } +#endif /* CONFIG_FST */ + if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_UTF_8_SSID)) { + ret = os_snprintf(pos, end - pos, "[UTF-8]"); + if (os_snprintf_error(end - pos, ret)) + return 0; + pos += ret; + } ret = os_snprintf(pos, end - pos, "\n"); if (os_snprintf_error(end - pos, ret)) @@ -4322,6 +4886,8 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, pos = anqp_add_hex(pos, end, "anqp_3gpp", anqp->anqp_3gpp); pos = anqp_add_hex(pos, end, "anqp_domain_name", anqp->domain_name); + pos = anqp_add_hex(pos, end, "anqp_fils_realm_info", + anqp->fils_realm_info); #ifdef CONFIG_HS20 pos = anqp_add_hex(pos, end, "hs20_capability_list", anqp->hs20_capability_list); @@ -4335,6 +4901,10 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, anqp->hs20_operating_class); pos = anqp_add_hex(pos, end, "hs20_osu_providers_list", anqp->hs20_osu_providers_list); + pos = anqp_add_hex(pos, end, "hs20_operator_icon_metadata", + anqp->hs20_operator_icon_metadata); + pos = anqp_add_hex(pos, end, "hs20_osu_providers_nai_list", + anqp->hs20_osu_providers_nai_list); #endif /* CONFIG_HS20 */ dl_list_for_each(elem, &anqp->anqp_elems, @@ -4383,6 +4953,44 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, } #endif /* CONFIG_FST */ + if (mask & WPA_BSS_MASK_UPDATE_IDX) { + ret = os_snprintf(pos, end - pos, "update_idx=%u\n", + bss->last_update_idx); + if (os_snprintf_error(end - pos, ret)) + return 0; + pos += ret; + } + + if ((mask & WPA_BSS_MASK_BEACON_IE) && bss->beacon_ie_len) { + ret = os_snprintf(pos, end - pos, "beacon_ie="); + if (os_snprintf_error(end - pos, ret)) + return 0; + pos += ret; + + ie = (const u8 *) (bss + 1); + ie += bss->ie_len; + for (i = 0; i < bss->beacon_ie_len; i++) { + ret = os_snprintf(pos, end - pos, "%02x", *ie++); + if (os_snprintf_error(end - pos, ret)) + return 0; + pos += ret; + } + + ret = os_snprintf(pos, end - pos, "\n"); + if (os_snprintf_error(end - pos, ret)) + return 0; + pos += ret; + } + +#ifdef CONFIG_FILS + if (mask & WPA_BSS_MASK_FILS_INDICATION) { + ret = print_fils_indication(bss, pos, end); + if (ret < 0) + return 0; + pos += ret; + } +#endif /* CONFIG_FILS */ + if (mask & WPA_BSS_MASK_DELIM) { ret = os_snprintf(pos, end - pos, "====\n"); if (os_snprintf_error(end - pos, ret)) @@ -4473,6 +5081,8 @@ static int wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant *wpa_s, bss = dl_list_entry(next, struct wpa_bss, list_id); } + } else if (os_strncmp(cmd, "CURRENT", 7) == 0) { + bss = wpa_s->current_bss; #ifdef CONFIG_P2P } else if (os_strncmp(cmd, "p2p_dev_addr=", 13) == 0) { if (hwaddr_aton(cmd + 13, bssid) == 0) @@ -4488,10 +5098,11 @@ static int wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant *wpa_s, bss = NULL; dl_list_for_each(tmp, &wpa_s->bss_id, struct wpa_bss, list_id) { - if (i-- == 0) { + if (i == 0) { bss = tmp; break; } + i--; } } @@ -4977,6 +5588,7 @@ static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd, int ht40, vht, max_oper_chwidth, chwidth = 0, freq2 = 0; u8 _group_ssid[SSID_MAX_LEN], *group_ssid = NULL; size_t group_ssid_len = 0; + int he; if (!wpa_s->global->p2p_init_wpa_s) return -1; @@ -4989,7 +5601,7 @@ static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd, /* <addr> <"pbc" | "pin" | PIN> [label|display|keypad|p2ps] * [persistent|persistent=<network id>] * [join] [auth] [go_intent=<0..15>] [freq=<in MHz>] [provdisc] - * [ht40] [vht] [auto] [ssid=<hexdump>] */ + * [ht40] [vht] [he] [auto] [ssid=<hexdump>] */ if (hwaddr_aton(cmd, addr)) return -1; @@ -5020,6 +5632,7 @@ static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd, vht = (os_strstr(cmd, " vht") != NULL) || wpa_s->conf->p2p_go_vht; ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40 || vht; + he = (os_strstr(cmd, " he") != NULL) || wpa_s->conf->p2p_go_he; pos2 = os_strstr(pos, " go_intent="); if (pos2) { @@ -5090,7 +5703,7 @@ static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd, new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method, persistent_group, automatic, join, auth, go_intent, freq, freq2, persistent_id, - pd, ht40, vht, max_oper_chwidth, + pd, ht40, vht, max_oper_chwidth, he, group_ssid, group_ssid_len); if (new_pin == -2) { os_memcpy(buf, "FAIL-CHANNEL-UNAVAILABLE\n", 25); @@ -5646,7 +6259,7 @@ static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd) struct wpa_ssid *ssid; u8 *_peer = NULL, peer[ETH_ALEN]; int freq = 0, pref_freq = 0; - int ht40, vht, max_oper_chwidth, chwidth = 0, freq2 = 0; + int ht40, vht, he, max_oper_chwidth, chwidth = 0, freq2 = 0; id = atoi(cmd); pos = os_strstr(cmd, " peer="); @@ -5683,6 +6296,7 @@ static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd) vht = (os_strstr(cmd, " vht") != NULL) || wpa_s->conf->p2p_go_vht; ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40 || vht; + he = (os_strstr(cmd, " he") != NULL) || wpa_s->conf->p2p_go_he; pos = os_strstr(cmd, "freq2="); if (pos) @@ -5697,7 +6311,7 @@ static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd) return -1; return wpas_p2p_invite(wpa_s, _peer, ssid, NULL, freq, freq2, ht40, vht, - max_oper_chwidth, pref_freq); + max_oper_chwidth, pref_freq, he); } @@ -5745,7 +6359,8 @@ static int p2p_ctrl_invite(struct wpa_supplicant *wpa_s, char *cmd) static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s, int id, int freq, int vht_center_freq2, - int ht40, int vht, int vht_chwidth) + int ht40, int vht, int vht_chwidth, + int he) { struct wpa_ssid *ssid; @@ -5759,7 +6374,7 @@ static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s, return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, vht_center_freq2, 0, ht40, vht, - vht_chwidth, NULL, 0, 0); + vht_chwidth, he, NULL, 0, 0); } @@ -5768,20 +6383,31 @@ static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd) int freq = 0, persistent = 0, group_id = -1; int vht = wpa_s->conf->p2p_go_vht; int ht40 = wpa_s->conf->p2p_go_ht40 || vht; + int he = wpa_s->conf->p2p_go_he; int max_oper_chwidth, chwidth = 0, freq2 = 0; char *token, *context = NULL; +#ifdef CONFIG_ACS + int acs = 0; +#endif /* CONFIG_ACS */ while ((token = str_token(cmd, " ", &context))) { - if (sscanf(token, "freq=%d", &freq) == 1 || - sscanf(token, "freq2=%d", &freq2) == 1 || + if (sscanf(token, "freq2=%d", &freq2) == 1 || sscanf(token, "persistent=%d", &group_id) == 1 || sscanf(token, "max_oper_chwidth=%d", &chwidth) == 1) { continue; +#ifdef CONFIG_ACS + } else if (os_strcmp(token, "freq=acs") == 0) { + acs = 1; +#endif /* CONFIG_ACS */ + } else if (sscanf(token, "freq=%d", &freq) == 1) { + continue; } else if (os_strcmp(token, "ht40") == 0) { ht40 = 1; } else if (os_strcmp(token, "vht") == 0) { vht = 1; ht40 = 1; + } else if (os_strcmp(token, "he") == 0) { + he = 1; } else if (os_strcmp(token, "persistent") == 0) { persistent = 1; } else { @@ -5792,6 +6418,26 @@ static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd) } } +#ifdef CONFIG_ACS + if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_ACS_OFFLOAD) && + (acs || freq == 2 || freq == 5)) { + if (freq == 2 && wpa_s->best_24_freq <= 0) { + wpa_s->p2p_go_acs_band = HOSTAPD_MODE_IEEE80211G; + wpa_s->p2p_go_do_acs = 1; + freq = 0; + } else if (freq == 5 && wpa_s->best_5_freq <= 0) { + wpa_s->p2p_go_acs_band = HOSTAPD_MODE_IEEE80211A; + wpa_s->p2p_go_do_acs = 1; + freq = 0; + } else { + wpa_s->p2p_go_acs_band = HOSTAPD_MODE_IEEE80211ANY; + wpa_s->p2p_go_do_acs = 1; + } + } else { + wpa_s->p2p_go_do_acs = 0; + } +#endif /* CONFIG_ACS */ + max_oper_chwidth = parse_freq(chwidth, freq2); if (max_oper_chwidth < 0) return -1; @@ -5799,10 +6445,10 @@ static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd) if (group_id >= 0) return p2p_ctrl_group_add_persistent(wpa_s, group_id, freq, freq2, ht40, vht, - max_oper_chwidth); + max_oper_chwidth, he); return wpas_p2p_group_add(wpa_s, persistent, freq, freq2, ht40, vht, - max_oper_chwidth); + max_oper_chwidth, he); } @@ -5829,10 +6475,24 @@ static int p2p_ctrl_group_member(struct wpa_supplicant *wpa_s, const char *cmd, } +static int wpas_find_p2p_dev_addr_bss(struct wpa_global *global, + const u8 *p2p_dev_addr) +{ + struct wpa_supplicant *wpa_s; + + for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) { + if (wpa_bss_get_p2p_dev_addr(wpa_s, p2p_dev_addr)) + return 1; + } + + return 0; +} + + static int p2p_ctrl_peer(struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen) { - u8 addr[ETH_ALEN], *addr_ptr; + u8 addr[ETH_ALEN], *addr_ptr, group_capab; int next, res; const struct p2p_peer_info *info; char *pos, *end; @@ -5861,6 +6521,16 @@ static int p2p_ctrl_peer(struct wpa_supplicant *wpa_s, char *cmd, info = p2p_get_peer_info(wpa_s->global->p2p, addr_ptr, next); if (info == NULL) return -1; + group_capab = info->group_capab; + + if (group_capab && + !wpas_find_p2p_dev_addr_bss(wpa_s->global, info->p2p_device_addr)) { + wpa_printf(MSG_DEBUG, + "P2P: Could not find any BSS with p2p_dev_addr " + MACSTR ", hence override group_capab from 0x%x to 0", + MAC2STR(info->p2p_device_addr), group_capab); + group_capab = 0; + } pos = buf; end = buf + buflen; @@ -5886,7 +6556,7 @@ static int p2p_ctrl_peer(struct wpa_supplicant *wpa_s, char *cmd, info->serial_number, info->config_methods, info->dev_capab, - info->group_capab, + group_capab, info->level); if (os_snprintf_error(end - pos, res)) return pos - buf; @@ -6167,6 +6837,20 @@ static int p2p_ctrl_set(struct wpa_supplicant *wpa_s, char *cmd) return 0; } + if (os_strcmp(cmd, "override_pref_op_chan") == 0) { + int op_class, chan; + + op_class = atoi(param); + param = os_strchr(param, ':'); + if (!param) + return -1; + param++; + chan = atoi(param); + p2p_set_override_pref_op_chan(wpa_s->global->p2p, op_class, + chan); + return 0; + } + wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown P2P_SET field value '%s'", cmd); @@ -6178,6 +6862,12 @@ static void p2p_ctrl_flush(struct wpa_supplicant *wpa_s) { os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN); wpa_s->force_long_sd = 0; + +#ifdef CONFIG_TESTING_OPTIONS + os_free(wpa_s->get_pref_freq_list_override); + wpa_s->get_pref_freq_list_override = NULL; +#endif /* CONFIG_TESTING_OPTIONS */ + wpas_p2p_stop_find(wpa_s); wpa_s->parent->p2ps_method_config_any = 0; if (wpa_s->global->p2p) @@ -6385,7 +7075,7 @@ static int get_anqp(struct wpa_supplicant *wpa_s, char *dst) u16 id[MAX_ANQP_INFO_ID]; size_t num_id = 0; u32 subtypes = 0; - int get_cell_pref = 0; + u32 mbo_subtypes = 0; used = hwaddr_aton2(dst, dst_addr); if (used < 0) @@ -6406,9 +7096,10 @@ static int get_anqp(struct wpa_supplicant *wpa_s, char *dst) } else if (os_strncmp(pos, "mbo:", 4) == 0) { #ifdef CONFIG_MBO int num = atoi(pos + 4); - if (num != MBO_ANQP_SUBTYPE_CELL_CONN_PREF) + + if (num <= 0 || num > MAX_MBO_ANQP_SUBTYPE) return -1; - get_cell_pref = 1; + mbo_subtypes |= BIT(num); #else /* CONFIG_MBO */ return -1; #endif /* CONFIG_MBO */ @@ -6423,11 +7114,11 @@ static int get_anqp(struct wpa_supplicant *wpa_s, char *dst) pos++; } - if (num_id == 0) + if (num_id == 0 && !subtypes && !mbo_subtypes) return -1; return anqp_send_req(wpa_s, dst_addr, id, num_id, subtypes, - get_cell_pref); + mbo_subtypes); } @@ -6764,6 +7455,9 @@ static int wpa_supplicant_ctrl_iface_autoscan(struct wpa_supplicant *wpa_s, autoscan_init(wpa_s, 1); else if (state == WPA_SCANNING) wpa_supplicant_reinit_autoscan(wpa_s); + else + wpa_printf(MSG_DEBUG, "No autoscan update in state %s", + wpa_supplicant_state_txt(state)); return 0; } @@ -6826,26 +7520,41 @@ static int wpas_ctrl_iface_wnm_sleep(struct wpa_supplicant *wpa_s, char *cmd) static int wpas_ctrl_iface_wnm_bss_query(struct wpa_supplicant *wpa_s, char *cmd) { int query_reason, list = 0; + char *btm_candidates = NULL; query_reason = atoi(cmd); cmd = os_strchr(cmd, ' '); if (cmd) { - cmd++; - if (os_strncmp(cmd, "list", 4) == 0) { + if (os_strncmp(cmd, " list", 5) == 0) list = 1; - } else { - wpa_printf(MSG_DEBUG, "WNM Query: Invalid option %s", - cmd); - return -1; - } + else + btm_candidates = cmd; } wpa_printf(MSG_DEBUG, "CTRL_IFACE: WNM_BSS_QUERY query_reason=%d%s", query_reason, list ? " candidate list" : ""); - return wnm_send_bss_transition_mgmt_query(wpa_s, query_reason, list); + return wnm_send_bss_transition_mgmt_query(wpa_s, query_reason, + btm_candidates, + list); +} + + +static int wpas_ctrl_iface_coloc_intf_report(struct wpa_supplicant *wpa_s, + char *cmd) +{ + struct wpabuf *elems; + int ret; + + elems = wpabuf_parse_bin(cmd); + if (!elems) + return -1; + + ret = wnm_send_coloc_intf_report(wpa_s, 0, elems); + wpabuf_free(elems); + return ret; } #endif /* CONFIG_WNM */ @@ -6881,10 +7590,17 @@ static int wpa_supplicant_signal_poll(struct wpa_supplicant *wpa_s, char *buf, pos += ret; } - if (si.center_frq1 > 0 && si.center_frq2 > 0) { - ret = os_snprintf(pos, end - pos, - "CENTER_FRQ1=%d\nCENTER_FRQ2=%d\n", - si.center_frq1, si.center_frq2); + if (si.center_frq1 > 0) { + ret = os_snprintf(pos, end - pos, "CENTER_FRQ1=%d\n", + si.center_frq1); + if (os_snprintf_error(end - pos, ret)) + return -1; + pos += ret; + } + + if (si.center_frq2 > 0) { + ret = os_snprintf(pos, end - pos, "CENTER_FRQ2=%d\n", + si.center_frq2); if (os_snprintf_error(end - pos, ret)) return -1; pos += ret; @@ -6932,6 +7648,46 @@ static int wpas_ctrl_iface_signal_monitor(struct wpa_supplicant *wpa_s, } +#ifdef CONFIG_TESTING_OPTIONS +int wpas_ctrl_iface_get_pref_freq_list_override(struct wpa_supplicant *wpa_s, + enum wpa_driver_if_type if_type, + unsigned int *num, + unsigned int *freq_list) +{ + char *pos = wpa_s->get_pref_freq_list_override; + char *end; + unsigned int count = 0; + + /* Override string format: + * <if_type1>:<freq1>,<freq2>,... <if_type2>:... */ + + while (pos) { + if (atoi(pos) == (int) if_type) + break; + pos = os_strchr(pos, ' '); + if (pos) + pos++; + } + if (!pos) + return -1; + pos = os_strchr(pos, ':'); + if (!pos) + return -1; + pos++; + end = os_strchr(pos, ' '); + while (pos && (!end || pos < end) && count < *num) { + freq_list[count++] = atoi(pos); + pos = os_strchr(pos, ','); + if (pos) + pos++; + } + + *num = count; + return 0; +} +#endif /* CONFIG_TESTING_OPTIONS */ + + static int wpas_ctrl_iface_get_pref_freq_list( struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen) { @@ -6961,7 +7717,7 @@ static int wpas_ctrl_iface_get_pref_freq_list( wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_PREF_FREQ_LIST iface_type=%d (%s)", - iface_type, buf); + iface_type, cmd); ret = wpa_drv_get_pref_freq_list(wpa_s, iface_type, &num, freq_list); if (ret) @@ -7118,7 +7874,8 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s) wpa_dbg(wpa_s, MSG_DEBUG, "Flush all wpa_supplicant state"); - wpas_abort_ongoing_scan(wpa_s); + if (wpas_abort_ongoing_scan(wpa_s) == 0) + wpa_s->ignore_post_flush_scan_res = 1; if (wpa_s->wpa_state >= WPA_AUTHENTICATING) { /* @@ -7159,6 +7916,22 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s) wpa_s->after_wps = 0; wpa_s->known_wps_freq = 0; +#ifdef CONFIG_DPP + wpas_dpp_deinit(wpa_s); + wpa_s->dpp_init_max_tries = 0; + wpa_s->dpp_init_retry_time = 0; + wpa_s->dpp_resp_wait_time = 0; + wpa_s->dpp_resp_max_tries = 0; + wpa_s->dpp_resp_retry_time = 0; +#ifdef CONFIG_TESTING_OPTIONS + os_memset(dpp_pkex_own_mac_override, 0, ETH_ALEN); + os_memset(dpp_pkex_peer_mac_override, 0, ETH_ALEN); + dpp_pkex_ephemeral_key_override_len = 0; + dpp_protocol_key_override_len = 0; + dpp_nonce_override_len = 0; +#endif /* CONFIG_TESTING_OPTIONS */ +#endif /* CONFIG_DPP */ + #ifdef CONFIG_TDLS #ifdef CONFIG_TDLS_TESTING tdls_testing = 0; @@ -7220,13 +7993,29 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s) wpa_s->p2p_go_csa_on_inv = 0; wpa_s->ignore_auth_resp = 0; wpa_s->ignore_assoc_disallow = 0; + wpa_s->testing_resend_assoc = 0; wpa_s->reject_btm_req_reason = 0; wpa_sm_set_test_assoc_ie(wpa_s->wpa, NULL); + os_free(wpa_s->get_pref_freq_list_override); + wpa_s->get_pref_freq_list_override = NULL; + wpabuf_free(wpa_s->sae_commit_override); + wpa_s->sae_commit_override = NULL; +#ifdef CONFIG_DPP + os_free(wpa_s->dpp_config_obj_override); + wpa_s->dpp_config_obj_override = NULL; + os_free(wpa_s->dpp_discovery_override); + wpa_s->dpp_discovery_override = NULL; + os_free(wpa_s->dpp_groups_override); + wpa_s->dpp_groups_override = NULL; + dpp_test = DPP_TEST_DISABLED; +#endif /* CONFIG_DPP */ #endif /* CONFIG_TESTING_OPTIONS */ wpa_s->disconnected = 0; os_free(wpa_s->next_scan_freqs); wpa_s->next_scan_freqs = NULL; + os_free(wpa_s->select_network_scan_freqs); + wpa_s->select_network_scan_freqs = NULL; wpa_bss_flush(wpa_s); if (!dl_list_empty(&wpa_s->bss)) { @@ -7244,6 +8033,13 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s) #ifdef CONFIG_SME wpa_s->sme.last_unprot_disconnect.sec = 0; #endif /* CONFIG_SME */ + + wpabuf_free(wpa_s->ric_ies); + wpa_s->ric_ies = NULL; + + wpa_supplicant_update_channel_list(wpa_s, NULL); + + free_bss_tmp_disallowed(wpa_s); } @@ -7541,6 +8337,19 @@ static void wpas_ctrl_scan(struct wpa_supplicant *wpa_s, char *params, goto done; } + pos = os_strstr(params, "bssid="); + if (pos) { + u8 bssid[ETH_ALEN]; + + pos += 6; + if (hwaddr_aton(pos, bssid)) { + wpa_printf(MSG_ERROR, "Invalid BSSID %s", pos); + *reply_len = -1; + goto done; + } + os_memcpy(wpa_s->next_scan_bssid, bssid, ETH_ALEN); + } + pos = params; while (pos && *pos != '\0') { if (os_strncmp(pos, "ssid ", 5) == 0) { @@ -7826,6 +8635,124 @@ static int wpas_ctrl_iface_mgmt_rx_process(struct wpa_supplicant *wpa_s, } +static int wpas_ctrl_iface_driver_scan_res(struct wpa_supplicant *wpa_s, + char *param) +{ + struct wpa_scan_res *res; + struct os_reltime now; + char *pos, *end; + int ret = -1; + + if (!param) + return -1; + + if (os_strcmp(param, "START") == 0) { + wpa_bss_update_start(wpa_s); + return 0; + } + + if (os_strcmp(param, "END") == 0) { + wpa_bss_update_end(wpa_s, NULL, 1); + return 0; + } + + if (os_strncmp(param, "BSS ", 4) != 0) + return -1; + param += 3; + + res = os_zalloc(sizeof(*res) + os_strlen(param) / 2); + if (!res) + return -1; + + pos = os_strstr(param, " flags="); + if (pos) + res->flags = strtol(pos + 7, NULL, 16); + + pos = os_strstr(param, " bssid="); + if (pos && hwaddr_aton(pos + 7, res->bssid)) + goto fail; + + pos = os_strstr(param, " freq="); + if (pos) + res->freq = atoi(pos + 6); + + pos = os_strstr(param, " beacon_int="); + if (pos) + res->beacon_int = atoi(pos + 12); + + pos = os_strstr(param, " caps="); + if (pos) + res->caps = strtol(pos + 6, NULL, 16); + + pos = os_strstr(param, " qual="); + if (pos) + res->qual = atoi(pos + 6); + + pos = os_strstr(param, " noise="); + if (pos) + res->noise = atoi(pos + 7); + + pos = os_strstr(param, " level="); + if (pos) + res->level = atoi(pos + 7); + + pos = os_strstr(param, " tsf="); + if (pos) + res->tsf = strtoll(pos + 5, NULL, 16); + + pos = os_strstr(param, " age="); + if (pos) + res->age = atoi(pos + 5); + + pos = os_strstr(param, " est_throughput="); + if (pos) + res->est_throughput = atoi(pos + 16); + + pos = os_strstr(param, " snr="); + if (pos) + res->snr = atoi(pos + 5); + + pos = os_strstr(param, " parent_tsf="); + if (pos) + res->parent_tsf = strtoll(pos + 7, NULL, 16); + + pos = os_strstr(param, " tsf_bssid="); + if (pos && hwaddr_aton(pos + 11, res->tsf_bssid)) + goto fail; + + pos = os_strstr(param, " ie="); + if (pos) { + pos += 4; + end = os_strchr(pos, ' '); + if (!end) + end = pos + os_strlen(pos); + res->ie_len = (end - pos) / 2; + if (hexstr2bin(pos, (u8 *) (res + 1), res->ie_len)) + goto fail; + } + + pos = os_strstr(param, " beacon_ie="); + if (pos) { + pos += 11; + end = os_strchr(pos, ' '); + if (!end) + end = pos + os_strlen(pos); + res->beacon_ie_len = (end - pos) / 2; + if (hexstr2bin(pos, ((u8 *) (res + 1)) + res->ie_len, + res->beacon_ie_len)) + goto fail; + } + + os_get_reltime(&now); + wpa_bss_update_scan_res(wpa_s, res, &now); + ret = 0; +fail: + os_free(res); + + return ret; +} + + static int wpas_ctrl_iface_driver_event(struct wpa_supplicant *wpa_s, char *cmd) { char *pos, *param; @@ -7856,6 +8783,8 @@ static int wpas_ctrl_iface_driver_event(struct wpa_supplicant *wpa_s, char *cmd) wpa_supplicant_event(wpa_s, ev, &event); os_free(event.freq_range.range); return 0; + } else if (os_strcmp(cmd, "SCAN_RES") == 0) { + return wpas_ctrl_iface_driver_scan_res(wpa_s, param); } else { wpa_dbg(wpa_s, MSG_DEBUG, "Testing - unknown driver event: %s", cmd); @@ -7933,26 +8862,39 @@ static void wpas_data_test_rx(void *ctx, const u8 *src_addr, const u8 *buf, struct iphdr ip; const u8 *pos; unsigned int i; + char extra[30]; - if (len != HWSIM_PACKETLEN) + if (len < sizeof(*eth) + sizeof(ip) || len > HWSIM_PACKETLEN) { + wpa_printf(MSG_DEBUG, + "test data: RX - ignore unexpected length %d", + (int) len); return; + } eth = (const struct ether_header *) buf; os_memcpy(&ip, eth + 1, sizeof(ip)); pos = &buf[sizeof(*eth) + sizeof(ip)]; if (ip.ihl != 5 || ip.version != 4 || - ntohs(ip.tot_len) != HWSIM_IP_LEN) + ntohs(ip.tot_len) > HWSIM_IP_LEN) { + wpa_printf(MSG_DEBUG, + "test data: RX - ignore unexpect IP header"); return; + } - for (i = 0; i < HWSIM_IP_LEN - sizeof(ip); i++) { - if (*pos != (u8) i) + for (i = 0; i < ntohs(ip.tot_len) - sizeof(ip); i++) { + if (*pos != (u8) i) { + wpa_printf(MSG_DEBUG, + "test data: RX - ignore mismatching payload"); return; + } pos++; } - - wpa_msg(wpa_s, MSG_INFO, "DATA-TEST-RX " MACSTR " " MACSTR, - MAC2STR(eth->ether_dhost), MAC2STR(eth->ether_shost)); + extra[0] = '\0'; + if (ntohs(ip.tot_len) != HWSIM_IP_LEN) + os_snprintf(extra, sizeof(extra), " len=%d", ntohs(ip.tot_len)); + wpa_msg(wpa_s, MSG_INFO, "DATA-TEST-RX " MACSTR " " MACSTR "%s", + MAC2STR(eth->ether_dhost), MAC2STR(eth->ether_shost), extra); } @@ -7996,7 +8938,7 @@ static int wpas_ctrl_iface_data_test_config(struct wpa_supplicant *wpa_s, static int wpas_ctrl_iface_data_test_tx(struct wpa_supplicant *wpa_s, char *cmd) { u8 dst[ETH_ALEN], src[ETH_ALEN]; - char *pos; + char *pos, *pos2; int used; long int val; u8 tos; @@ -8005,11 +8947,12 @@ static int wpas_ctrl_iface_data_test_tx(struct wpa_supplicant *wpa_s, char *cmd) struct iphdr *ip; u8 *dpos; unsigned int i; + size_t send_len = HWSIM_IP_LEN; if (wpa_s->l2_test == NULL) return -1; - /* format: <dst> <src> <tos> */ + /* format: <dst> <src> <tos> [len=<length>] */ pos = cmd; used = hwaddr_aton2(pos, dst); @@ -8023,11 +8966,19 @@ static int wpas_ctrl_iface_data_test_tx(struct wpa_supplicant *wpa_s, char *cmd) return -1; pos += used; - val = strtol(pos, NULL, 0); + val = strtol(pos, &pos2, 0); if (val < 0 || val > 0xff) return -1; tos = val; + pos = os_strstr(pos2, " len="); + if (pos) { + i = atoi(pos + 5); + if (i < sizeof(*ip) || i > HWSIM_IP_LEN) + return -1; + send_len = i; + } + eth = (struct ether_header *) &buf[2]; os_memcpy(eth->ether_dhost, dst, ETH_ALEN); os_memcpy(eth->ether_shost, src, ETH_ALEN); @@ -8038,17 +8989,17 @@ static int wpas_ctrl_iface_data_test_tx(struct wpa_supplicant *wpa_s, char *cmd) ip->version = 4; ip->ttl = 64; ip->tos = tos; - ip->tot_len = htons(HWSIM_IP_LEN); + ip->tot_len = htons(send_len); ip->protocol = 1; ip->saddr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 1); ip->daddr = htonl(192U << 24 | 168 << 16 | 1 << 8 | 2); ip->check = ipv4_hdr_checksum(ip, sizeof(*ip)); dpos = (u8 *) (ip + 1); - for (i = 0; i < HWSIM_IP_LEN - sizeof(*ip); i++) + for (i = 0; i < send_len - sizeof(*ip); i++) *dpos++ = i; if (l2_packet_send(wpa_s->l2_test, dst, ETHERTYPE_IP, &buf[2], - HWSIM_PACKETLEN) < 0) + sizeof(struct ether_header) + send_len) < 0) return -1; wpa_dbg(wpa_s, MSG_DEBUG, "test data: TX dst=" MACSTR " src=" MACSTR @@ -8220,6 +9171,79 @@ static int wpas_ctrl_test_assoc_ie(struct wpa_supplicant *wpa_s, return 0; } + +static int wpas_ctrl_reset_pn(struct wpa_supplicant *wpa_s) +{ + u8 zero[WPA_TK_MAX_LEN]; + + if (wpa_s->last_tk_alg == WPA_ALG_NONE) + return -1; + + wpa_printf(MSG_INFO, "TESTING: Reset PN"); + os_memset(zero, 0, sizeof(zero)); + + /* 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) < 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); +} + + +static int wpas_ctrl_key_request(struct wpa_supplicant *wpa_s, const char *cmd) +{ + const char *pos = cmd; + int error, pairwise; + + error = atoi(pos); + pos = os_strchr(pos, ' '); + if (!pos) + return -1; + pairwise = atoi(pos); + wpa_sm_key_request(wpa_s->wpa, error, pairwise); + return 0; +} + + +static int wpas_ctrl_resend_assoc(struct wpa_supplicant *wpa_s) +{ +#ifdef CONFIG_SME + struct wpa_driver_associate_params params; + int ret; + + os_memset(¶ms, 0, sizeof(params)); + params.bssid = wpa_s->bssid; + params.ssid = wpa_s->sme.ssid; + params.ssid_len = wpa_s->sme.ssid_len; + params.freq.freq = wpa_s->sme.freq; + if (wpa_s->last_assoc_req_wpa_ie) { + params.wpa_ie = wpabuf_head(wpa_s->last_assoc_req_wpa_ie); + params.wpa_ie_len = wpabuf_len(wpa_s->last_assoc_req_wpa_ie); + } + params.pairwise_suite = wpa_s->pairwise_cipher; + params.group_suite = wpa_s->group_cipher; + params.mgmt_group_suite = wpa_s->mgmt_group_cipher; + params.key_mgmt_suite = wpa_s->key_mgmt; + params.wpa_proto = wpa_s->wpa_proto; + params.mgmt_frame_protection = wpa_s->sme.mfp; + params.rrm_used = wpa_s->rrm.rrm_used; + if (wpa_s->sme.prev_bssid_set) + params.prev_bssid = wpa_s->sme.prev_bssid; + wpa_printf(MSG_INFO, "TESTING: Resend association request"); + ret = wpa_drv_associate(wpa_s, ¶ms); + wpa_s->testing_resend_assoc = 1; + return ret; +#else /* CONFIG_SME */ + return -1; +#endif /* CONFIG_SME */ +} + #endif /* CONFIG_TESTING_OPTIONS */ @@ -8555,13 +9579,6 @@ static int wpas_ctrl_iface_mac_rand_scan(struct wpa_supplicant *wpa_s, return -1; } - if ((wpa_s->mac_addr_rand_supported & type) != type) { - wpa_printf(MSG_INFO, - "CTRL: MAC_RAND_SCAN types=%u != supported=%u", - type, wpa_s->mac_addr_rand_supported); - return -1; - } - if (enable > 1) { wpa_printf(MSG_INFO, "CTRL: MAC_RAND_SCAN enable=<0/1> not specified"); @@ -8595,21 +9612,25 @@ static int wpas_ctrl_iface_mac_rand_scan(struct wpa_supplicant *wpa_s, } if (type & MAC_ADDR_RAND_SCAN) { - wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCAN, - addr, mask); + if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCAN, + addr, mask)) + return -1; } if (type & MAC_ADDR_RAND_SCHED_SCAN) { - wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCHED_SCAN, - addr, mask); + if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_SCHED_SCAN, + addr, mask)) + return -1; if (wpa_s->sched_scanning && !wpa_s->pno) wpas_scan_restart_sched_scan(wpa_s); } if (type & MAC_ADDR_RAND_PNO) { - wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_PNO, - addr, mask); + if (wpas_mac_addr_rand_scan_set(wpa_s, MAC_ADDR_RAND_PNO, + addr, mask)) + return -1; + if (wpa_s->pno) { wpas_stop_pno(wpa_s); wpas_start_pno(wpa_s); @@ -8643,6 +9664,248 @@ static void wpas_ctrl_iface_pmksa_flush(struct wpa_supplicant *wpa_s) } +#ifdef CONFIG_PMKSA_CACHE_EXTERNAL + +static int wpas_ctrl_iface_pmksa_get(struct wpa_supplicant *wpa_s, + const char *cmd, char *buf, size_t buflen) +{ + struct rsn_pmksa_cache_entry *entry; + struct wpa_ssid *ssid; + char *pos, *pos2, *end; + int ret; + struct os_reltime now; + + ssid = wpa_config_get_network(wpa_s->conf, atoi(cmd)); + if (!ssid) + return -1; + + pos = buf; + end = buf + buflen; + + os_get_reltime(&now); + + /* + * Entry format: + * <BSSID> <PMKID> <PMK> <reauth_time in seconds> + * <expiration in seconds> <akmp> <opportunistic> + * [FILS Cache Identifier] + */ + + for (entry = wpa_sm_pmksa_cache_head(wpa_s->wpa); entry; + entry = entry->next) { + if (entry->network_ctx != ssid) + continue; + + pos2 = pos; + ret = os_snprintf(pos2, end - pos2, MACSTR " ", + MAC2STR(entry->aa)); + if (os_snprintf_error(end - pos2, ret)) + break; + pos2 += ret; + + pos2 += wpa_snprintf_hex(pos2, end - pos2, entry->pmkid, + PMKID_LEN); + + ret = os_snprintf(pos2, end - pos2, " "); + if (os_snprintf_error(end - pos2, ret)) + break; + pos2 += ret; + + pos2 += wpa_snprintf_hex(pos2, end - pos2, entry->pmk, + entry->pmk_len); + + ret = os_snprintf(pos2, end - pos2, " %d %d %d %d", + (int) (entry->reauth_time - now.sec), + (int) (entry->expiration - now.sec), + entry->akmp, + entry->opportunistic); + if (os_snprintf_error(end - pos2, ret)) + break; + pos2 += ret; + + if (entry->fils_cache_id_set) { + ret = os_snprintf(pos2, end - pos2, " %02x%02x", + entry->fils_cache_id[0], + entry->fils_cache_id[1]); + if (os_snprintf_error(end - pos2, ret)) + break; + pos2 += ret; + } + + ret = os_snprintf(pos2, end - pos2, "\n"); + if (os_snprintf_error(end - pos2, ret)) + break; + pos2 += ret; + + pos = pos2; + } + + return pos - buf; +} + + +static int wpas_ctrl_iface_pmksa_add(struct wpa_supplicant *wpa_s, + char *cmd) +{ + struct rsn_pmksa_cache_entry *entry; + struct wpa_ssid *ssid; + char *pos, *pos2; + int ret = -1; + struct os_reltime now; + int reauth_time = 0, expiration = 0, i; + + /* + * Entry format: + * <network_id> <BSSID> <PMKID> <PMK> <reauth_time in seconds> + * <expiration in seconds> <akmp> <opportunistic> + * [FILS Cache Identifier] + */ + + ssid = wpa_config_get_network(wpa_s->conf, atoi(cmd)); + if (!ssid) + return -1; + + pos = os_strchr(cmd, ' '); + if (!pos) + return -1; + pos++; + + entry = os_zalloc(sizeof(*entry)); + if (!entry) + return -1; + + if (hwaddr_aton(pos, entry->aa)) + goto fail; + + pos = os_strchr(pos, ' '); + if (!pos) + goto fail; + pos++; + + if (hexstr2bin(pos, entry->pmkid, PMKID_LEN) < 0) + goto fail; + + pos = os_strchr(pos, ' '); + if (!pos) + goto fail; + pos++; + + pos2 = os_strchr(pos, ' '); + if (!pos2) + goto fail; + entry->pmk_len = (pos2 - pos) / 2; + if (entry->pmk_len < PMK_LEN || entry->pmk_len > PMK_LEN_MAX || + hexstr2bin(pos, entry->pmk, entry->pmk_len) < 0) + goto fail; + + pos = os_strchr(pos, ' '); + if (!pos) + goto fail; + pos++; + + if (sscanf(pos, "%d %d %d %d", &reauth_time, &expiration, + &entry->akmp, &entry->opportunistic) != 4) + goto fail; + for (i = 0; i < 4; i++) { + pos = os_strchr(pos, ' '); + if (!pos) { + if (i < 3) + goto fail; + break; + } + pos++; + } + if (pos) { + if (hexstr2bin(pos, entry->fils_cache_id, + FILS_CACHE_ID_LEN) < 0) + goto fail; + entry->fils_cache_id_set = 1; + } + os_get_reltime(&now); + entry->expiration = now.sec + expiration; + entry->reauth_time = now.sec + reauth_time; + + entry->network_ctx = ssid; + + wpa_sm_pmksa_cache_add_entry(wpa_s->wpa, entry); + entry = NULL; + ret = 0; +fail: + os_free(entry); + return ret; +} + + +#ifdef CONFIG_MESH + +static int wpas_ctrl_iface_mesh_pmksa_get(struct wpa_supplicant *wpa_s, + const char *cmd, char *buf, + size_t buflen) +{ + u8 spa[ETH_ALEN]; + + if (!wpa_s->ifmsh) + return -1; + + if (os_strcasecmp(cmd, "any") == 0) + return wpas_ap_pmksa_cache_list_mesh(wpa_s, NULL, buf, buflen); + + if (hwaddr_aton(cmd, spa)) + return -1; + + return wpas_ap_pmksa_cache_list_mesh(wpa_s, spa, buf, buflen); +} + + +static int wpas_ctrl_iface_mesh_pmksa_add(struct wpa_supplicant *wpa_s, + char *cmd) +{ + /* + * We do not check mesh interface existance because PMKSA should be + * stored before wpa_s->ifmsh creation to suppress commit message + * creation. + */ + return wpas_ap_pmksa_cache_add_external(wpa_s, cmd); +} + +#endif /* CONFIG_MESH */ +#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */ + + +#ifdef CONFIG_FILS +static int wpas_ctrl_iface_fils_hlp_req_add(struct wpa_supplicant *wpa_s, + const char *cmd) +{ + struct fils_hlp_req *req; + const char *pos; + + /* format: <dst> <packet starting from ethertype> */ + + req = os_zalloc(sizeof(*req)); + if (!req) + return -1; + + if (hwaddr_aton(cmd, req->dst)) + goto fail; + + pos = os_strchr(cmd, ' '); + if (!pos) + goto fail; + pos++; + req->pkt = wpabuf_parse_bin(pos); + if (!req->pkt) + goto fail; + + dl_list_add_tail(&wpa_s->fils_hlp_req, &req->list); + return 0; +fail: + wpabuf_free(req->pkt); + os_free(req); + return -1; +} +#endif /* CONFIG_FILS */ + + static int wpas_ctrl_cmd_debug_level(const char *cmd) { if (os_strcmp(cmd, "PING") == 0 || @@ -8664,7 +9927,9 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, int reply_len; if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0 || - os_strncmp(buf, "SET_NETWORK ", 12) == 0) { + os_strncmp(buf, "SET_NETWORK ", 12) == 0 || + os_strncmp(buf, "PMKSA_ADD ", 10) == 0 || + os_strncmp(buf, "MESH_PMKSA_ADD ", 15) == 0) { if (wpa_debug_show_keys) wpa_dbg(wpa_s, MSG_DEBUG, "Control interface command '%s'", buf); @@ -8673,7 +9938,9 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, "Control interface command '%s [REMOVED]'", os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0 ? - WPA_CTRL_RSP : "SET_NETWORK"); + WPA_CTRL_RSP : + (os_strncmp(buf, "SET_NETWORK ", 12) == 0 ? + "SET_NETWORK" : "key-add")); } else if (os_strncmp(buf, "WPS_NFC_TAG_READ", 16) == 0 || os_strncmp(buf, "NFC_REPORT_HANDOVER", 19) == 0) { wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface", @@ -8709,6 +9976,11 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, reply_len += eapol_sm_get_mib(wpa_s->eapol, reply + reply_len, reply_size - reply_len); +#ifdef CONFIG_MACSEC + reply_len += ieee802_1x_kay_get_mib( + wpa_s->kay, reply + reply_len, + reply_size - reply_len); +#endif /* CONFIG_MACSEC */ } } else if (os_strncmp(buf, "STATUS", 6) == 0) { reply_len = wpa_supplicant_ctrl_iface_status( @@ -8717,6 +9989,22 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, reply_len = wpas_ctrl_iface_pmksa(wpa_s, reply, reply_size); } else if (os_strcmp(buf, "PMKSA_FLUSH") == 0) { wpas_ctrl_iface_pmksa_flush(wpa_s); +#ifdef CONFIG_PMKSA_CACHE_EXTERNAL + } else if (os_strncmp(buf, "PMKSA_GET ", 10) == 0) { + reply_len = wpas_ctrl_iface_pmksa_get(wpa_s, buf + 10, + reply, reply_size); + } else if (os_strncmp(buf, "PMKSA_ADD ", 10) == 0) { + if (wpas_ctrl_iface_pmksa_add(wpa_s, buf + 10) < 0) + reply_len = -1; +#ifdef CONFIG_MESH + } else if (os_strncmp(buf, "MESH_PMKSA_GET ", 15) == 0) { + reply_len = wpas_ctrl_iface_mesh_pmksa_get(wpa_s, buf + 15, + reply, reply_size); + } else if (os_strncmp(buf, "MESH_PMKSA_ADD ", 15) == 0) { + if (wpas_ctrl_iface_mesh_pmksa_add(wpa_s, buf + 15) < 0) + reply_len = -1; +#endif /* CONFIG_MESH */ +#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */ } else if (os_strncmp(buf, "SET ", 4) == 0) { if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4)) reply_len = -1; @@ -8753,11 +10041,6 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8)) reply_len = -1; #endif /* IEEE8021X_EAPOL */ -#ifdef CONFIG_PEERKEY - } else if (os_strncmp(buf, "STKSTART ", 9) == 0) { - if (wpa_supplicant_ctrl_iface_stkstart(wpa_s, buf + 9)) - reply_len = -1; -#endif /* CONFIG_PEERKEY */ #ifdef CONFIG_IEEE80211R } else if (os_strncmp(buf, "FT_DS ", 6) == 0) { if (wpa_supplicant_ctrl_iface_ft_ds(wpa_s, buf + 6)) @@ -9288,6 +10571,9 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, } else if (os_strncmp(buf, "WNM_BSS_QUERY ", 14) == 0) { if (wpas_ctrl_iface_wnm_bss_query(wpa_s, buf + 14)) reply_len = -1; + } else if (os_strncmp(buf, "COLOC_INTF_REPORT ", 18) == 0) { + if (wpas_ctrl_iface_coloc_intf_report(wpa_s, buf + 18)) + reply_len = -1; #endif /* CONFIG_WNM */ } else if (os_strcmp(buf, "FLUSH") == 0) { wpa_supplicant_ctrl_iface_flush(wpa_s); @@ -9334,6 +10620,21 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, } else if (os_strncmp(buf, "TEST_ASSOC_IE ", 14) == 0) { if (wpas_ctrl_test_assoc_ie(wpa_s, buf + 14) < 0) reply_len = -1; + } else if (os_strcmp(buf, "RESET_PN") == 0) { + if (wpas_ctrl_reset_pn(wpa_s) < 0) + reply_len = -1; + } else if (os_strncmp(buf, "KEY_REQUEST ", 12) == 0) { + if (wpas_ctrl_key_request(wpa_s, buf + 12) < 0) + reply_len = -1; + } else if (os_strcmp(buf, "RESEND_ASSOC") == 0) { + if (wpas_ctrl_resend_assoc(wpa_s) < 0) + reply_len = -1; +#ifdef CONFIG_IEEE80211W + } else if (os_strcmp(buf, "UNPROT_DEAUTH") == 0) { + sme_event_unprot_disconnect( + wpa_s, wpa_s->bssid, NULL, + WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA); +#endif /* CONFIG_IEEE80211W */ #endif /* CONFIG_TESTING_OPTIONS */ } else if (os_strncmp(buf, "VENDOR_ELEM_ADD ", 16) == 0) { if (wpas_ctrl_vendor_elem_add(wpa_s, buf + 16) < 0) @@ -9355,6 +10656,98 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, } else if (os_strncmp(buf, "GET_PREF_FREQ_LIST ", 19) == 0) { reply_len = wpas_ctrl_iface_get_pref_freq_list( wpa_s, buf + 19, reply, reply_size); +#ifdef CONFIG_FILS + } else if (os_strncmp(buf, "FILS_HLP_REQ_ADD ", 17) == 0) { + if (wpas_ctrl_iface_fils_hlp_req_add(wpa_s, buf + 17)) + reply_len = -1; + } else if (os_strcmp(buf, "FILS_HLP_REQ_FLUSH") == 0) { + wpas_flush_fils_hlp_req(wpa_s); +#endif /* CONFIG_FILS */ +#ifdef CONFIG_DPP + } else if (os_strncmp(buf, "DPP_QR_CODE ", 12) == 0) { + int res; + + res = wpas_dpp_qr_code(wpa_s, buf + 12); + if (res < 0) { + reply_len = -1; + } else { + reply_len = os_snprintf(reply, reply_size, "%d", res); + if (os_snprintf_error(reply_size, reply_len)) + reply_len = -1; + } + } else if (os_strncmp(buf, "DPP_BOOTSTRAP_GEN ", 18) == 0) { + int res; + + res = dpp_bootstrap_gen(wpa_s->dpp, buf + 18); + if (res < 0) { + reply_len = -1; + } else { + reply_len = os_snprintf(reply, reply_size, "%d", res); + if (os_snprintf_error(reply_size, reply_len)) + reply_len = -1; + } + } else if (os_strncmp(buf, "DPP_BOOTSTRAP_REMOVE ", 21) == 0) { + if (dpp_bootstrap_remove(wpa_s->dpp, buf + 21) < 0) + reply_len = -1; + } else if (os_strncmp(buf, "DPP_BOOTSTRAP_GET_URI ", 22) == 0) { + const char *uri; + + uri = dpp_bootstrap_get_uri(wpa_s->dpp, atoi(buf + 22)); + if (!uri) { + reply_len = -1; + } else { + reply_len = os_snprintf(reply, reply_size, "%s", uri); + if (os_snprintf_error(reply_size, reply_len)) + reply_len = -1; + } + } else if (os_strncmp(buf, "DPP_BOOTSTRAP_INFO ", 19) == 0) { + reply_len = dpp_bootstrap_info(wpa_s->dpp, atoi(buf + 19), + reply, reply_size); + } else if (os_strncmp(buf, "DPP_AUTH_INIT ", 14) == 0) { + if (wpas_dpp_auth_init(wpa_s, buf + 13) < 0) + reply_len = -1; + } else if (os_strncmp(buf, "DPP_LISTEN ", 11) == 0) { + if (wpas_dpp_listen(wpa_s, buf + 11) < 0) + reply_len = -1; + } else if (os_strcmp(buf, "DPP_STOP_LISTEN") == 0) { + wpas_dpp_stop(wpa_s); + wpas_dpp_listen_stop(wpa_s); + } else if (os_strncmp(buf, "DPP_CONFIGURATOR_ADD", 20) == 0) { + int res; + + res = dpp_configurator_add(wpa_s->dpp, buf + 20); + if (res < 0) { + reply_len = -1; + } else { + reply_len = os_snprintf(reply, reply_size, "%d", res); + if (os_snprintf_error(reply_size, reply_len)) + reply_len = -1; + } + } else if (os_strncmp(buf, "DPP_CONFIGURATOR_REMOVE ", 24) == 0) { + if (dpp_configurator_remove(wpa_s->dpp, buf + 24) < 0) + reply_len = -1; + } else if (os_strncmp(buf, "DPP_CONFIGURATOR_SIGN ", 22) == 0) { + if (wpas_dpp_configurator_sign(wpa_s, buf + 21) < 0) + reply_len = -1; + } else if (os_strncmp(buf, "DPP_CONFIGURATOR_GET_KEY ", 25) == 0) { + reply_len = dpp_configurator_get_key_id(wpa_s->dpp, + atoi(buf + 25), + reply, reply_size); + } else if (os_strncmp(buf, "DPP_PKEX_ADD ", 13) == 0) { + int res; + + res = wpas_dpp_pkex_add(wpa_s, buf + 12); + if (res < 0) { + reply_len = -1; + } else { + reply_len = os_snprintf(reply, reply_size, "%d", res); + if (os_snprintf_error(reply_size, reply_len)) + reply_len = -1; + } + } else if (os_strncmp(buf, "DPP_PKEX_REMOVE ", 16) == 0) { + if (wpas_dpp_pkex_remove(wpa_s, buf + 16) < 0) + reply_len = -1; +#endif /* CONFIG_DPP */ } else { os_memcpy(reply, "UNKNOWN COMMAND\n", 16); reply_len = 16; @@ -9664,12 +11057,16 @@ static char * wpas_global_ctrl_iface_redir_p2p(struct wpa_global *global, "P2P_CANCEL", "P2P_PRESENCE_REQ", "P2P_EXT_LISTEN", +#ifdef CONFIG_AP + "STA-FIRST", +#endif /* CONFIG_AP */ NULL }; static const char * prefix[] = { #ifdef ANDROID "DRIVER ", #endif /* ANDROID */ + "GET_CAPABILITY ", "GET_NETWORK ", "REMOVE_NETWORK ", "P2P_FIND ", @@ -9701,6 +11098,10 @@ static char * wpas_global_ctrl_iface_redir_p2p(struct wpa_global *global, "NFC_REPORT_HANDOVER ", "P2P_ASP_PROVISION ", "P2P_ASP_PROVISION_RESP ", +#ifdef CONFIG_AP + "STA ", + "STA-NEXT ", +#endif /* CONFIG_AP */ NULL }; int found = 0; diff --git a/freebsd/contrib/wpa/wpa_supplicant/ctrl_iface_unix.c b/freebsd/contrib/wpa/wpa_supplicant/ctrl_iface_unix.c index ff1814c9..cab15263 100644 --- a/freebsd/contrib/wpa/wpa_supplicant/ctrl_iface_unix.c +++ b/freebsd/contrib/wpa/wpa_supplicant/ctrl_iface_unix.c @@ -105,7 +105,7 @@ static int wpa_supplicant_ctrl_iface_attach(struct dl_list *ctrl_dst, struct sockaddr_storage *from, socklen_t fromlen, int global) { - return ctrl_iface_attach(ctrl_dst, from, fromlen); + return ctrl_iface_attach(ctrl_dst, from, fromlen, NULL); } @@ -572,8 +572,8 @@ static int wpas_ctrl_iface_open_sock(struct wpa_supplicant *wpa_s, } } - if (gid_set && chown(dir, -1, gid) < 0) { - wpa_printf(MSG_ERROR, "chown[ctrl_interface=%s,gid=%d]: %s", + if (gid_set && lchown(dir, -1, gid) < 0) { + wpa_printf(MSG_ERROR, "lchown[ctrl_interface=%s,gid=%d]: %s", dir, (int) gid, strerror(errno)); goto fail; } @@ -640,8 +640,8 @@ static int wpas_ctrl_iface_open_sock(struct wpa_supplicant *wpa_s, } } - if (gid_set && chown(fname, -1, gid) < 0) { - wpa_printf(MSG_ERROR, "chown[ctrl_interface=%s,gid=%d]: %s", + if (gid_set && lchown(fname, -1, gid) < 0) { + wpa_printf(MSG_ERROR, "lchown[ctrl_interface=%s,gid=%d]: %s", fname, (int) gid, strerror(errno)); goto fail; } @@ -1237,9 +1237,9 @@ static int wpas_global_ctrl_iface_open_sock(struct wpa_global *global, wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d", (int) gid); } - if (chown(ctrl, -1, gid) < 0) { + if (lchown(ctrl, -1, gid) < 0) { wpa_printf(MSG_ERROR, - "chown[global_ctrl_interface=%s,gid=%d]: %s", + "lchown[global_ctrl_interface=%s,gid=%d]: %s", ctrl, (int) gid, strerror(errno)); goto fail; } diff --git a/freebsd/contrib/wpa/wpa_supplicant/dbus/dbus_new.h b/freebsd/contrib/wpa/wpa_supplicant/dbus/dbus_new.h index d64fceef..42db3892 100644 --- a/freebsd/contrib/wpa/wpa_supplicant/dbus/dbus_new.h +++ b/freebsd/contrib/wpa/wpa_supplicant/dbus/dbus_new.h @@ -28,8 +28,14 @@ enum wpas_dbus_prop { WPAS_DBUS_PROP_CURRENT_NETWORK, WPAS_DBUS_PROP_CURRENT_AUTH_MODE, WPAS_DBUS_PROP_BSSS, + WPAS_DBUS_PROP_STATIONS, WPAS_DBUS_PROP_DISCONNECT_REASON, + WPAS_DBUS_PROP_AUTH_STATUS_CODE, WPAS_DBUS_PROP_ASSOC_STATUS_CODE, + WPAS_DBUS_PROP_ROAM_TIME, + WPAS_DBUS_PROP_ROAM_COMPLETE, + WPAS_DBUS_PROP_SESSION_LENGTH, + WPAS_DBUS_PROP_BSS_TM_STATUS, }; enum wpas_dbus_bss_prop { @@ -45,6 +51,10 @@ enum wpas_dbus_bss_prop { WPAS_DBUS_BSS_PROP_AGE, }; +enum wpas_dbus_sta_prop { + WPAS_DBUS_STA_PROP_ADDRESS, +}; + #define WPAS_DBUS_OBJECT_PATH_MAX 150 #define WPAS_DBUS_NEW_SERVICE "fi.w1.wpa_supplicant1" @@ -61,9 +71,14 @@ enum wpas_dbus_bss_prop { #define WPAS_DBUS_NEW_BSSIDS_PART "BSSs" #define WPAS_DBUS_NEW_IFACE_BSS WPAS_DBUS_NEW_INTERFACE ".BSS" +#define WPAS_DBUS_NEW_STAS_PART "Stations" +#define WPAS_DBUS_NEW_IFACE_STA WPAS_DBUS_NEW_INTERFACE ".Station" + #define WPAS_DBUS_NEW_IFACE_P2PDEVICE \ WPAS_DBUS_NEW_IFACE_INTERFACE ".P2PDevice" +#define WPAS_DBUS_NEW_IFACE_MESH WPAS_DBUS_NEW_IFACE_INTERFACE ".Mesh" + /* * Groups correspond to P2P groups where this device is a GO (owner) */ @@ -161,6 +176,8 @@ int wpas_dbus_unregister_bss(struct wpa_supplicant *wpa_s, u8 bssid[ETH_ALEN], unsigned int id); int wpas_dbus_register_bss(struct wpa_supplicant *wpa_s, u8 bssid[ETH_ALEN], unsigned int id); +int wpas_dbus_unregister_sta(struct wpa_supplicant *wpa_s, const u8 *sta); +int wpas_dbus_register_sta(struct wpa_supplicant *wpa_s, const u8 *sta); void wpas_dbus_signal_blob_added(struct wpa_supplicant *wpa_s, const char *name); void wpas_dbus_signal_blob_removed(struct wpa_supplicant *wpa_s, @@ -190,7 +207,8 @@ void wpas_dbus_signal_p2p_go_neg_req(struct wpa_supplicant *wpa_s, const u8 *src, u16 dev_passwd_id, u8 go_intent); void wpas_dbus_signal_p2p_group_started(struct wpa_supplicant *wpa_s, - int client, int persistent); + int client, int persistent, + const u8 *ip); void wpas_dbus_signal_p2p_group_formation_failure(struct wpa_supplicant *wpa_s, const char *reason); void wpas_dbus_register_p2p_group(struct wpa_supplicant *wpa_s, @@ -237,6 +255,15 @@ void wpas_dbus_signal_p2p_invitation_received(struct wpa_supplicant *wpa_s, const u8 *sa, const u8 *dev_addr, const u8 *bssid, int id, int op_freq); +void wpas_dbus_signal_mesh_group_started(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid); +void wpas_dbus_signal_mesh_group_removed(struct wpa_supplicant *wpa_s, + const u8 *meshid, u8 meshid_len, + int reason); +void wpas_dbus_signal_mesh_peer_connected(struct wpa_supplicant *wpa_s, + const u8 *peer_addr); +void wpas_dbus_signal_mesh_peer_disconnected(struct wpa_supplicant *wpa_s, + const u8 *peer_addr, int reason); #else /* CONFIG_CTRL_IFACE_DBUS_NEW */ @@ -333,6 +360,18 @@ static inline int wpas_dbus_register_bss(struct wpa_supplicant *wpa_s, return 0; } +static inline int wpas_dbus_unregister_sta(struct wpa_supplicant *wpa_s, + const u8 *sta) +{ + return 0; +} + +static inline int wpas_dbus_register_sta(struct wpa_supplicant *wpa_s, + const u8 *sta) +{ + return 0; +} + static inline void wpas_dbus_signal_blob_added(struct wpa_supplicant *wpa_s, const char *name) { @@ -400,7 +439,8 @@ static inline void wpas_dbus_signal_p2p_go_neg_req(struct wpa_supplicant *wpa_s, static inline void wpas_dbus_signal_p2p_group_started(struct wpa_supplicant *wpa_s, - int client, int persistent) + int client, int persistent, + const u8 *ip) { } @@ -551,6 +591,31 @@ void wpas_dbus_signal_p2p_invitation_received(struct wpa_supplicant *wpa_s, { } +static inline +void wpas_dbus_signal_mesh_group_started(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid) +{ +} + +static inline +void wpas_dbus_signal_mesh_group_removed(struct wpa_supplicant *wpa_s, + const u8 *meshid, u8 meshid_len, + int reason) +{ +} + +static inline +void wpas_dbus_signal_mesh_peer_connected(struct wpa_supplicant *wpa_s, + const u8 *peer_addr) +{ +} + +static inline +void wpas_dbus_signal_mesh_peer_disconnected(struct wpa_supplicant *wpa_s, + const u8 *peer_addr, int reason) +{ +} + #endif /* CONFIG_CTRL_IFACE_DBUS_NEW */ #endif /* CTRL_IFACE_DBUS_H_NEW */ diff --git a/freebsd/contrib/wpa/wpa_supplicant/dbus/dbus_old.h b/freebsd/contrib/wpa/wpa_supplicant/dbus/dbus_old.h deleted file mode 100644 index 451a9f82..00000000 --- a/freebsd/contrib/wpa/wpa_supplicant/dbus/dbus_old.h +++ /dev/null @@ -1,142 +0,0 @@ -/* - * WPA Supplicant / dbus-based control interface - * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc. - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#ifndef CTRL_IFACE_DBUS_H -#define CTRL_IFACE_DBUS_H - -struct wps_credential; - -#ifdef CONFIG_CTRL_IFACE_DBUS - -#define WPAS_DBUS_OBJECT_PATH_MAX 150 - -#define WPAS_DBUS_SERVICE "fi.epitest.hostap.WPASupplicant" -#define WPAS_DBUS_PATH "/fi/epitest/hostap/WPASupplicant" -#define WPAS_DBUS_INTERFACE "fi.epitest.hostap.WPASupplicant" - -#define WPAS_DBUS_PATH_INTERFACES WPAS_DBUS_PATH "/Interfaces" -#define WPAS_DBUS_IFACE_INTERFACE WPAS_DBUS_INTERFACE ".Interface" - -#define WPAS_DBUS_NETWORKS_PART "Networks" -#define WPAS_DBUS_IFACE_NETWORK WPAS_DBUS_INTERFACE ".Network" - -#define WPAS_DBUS_BSSIDS_PART "BSSIDs" -#define WPAS_DBUS_IFACE_BSSID WPAS_DBUS_INTERFACE ".BSSID" - - -/* Errors */ -#define WPAS_ERROR_INVALID_NETWORK \ - WPAS_DBUS_IFACE_INTERFACE ".InvalidNetwork" -#define WPAS_ERROR_INVALID_BSSID \ - WPAS_DBUS_IFACE_INTERFACE ".InvalidBSSID" - -#define WPAS_ERROR_INVALID_OPTS \ - WPAS_DBUS_INTERFACE ".InvalidOptions" -#define WPAS_ERROR_INVALID_IFACE \ - WPAS_DBUS_INTERFACE ".InvalidInterface" - -#define WPAS_ERROR_ADD_ERROR \ - WPAS_DBUS_INTERFACE ".AddError" -#define WPAS_ERROR_EXISTS_ERROR \ - WPAS_DBUS_INTERFACE ".ExistsError" -#define WPAS_ERROR_REMOVE_ERROR \ - WPAS_DBUS_INTERFACE ".RemoveError" - -#define WPAS_ERROR_SCAN_ERROR \ - WPAS_DBUS_IFACE_INTERFACE ".ScanError" -#define WPAS_ERROR_ADD_NETWORK_ERROR \ - WPAS_DBUS_IFACE_INTERFACE ".AddNetworkError" -#define WPAS_ERROR_INTERNAL_ERROR \ - WPAS_DBUS_IFACE_INTERFACE ".InternalError" -#define WPAS_ERROR_REMOVE_NETWORK_ERROR \ - WPAS_DBUS_IFACE_INTERFACE ".RemoveNetworkError" - -#define WPAS_ERROR_WPS_PBC_ERROR \ - WPAS_DBUS_IFACE_INTERFACE ".WpsPbcError" -#define WPAS_ERROR_WPS_PIN_ERROR \ - WPAS_DBUS_IFACE_INTERFACE ".WpsPinError" -#define WPAS_ERROR_WPS_REG_ERROR \ - WPAS_DBUS_IFACE_INTERFACE ".WpsRegError" - -#define WPAS_DBUS_BSSID_FORMAT "%02x%02x%02x%02x%02x%02x" - -struct wpa_global; -struct wpa_supplicant; - -int wpa_supplicant_dbus_ctrl_iface_init(struct wpas_dbus_priv *iface); -void wpa_supplicant_dbus_notify_scan_results(struct wpa_supplicant *wpa_s); -void wpa_supplicant_dbus_notify_scanning(struct wpa_supplicant *wpa_s); -void wpa_supplicant_dbus_notify_state_change(struct wpa_supplicant *wpa_s, - enum wpa_states new_state, - enum wpa_states old_state); -void wpa_supplicant_dbus_notify_wps_cred(struct wpa_supplicant *wpa_s, - const struct wps_credential *cred); -void wpa_supplicant_dbus_notify_certification(struct wpa_supplicant *wpa_s, - int depth, const char *subject, - const char *cert_hash, - const struct wpabuf *cert); - -char * wpas_dbus_decompose_object_path(const char *path, char **network, - char **bssid); - -int wpas_dbus_register_iface(struct wpa_supplicant *wpa_s); -int wpas_dbus_unregister_iface(struct wpa_supplicant *wpa_s); - - -/* Methods internal to the dbus control interface */ -struct wpa_supplicant * wpa_supplicant_get_iface_by_dbus_path( - struct wpa_global *global, const char *path); - -#else /* CONFIG_CTRL_IFACE_DBUS */ - -static inline void -wpa_supplicant_dbus_notify_scan_results(struct wpa_supplicant *wpa_s) -{ -} - -static inline void -wpa_supplicant_dbus_notify_scanning(struct wpa_supplicant *wpa_s) -{ -} - -static inline void -wpa_supplicant_dbus_notify_state_change(struct wpa_supplicant *wpa_s, - enum wpa_states new_state, - enum wpa_states old_state) -{ -} - -static inline void -wpa_supplicant_dbus_notify_wps_cred(struct wpa_supplicant *wpa_s, - const struct wps_credential *cred) -{ -} - -static inline void -wpa_supplicant_dbus_notify_certification(struct wpa_supplicant *wpa_s, - int depth, const char *subject, - const char *cert_hash, - const struct wpabuf *cert) -{ -} - -static inline int -wpas_dbus_register_iface(struct wpa_supplicant *wpa_s) -{ - return 0; -} - -static inline int -wpas_dbus_unregister_iface(struct wpa_supplicant *wpa_s) -{ - return 0; -} - -#endif /* CONFIG_CTRL_IFACE_DBUS */ - -#endif /* CTRL_IFACE_DBUS_H */ diff --git a/freebsd/contrib/wpa/wpa_supplicant/dpp_supplicant.h b/freebsd/contrib/wpa/wpa_supplicant/dpp_supplicant.h new file mode 100644 index 00000000..ecb7a7d6 --- /dev/null +++ b/freebsd/contrib/wpa/wpa_supplicant/dpp_supplicant.h @@ -0,0 +1,29 @@ +/* + * wpa_supplicant - DPP + * Copyright (c) 2017, Qualcomm Atheros, Inc. + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef DPP_SUPPLICANT_H +#define DPP_SUPPLICANT_H + +int wpas_dpp_qr_code(struct wpa_supplicant *wpa_s, const char *cmd); +int wpas_dpp_auth_init(struct wpa_supplicant *wpa_s, const char *cmd); +int wpas_dpp_listen(struct wpa_supplicant *wpa_s, const char *cmd); +void wpas_dpp_listen_stop(struct wpa_supplicant *wpa_s); +void wpas_dpp_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s, + unsigned int freq); +void wpas_dpp_rx_action(struct wpa_supplicant *wpa_s, const u8 *src, + const u8 *buf, size_t len, unsigned int freq); +int wpas_dpp_configurator_sign(struct wpa_supplicant *wpa_s, const char *cmd); +int wpas_dpp_pkex_add(struct wpa_supplicant *wpa_s, const char *cmd); +int wpas_dpp_pkex_remove(struct wpa_supplicant *wpa_s, const char *id); +void wpas_dpp_stop(struct wpa_supplicant *wpa_s); +int wpas_dpp_init(struct wpa_supplicant *wpa_s); +void wpas_dpp_deinit(struct wpa_supplicant *wpa_s); +int wpas_dpp_check_connect(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, + struct wpa_bss *bss); + +#endif /* DPP_SUPPLICANT_H */ diff --git a/freebsd/contrib/wpa/wpa_supplicant/driver_i.h b/freebsd/contrib/wpa/wpa_supplicant/driver_i.h index 220b7ba3..4a9f472e 100644 --- a/freebsd/contrib/wpa/wpa_supplicant/driver_i.h +++ b/freebsd/contrib/wpa/wpa_supplicant/driver_i.h @@ -189,20 +189,19 @@ static inline int wpa_drv_deauthenticate(struct wpa_supplicant *wpa_s, } static inline int wpa_drv_add_pmkid(struct wpa_supplicant *wpa_s, - const u8 *bssid, const u8 *pmkid) + struct wpa_pmkid_params *params) { if (wpa_s->driver->add_pmkid) { - return wpa_s->driver->add_pmkid(wpa_s->drv_priv, bssid, pmkid); + return wpa_s->driver->add_pmkid(wpa_s->drv_priv, params); } return -1; } static inline int wpa_drv_remove_pmkid(struct wpa_supplicant *wpa_s, - const u8 *bssid, const u8 *pmkid) + struct wpa_pmkid_params *params) { if (wpa_s->driver->remove_pmkid) { - return wpa_s->driver->remove_pmkid(wpa_s->drv_priv, bssid, - pmkid); + return wpa_s->driver->remove_pmkid(wpa_s->drv_priv, params); } return -1; } @@ -276,11 +275,12 @@ static inline int wpa_drv_mlme_setprotection(struct wpa_supplicant *wpa_s, static inline struct hostapd_hw_modes * wpa_drv_get_hw_feature_data(struct wpa_supplicant *wpa_s, u16 *num_modes, - u16 *flags) + u16 *flags, u8 *dfs_domain) { if (wpa_s->driver->get_hw_feature_data) return wpa_s->driver->get_hw_feature_data(wpa_s->drv_priv, - num_modes, flags); + num_modes, flags, + dfs_domain); return NULL; } @@ -492,6 +492,14 @@ static inline int wpa_drv_signal_poll(struct wpa_supplicant *wpa_s, return -1; } +static inline int wpa_drv_channel_info(struct wpa_supplicant *wpa_s, + struct wpa_channel_info *ci) +{ + if (wpa_s->driver->channel_info) + return wpa_s->driver->channel_info(wpa_s->drv_priv, ci); + return -1; +} + static inline int wpa_drv_pktcnt_poll(struct wpa_supplicant *wpa_s, struct hostap_sta_driver_data *sta) { @@ -689,6 +697,14 @@ static inline int wpa_drv_roaming(struct wpa_supplicant *wpa_s, int allowed, return wpa_s->driver->roaming(wpa_s->drv_priv, allowed, bssid); } +static inline int wpa_drv_disable_fils(struct wpa_supplicant *wpa_s, + int disable) +{ + if (!wpa_s->driver->disable_fils) + return -1; + return wpa_s->driver->disable_fils(wpa_s->drv_priv, disable); +} + static inline int wpa_drv_set_mac_addr(struct wpa_supplicant *wpa_s, const u8 *addr) { @@ -715,6 +731,14 @@ static inline int wpa_drv_macsec_deinit(struct wpa_supplicant *wpa_s) return wpa_s->driver->macsec_deinit(wpa_s->drv_priv); } +static inline int wpa_drv_macsec_get_capability(struct wpa_supplicant *wpa_s, + enum macsec_cap *cap) +{ + if (!wpa_s->driver->macsec_get_capability) + return -1; + return wpa_s->driver->macsec_get_capability(wpa_s->drv_priv, cap); +} + static inline int wpa_drv_enable_protect_frames(struct wpa_supplicant *wpa_s, Boolean enabled) { @@ -723,6 +747,14 @@ static inline int wpa_drv_enable_protect_frames(struct wpa_supplicant *wpa_s, return wpa_s->driver->enable_protect_frames(wpa_s->drv_priv, enabled); } +static inline int wpa_drv_enable_encrypt(struct wpa_supplicant *wpa_s, + Boolean enabled) +{ + if (!wpa_s->driver->enable_encrypt) + return -1; + return wpa_s->driver->enable_encrypt(wpa_s->drv_priv, enabled); +} + static inline int wpa_drv_set_replay_protect(struct wpa_supplicant *wpa_s, Boolean enabled, u32 window) { @@ -749,145 +781,135 @@ static inline int wpa_drv_enable_controlled_port(struct wpa_supplicant *wpa_s, } static inline int wpa_drv_get_receive_lowest_pn(struct wpa_supplicant *wpa_s, - u32 channel, u8 an, - u32 *lowest_pn) + struct receive_sa *sa) { if (!wpa_s->driver->get_receive_lowest_pn) return -1; - return wpa_s->driver->get_receive_lowest_pn(wpa_s->drv_priv, channel, - an, lowest_pn); + return wpa_s->driver->get_receive_lowest_pn(wpa_s->drv_priv, sa); } static inline int wpa_drv_get_transmit_next_pn(struct wpa_supplicant *wpa_s, - u32 channel, u8 an, - u32 *next_pn) + struct transmit_sa *sa) { if (!wpa_s->driver->get_transmit_next_pn) return -1; - return wpa_s->driver->get_transmit_next_pn(wpa_s->drv_priv, channel, - an, next_pn); + return wpa_s->driver->get_transmit_next_pn(wpa_s->drv_priv, sa); } static inline int wpa_drv_set_transmit_next_pn(struct wpa_supplicant *wpa_s, - u32 channel, u8 an, - u32 next_pn) + struct transmit_sa *sa) { if (!wpa_s->driver->set_transmit_next_pn) return -1; - return wpa_s->driver->set_transmit_next_pn(wpa_s->drv_priv, channel, - an, next_pn); + return wpa_s->driver->set_transmit_next_pn(wpa_s->drv_priv, sa); } -static inline int wpa_drv_get_available_receive_sc(struct wpa_supplicant *wpa_s, - u32 *channel) +static inline int wpa_drv_set_receive_lowest_pn(struct wpa_supplicant *wpa_s, + struct receive_sa *sa) { - if (!wpa_s->driver->get_available_receive_sc) + if (!wpa_s->driver->set_receive_lowest_pn) return -1; - return wpa_s->driver->get_available_receive_sc(wpa_s->drv_priv, - channel); + return wpa_s->driver->set_receive_lowest_pn(wpa_s->drv_priv, sa); } static inline int -wpa_drv_create_receive_sc(struct wpa_supplicant *wpa_s, u32 channel, - const u8 *sci_addr, u16 sci_port, +wpa_drv_create_receive_sc(struct wpa_supplicant *wpa_s, struct receive_sc *sc, unsigned int conf_offset, int validation) { if (!wpa_s->driver->create_receive_sc) return -1; - return wpa_s->driver->create_receive_sc(wpa_s->drv_priv, channel, - sci_addr, sci_port, conf_offset, - validation); + return wpa_s->driver->create_receive_sc(wpa_s->drv_priv, sc, + conf_offset, validation); } static inline int wpa_drv_delete_receive_sc(struct wpa_supplicant *wpa_s, - u32 channel) + struct receive_sc *sc) { if (!wpa_s->driver->delete_receive_sc) return -1; - return wpa_s->driver->delete_receive_sc(wpa_s->drv_priv, channel); + return wpa_s->driver->delete_receive_sc(wpa_s->drv_priv, sc); } static inline int wpa_drv_create_receive_sa(struct wpa_supplicant *wpa_s, - u32 channel, u8 an, - u32 lowest_pn, const u8 *sak) + struct receive_sa *sa) { if (!wpa_s->driver->create_receive_sa) return -1; - return wpa_s->driver->create_receive_sa(wpa_s->drv_priv, channel, an, - lowest_pn, sak); + return wpa_s->driver->create_receive_sa(wpa_s->drv_priv, sa); } -static inline int wpa_drv_enable_receive_sa(struct wpa_supplicant *wpa_s, - u32 channel, u8 an) +static inline int wpa_drv_delete_receive_sa(struct wpa_supplicant *wpa_s, + struct receive_sa *sa) { - if (!wpa_s->driver->enable_receive_sa) + if (!wpa_s->driver->delete_receive_sa) return -1; - return wpa_s->driver->enable_receive_sa(wpa_s->drv_priv, channel, an); + return wpa_s->driver->delete_receive_sa(wpa_s->drv_priv, sa); } -static inline int wpa_drv_disable_receive_sa(struct wpa_supplicant *wpa_s, - u32 channel, u8 an) +static inline int wpa_drv_enable_receive_sa(struct wpa_supplicant *wpa_s, + struct receive_sa *sa) { - if (!wpa_s->driver->disable_receive_sa) + if (!wpa_s->driver->enable_receive_sa) return -1; - return wpa_s->driver->disable_receive_sa(wpa_s->drv_priv, channel, an); + return wpa_s->driver->enable_receive_sa(wpa_s->drv_priv, sa); } -static inline int -wpa_drv_get_available_transmit_sc(struct wpa_supplicant *wpa_s, u32 *channel) +static inline int wpa_drv_disable_receive_sa(struct wpa_supplicant *wpa_s, + struct receive_sa *sa) { - if (!wpa_s->driver->get_available_transmit_sc) + if (!wpa_s->driver->disable_receive_sa) return -1; - return wpa_s->driver->get_available_transmit_sc(wpa_s->drv_priv, - channel); + return wpa_s->driver->disable_receive_sa(wpa_s->drv_priv, sa); } static inline int -wpa_drv_create_transmit_sc(struct wpa_supplicant *wpa_s, u32 channel, - const u8 *sci_addr, u16 sci_port, +wpa_drv_create_transmit_sc(struct wpa_supplicant *wpa_s, struct transmit_sc *sc, unsigned int conf_offset) { if (!wpa_s->driver->create_transmit_sc) return -1; - return wpa_s->driver->create_transmit_sc(wpa_s->drv_priv, channel, - sci_addr, sci_port, + return wpa_s->driver->create_transmit_sc(wpa_s->drv_priv, sc, conf_offset); } static inline int wpa_drv_delete_transmit_sc(struct wpa_supplicant *wpa_s, - u32 channel) + struct transmit_sc *sc) { if (!wpa_s->driver->delete_transmit_sc) return -1; - return wpa_s->driver->delete_transmit_sc(wpa_s->drv_priv, channel); + return wpa_s->driver->delete_transmit_sc(wpa_s->drv_priv, sc); } static inline int wpa_drv_create_transmit_sa(struct wpa_supplicant *wpa_s, - u32 channel, u8 an, - u32 next_pn, - Boolean confidentiality, - const u8 *sak) + struct transmit_sa *sa) { if (!wpa_s->driver->create_transmit_sa) return -1; - return wpa_s->driver->create_transmit_sa(wpa_s->drv_priv, channel, an, - next_pn, confidentiality, sak); + return wpa_s->driver->create_transmit_sa(wpa_s->drv_priv, sa); +} + +static inline int wpa_drv_delete_transmit_sa(struct wpa_supplicant *wpa_s, + struct transmit_sa *sa) +{ + if (!wpa_s->driver->delete_transmit_sa) + return -1; + return wpa_s->driver->delete_transmit_sa(wpa_s->drv_priv, sa); } static inline int wpa_drv_enable_transmit_sa(struct wpa_supplicant *wpa_s, - u32 channel, u8 an) + struct transmit_sa *sa) { if (!wpa_s->driver->enable_transmit_sa) return -1; - return wpa_s->driver->enable_transmit_sa(wpa_s->drv_priv, channel, an); + return wpa_s->driver->enable_transmit_sa(wpa_s->drv_priv, sa); } static inline int wpa_drv_disable_transmit_sa(struct wpa_supplicant *wpa_s, - u32 channel, u8 an) + struct transmit_sa *sa) { if (!wpa_s->driver->disable_transmit_sa) return -1; - return wpa_s->driver->disable_transmit_sa(wpa_s->drv_priv, channel, an); + return wpa_s->driver->disable_transmit_sa(wpa_s->drv_priv, sa); } #endif /* CONFIG_MACSEC */ @@ -904,6 +926,11 @@ static inline int wpa_drv_get_pref_freq_list(struct wpa_supplicant *wpa_s, unsigned int *num, unsigned int *freq_list) { +#ifdef CONFIG_TESTING_OPTIONS + if (wpa_s->get_pref_freq_list_override) + return wpas_ctrl_iface_get_pref_freq_list_override( + wpa_s, if_type, num, freq_list); +#endif /* CONFIG_TESTING_OPTIONS */ if (!wpa_s->driver->get_pref_freq_list) return -1; return wpa_s->driver->get_pref_freq_list(wpa_s->drv_priv, if_type, @@ -918,11 +945,12 @@ static inline int wpa_drv_set_prob_oper_freq(struct wpa_supplicant *wpa_s, return wpa_s->driver->set_prob_oper_freq(wpa_s->drv_priv, freq); } -static inline int wpa_drv_abort_scan(struct wpa_supplicant *wpa_s) +static inline int wpa_drv_abort_scan(struct wpa_supplicant *wpa_s, + u64 scan_cookie) { if (!wpa_s->driver->abort_scan) return -1; - return wpa_s->driver->abort_scan(wpa_s->drv_priv); + return wpa_s->driver->abort_scan(wpa_s->drv_priv, scan_cookie); } static inline int wpa_drv_configure_frame_filters(struct wpa_supplicant *wpa_s, @@ -976,4 +1004,70 @@ static inline int wpa_drv_set_default_scan_ies(struct wpa_supplicant *wpa_s, return wpa_s->driver->set_default_scan_ies(wpa_s->drv_priv, ies, len); } +static inline int wpa_drv_set_tdls_mode(struct wpa_supplicant *wpa_s, + int tdls_external_control) +{ + if (!wpa_s->driver->set_tdls_mode) + return -1; + return wpa_s->driver->set_tdls_mode(wpa_s->drv_priv, + tdls_external_control); +} + +static inline struct wpa_bss_candidate_info * +wpa_drv_get_bss_trans_status(struct wpa_supplicant *wpa_s, + struct wpa_bss_trans_info *params) +{ + if (!wpa_s->driver->get_bss_transition_status) + return NULL; + return wpa_s->driver->get_bss_transition_status(wpa_s->drv_priv, + params); +} + +static inline int wpa_drv_ignore_assoc_disallow(struct wpa_supplicant *wpa_s, + int val) +{ + if (!wpa_s->driver->ignore_assoc_disallow) + return -1; + return wpa_s->driver->ignore_assoc_disallow(wpa_s->drv_priv, val); +} + +static inline int wpa_drv_set_bssid_blacklist(struct wpa_supplicant *wpa_s, + unsigned int num_bssid, + const u8 *bssids) +{ + if (!wpa_s->driver->set_bssid_blacklist) + return -1; + return wpa_s->driver->set_bssid_blacklist(wpa_s->drv_priv, num_bssid, + bssids); +} + +static inline int wpa_drv_update_connect_params( + struct wpa_supplicant *wpa_s, + struct wpa_driver_associate_params *params, + enum wpa_drv_update_connect_params_mask mask) +{ + if (!wpa_s->driver->update_connect_params) + return -1; + return wpa_s->driver->update_connect_params(wpa_s->drv_priv, params, + mask); +} + +static inline int +wpa_drv_send_external_auth_status(struct wpa_supplicant *wpa_s, + struct external_auth *params) +{ + if (!wpa_s->driver->send_external_auth_status) + return -1; + return wpa_s->driver->send_external_auth_status(wpa_s->drv_priv, + params); +} + +static inline int wpa_drv_set_4addr_mode(struct wpa_supplicant *wpa_s, int val) +{ + if (!wpa_s->driver->set_4addr_mode) + return -1; + return wpa_s->driver->set_4addr_mode(wpa_s->drv_priv, + wpa_s->bridge_ifname, val); +} + #endif /* DRIVER_I_H */ diff --git a/freebsd/contrib/wpa/wpa_supplicant/events.c b/freebsd/contrib/wpa/wpa_supplicant/events.c index 1ed27b58..8673d09c 100644 --- a/freebsd/contrib/wpa/wpa_supplicant/events.c +++ b/freebsd/contrib/wpa/wpa_supplicant/events.c @@ -2,7 +2,7 @@ /* * WPA Supplicant - Driver event processing - * Copyright (c) 2003-2015, Jouni Malinen <j@w1.fi> + * Copyright (c) 2003-2019, Jouni Malinen <j@w1.fi> * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -30,6 +30,8 @@ #include "notify.h" #include "common/ieee802_11_defs.h" #include "common/ieee802_11_common.h" +#include "common/gas_server.h" +#include "common/dpp.h" #include "crypto/random.h" #include "blacklist.h" #include "wpas_glue.h" @@ -48,6 +50,10 @@ #include "mesh.h" #include "mesh_mpm.h" #include "wmm_ac.h" +#include "dpp_supplicant.h" + + +#define MAX_OWE_TRANSITION_BSS_SELECT_COUNT 5 #ifndef CONFIG_NO_SCAN_PROCESSING @@ -56,8 +62,7 @@ static int wpas_select_network_from_last_scan(struct wpa_supplicant *wpa_s, #endif /* CONFIG_NO_SCAN_PROCESSING */ -static int wpas_temp_disabled(struct wpa_supplicant *wpa_s, - struct wpa_ssid *ssid) +int wpas_temp_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid) { struct os_reltime now; @@ -291,6 +296,13 @@ void wpa_supplicant_mark_disassoc(struct wpa_supplicant *wpa_s) if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) return; + if (os_reltime_initialized(&wpa_s->session_start)) { + os_reltime_age(&wpa_s->session_start, &wpa_s->session_length); + wpa_s->session_start.sec = 0; + wpa_s->session_start.usec = 0; + wpas_notify_session_length(wpa_s); + } + wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); bssid_changed = !is_zero_ether_addr(wpa_s->bssid); os_memset(wpa_s->bssid, 0, ETH_ALEN); @@ -304,7 +316,9 @@ void wpa_supplicant_mark_disassoc(struct wpa_supplicant *wpa_s) eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE); eapol_sm_notify_portValid(wpa_s->eapol, FALSE); - if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) + if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) || + wpa_s->key_mgmt == WPA_KEY_MGMT_OWE || + wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) eapol_sm_notify_eap_success(wpa_s->eapol, FALSE); wpa_s->ap_ies_from_associnfo = 0; wpa_s->current_ssid = NULL; @@ -313,6 +327,16 @@ void wpa_supplicant_mark_disassoc(struct wpa_supplicant *wpa_s) wpas_rrm_reset(wpa_s); wpa_s->wnmsleep_used = 0; + wnm_clear_coloc_intf_reporting(wpa_s); + +#ifdef CONFIG_TESTING_OPTIONS + wpa_s->last_tk_alg = WPA_ALG_NONE; + os_memset(wpa_s->last_tk, 0, sizeof(wpa_s->last_tk)); +#endif /* CONFIG_TESTING_OPTIONS */ + wpa_s->ieee80211ac = 0; + + if (wpa_s->enabled_4addr_mode && wpa_drv_set_4addr_mode(wpa_s, 0) == 0) + wpa_s->enabled_4addr_mode = 0; } @@ -329,7 +353,7 @@ static void wpa_find_assoc_pmkid(struct wpa_supplicant *wpa_s) for (i = 0; i < ie.num_pmkid; i++) { pmksa_set = pmksa_cache_set_current(wpa_s->wpa, ie.pmkid + i * PMKID_LEN, - NULL, NULL, 0); + NULL, NULL, 0, NULL, 0); if (pmksa_set == 0) { eapol_sm_notify_pmkid_attempt(wpa_s->eapol); break; @@ -481,6 +505,11 @@ static int wpa_supplicant_match_privacy(struct wpa_bss *bss, return 1; #endif /* CONFIG_WPS */ +#ifdef CONFIG_OWE + if ((ssid->key_mgmt & WPA_KEY_MGMT_OWE) && !ssid->owe_only) + return 1; +#endif /* CONFIG_OWE */ + if (has_wep_key(ssid)) privacy = 1; @@ -505,7 +534,7 @@ static int wpa_supplicant_match_privacy(struct wpa_bss *bss, static int wpa_supplicant_ssid_bss_match(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, - struct wpa_bss *bss) + struct wpa_bss *bss, int debug_print) { struct wpa_ie_data ie; int proto_match = 0; @@ -524,44 +553,63 @@ static int wpa_supplicant_ssid_bss_match(struct wpa_supplicant *wpa_s, (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)); rsn_ie = wpa_bss_get_ie(bss, WLAN_EID_RSN); - while ((ssid->proto & WPA_PROTO_RSN) && rsn_ie) { + while ((ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)) && rsn_ie) { proto_match++; if (wpa_parse_wpa_ie(rsn_ie, 2 + rsn_ie[1], &ie)) { - wpa_dbg(wpa_s, MSG_DEBUG, " skip RSN IE - parse " - "failed"); + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip RSN IE - parse failed"); break; } + if (!ie.has_pairwise) + ie.pairwise_cipher = wpa_default_rsn_cipher(bss->freq); + if (!ie.has_group) + ie.group_cipher = wpa_default_rsn_cipher(bss->freq); if (wep_ok && (ie.group_cipher & (WPA_CIPHER_WEP40 | WPA_CIPHER_WEP104))) { - wpa_dbg(wpa_s, MSG_DEBUG, " selected based on TSN " - "in RSN IE"); + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " selected based on TSN in RSN IE"); return 1; } - if (!(ie.proto & ssid->proto)) { - wpa_dbg(wpa_s, MSG_DEBUG, " skip RSN IE - proto " - "mismatch"); + if (!(ie.proto & ssid->proto) && + !(ssid->proto & WPA_PROTO_OSEN)) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip RSN IE - proto mismatch"); break; } if (!(ie.pairwise_cipher & ssid->pairwise_cipher)) { - wpa_dbg(wpa_s, MSG_DEBUG, " skip RSN IE - PTK " - "cipher mismatch"); + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip RSN IE - PTK cipher mismatch"); break; } if (!(ie.group_cipher & ssid->group_cipher)) { - wpa_dbg(wpa_s, MSG_DEBUG, " skip RSN IE - GTK " - "cipher mismatch"); + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip RSN IE - GTK cipher mismatch"); + break; + } + + if (ssid->group_mgmt_cipher && + !(ie.mgmt_group_cipher & ssid->group_mgmt_cipher)) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip RSN IE - group mgmt cipher mismatch"); break; } if (!(ie.key_mgmt & ssid->key_mgmt)) { - wpa_dbg(wpa_s, MSG_DEBUG, " skip RSN IE - key mgmt " - "mismatch"); + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip RSN IE - key mgmt mismatch"); break; } @@ -569,16 +617,18 @@ static int wpa_supplicant_ssid_bss_match(struct wpa_supplicant *wpa_s, if (!(ie.capabilities & WPA_CAPABILITY_MFPC) && wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) { - wpa_dbg(wpa_s, MSG_DEBUG, " skip RSN IE - no mgmt " - "frame protection"); + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip RSN IE - no mgmt frame protection"); break; } #endif /* CONFIG_IEEE80211W */ if ((ie.capabilities & WPA_CAPABILITY_MFPR) && wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION) { - wpa_dbg(wpa_s, MSG_DEBUG, - " skip RSN IE - no mgmt frame protection enabled but AP requires it"); + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip RSN IE - no mgmt frame protection enabled but AP requires it"); break; } #ifdef CONFIG_MBO @@ -586,20 +636,25 @@ static int wpa_supplicant_ssid_bss_match(struct wpa_supplicant *wpa_s, wpas_mbo_get_bss_attr(bss, MBO_ATTR_ID_AP_CAPA_IND) && wpas_get_ssid_pmf(wpa_s, ssid) != NO_MGMT_FRAME_PROTECTION) { - wpa_dbg(wpa_s, MSG_DEBUG, - " skip RSN IE - no mgmt frame protection enabled on MBO AP"); + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip RSN IE - no mgmt frame protection enabled on MBO AP"); break; } #endif /* CONFIG_MBO */ - wpa_dbg(wpa_s, MSG_DEBUG, " selected based on RSN IE"); + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " selected based on RSN IE"); return 1; } #ifdef CONFIG_IEEE80211W - if (wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) { - wpa_dbg(wpa_s, MSG_DEBUG, - " skip - MFP Required but network not MFP Capable"); + if (wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED && + (!(ssid->key_mgmt & WPA_KEY_MGMT_OWE) || ssid->owe_only)) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - MFP Required but network not MFP Capable"); return 0; } #endif /* CONFIG_IEEE80211W */ @@ -609,72 +664,110 @@ static int wpa_supplicant_ssid_bss_match(struct wpa_supplicant *wpa_s, proto_match++; if (wpa_parse_wpa_ie(wpa_ie, 2 + wpa_ie[1], &ie)) { - wpa_dbg(wpa_s, MSG_DEBUG, " skip WPA IE - parse " - "failed"); + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip WPA IE - parse failed"); break; } if (wep_ok && (ie.group_cipher & (WPA_CIPHER_WEP40 | WPA_CIPHER_WEP104))) { - wpa_dbg(wpa_s, MSG_DEBUG, " selected based on TSN " - "in WPA IE"); + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " selected based on TSN in WPA IE"); return 1; } if (!(ie.proto & ssid->proto)) { - wpa_dbg(wpa_s, MSG_DEBUG, " skip WPA IE - proto " - "mismatch"); + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip WPA IE - proto mismatch"); break; } if (!(ie.pairwise_cipher & ssid->pairwise_cipher)) { - wpa_dbg(wpa_s, MSG_DEBUG, " skip WPA IE - PTK " - "cipher mismatch"); + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip WPA IE - PTK cipher mismatch"); break; } if (!(ie.group_cipher & ssid->group_cipher)) { - wpa_dbg(wpa_s, MSG_DEBUG, " skip WPA IE - GTK " - "cipher mismatch"); + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip WPA IE - GTK cipher mismatch"); break; } if (!(ie.key_mgmt & ssid->key_mgmt)) { - wpa_dbg(wpa_s, MSG_DEBUG, " skip WPA IE - key mgmt " - "mismatch"); + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip WPA IE - key mgmt mismatch"); break; } - wpa_dbg(wpa_s, MSG_DEBUG, " selected based on WPA IE"); + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " selected based on WPA IE"); return 1; } if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && !wpa_ie && !rsn_ie) { - wpa_dbg(wpa_s, MSG_DEBUG, " allow for non-WPA IEEE 802.1X"); + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " allow for non-WPA IEEE 802.1X"); return 1; } +#ifdef CONFIG_OWE + if ((ssid->key_mgmt & WPA_KEY_MGMT_OWE) && !ssid->owe_only && + !wpa_ie && !rsn_ie) { + if (wpa_s->owe_transition_select && + wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE) && + ssid->owe_transition_bss_select_count + 1 <= + MAX_OWE_TRANSITION_BSS_SELECT_COUNT) { + ssid->owe_transition_bss_select_count++; + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip OWE transition BSS (selection count %d does not exceed %d)", + ssid->owe_transition_bss_select_count, + MAX_OWE_TRANSITION_BSS_SELECT_COUNT); + wpa_s->owe_transition_search = 1; + return 0; + } + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " allow in OWE transition mode"); + return 1; + } +#endif /* CONFIG_OWE */ + if ((ssid->proto & (WPA_PROTO_WPA | WPA_PROTO_RSN)) && wpa_key_mgmt_wpa(ssid->key_mgmt) && proto_match == 0) { - wpa_dbg(wpa_s, MSG_DEBUG, " skip - no WPA/RSN proto match"); + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - no WPA/RSN proto match"); return 0; } if ((ssid->key_mgmt & WPA_KEY_MGMT_OSEN) && wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE)) { - wpa_dbg(wpa_s, MSG_DEBUG, " allow in OSEN"); + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, " allow in OSEN"); return 1; } if (!wpa_key_mgmt_wpa(ssid->key_mgmt)) { - wpa_dbg(wpa_s, MSG_DEBUG, " allow in non-WPA/WPA2"); + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, " allow in non-WPA/WPA2"); return 1; } - wpa_dbg(wpa_s, MSG_DEBUG, " reject due to mismatch with " - "WPA/WPA2"); + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " reject due to mismatch with WPA/WPA2"); return 0; } @@ -694,7 +787,8 @@ static int freq_allowed(int *freqs, int freq) } -static int rate_match(struct wpa_supplicant *wpa_s, struct wpa_bss *bss) +static int rate_match(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, + int debug_print) { const struct hostapd_hw_modes *mode = NULL, *modes; const u8 scan_ie[2] = { WLAN_EID_SUPP_RATES, WLAN_EID_EXT_SUPP_RATES }; @@ -751,9 +845,9 @@ static int rate_match(struct wpa_supplicant *wpa_s, struct wpa_bss *bss) if (flagged && ((rate_ie[j] & 0x7f) == BSS_MEMBERSHIP_SELECTOR_HT_PHY)) { if (!ht_supported(mode)) { - wpa_dbg(wpa_s, MSG_DEBUG, - " hardware does not support " - "HT PHY"); + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " hardware does not support HT PHY"); return 0; } continue; @@ -763,9 +857,9 @@ static int rate_match(struct wpa_supplicant *wpa_s, struct wpa_bss *bss) if (flagged && ((rate_ie[j] & 0x7f) == BSS_MEMBERSHIP_SELECTOR_VHT_PHY)) { if (!vht_supported(mode)) { - wpa_dbg(wpa_s, MSG_DEBUG, - " hardware does not support " - "VHT PHY"); + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " hardware does not support VHT PHY"); return 0; } continue; @@ -785,10 +879,11 @@ static int rate_match(struct wpa_supplicant *wpa_s, struct wpa_bss *bss) * order to join a BSS all required rates * have to be supported by the hardware. */ - wpa_dbg(wpa_s, MSG_DEBUG, - " hardware does not support required rate %d.%d Mbps (freq=%d mode==%d num_rates=%d)", - r / 10, r % 10, - bss->freq, mode->mode, mode->num_rates); + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " hardware does not support required rate %d.%d Mbps (freq=%d mode==%d num_rates=%d)", + r / 10, r % 10, + bss->freq, mode->mode, mode->num_rates); return 0; } } @@ -841,39 +936,124 @@ static int addr_in_list(const u8 *addr, const u8 *list, size_t num) } +static void owe_trans_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, + const u8 **ret_ssid, size_t *ret_ssid_len) +{ +#ifdef CONFIG_OWE + const u8 *owe, *pos, *end, *bssid; + u8 ssid_len; + struct wpa_bss *open_bss; + + owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE); + if (!owe || !wpa_bss_get_ie(bss, WLAN_EID_RSN)) + return; + + pos = owe + 6; + end = owe + 2 + owe[1]; + + if (end - pos < ETH_ALEN + 1) + return; + bssid = pos; + pos += ETH_ALEN; + ssid_len = *pos++; + if (end - pos < ssid_len || ssid_len > SSID_MAX_LEN) + return; + + /* Match the profile SSID against the OWE transition mode SSID on the + * open network. */ + wpa_dbg(wpa_s, MSG_DEBUG, "OWE: transition mode BSSID: " MACSTR + " SSID: %s", MAC2STR(bssid), wpa_ssid_txt(pos, ssid_len)); + *ret_ssid = pos; + *ret_ssid_len = ssid_len; + + if (bss->ssid_len > 0) + return; + + open_bss = wpa_bss_get_bssid_latest(wpa_s, bssid); + if (!open_bss) + return; + if (ssid_len != open_bss->ssid_len || + os_memcmp(pos, open_bss->ssid, ssid_len) != 0) { + wpa_dbg(wpa_s, MSG_DEBUG, + "OWE: transition mode SSID mismatch: %s", + wpa_ssid_txt(open_bss->ssid, open_bss->ssid_len)); + return; + } + + owe = wpa_bss_get_vendor_ie(open_bss, OWE_IE_VENDOR_TYPE); + if (!owe || wpa_bss_get_ie(open_bss, WLAN_EID_RSN)) { + wpa_dbg(wpa_s, MSG_DEBUG, + "OWE: transition mode open BSS unexpected info"); + return; + } + + pos = owe + 6; + end = owe + 2 + owe[1]; + + if (end - pos < ETH_ALEN + 1) + return; + if (os_memcmp(pos, bss->bssid, ETH_ALEN) != 0) { + wpa_dbg(wpa_s, MSG_DEBUG, + "OWE: transition mode BSSID mismatch: " MACSTR, + MAC2STR(pos)); + return; + } + pos += ETH_ALEN; + ssid_len = *pos++; + if (end - pos < ssid_len || ssid_len > SSID_MAX_LEN) + return; + wpa_dbg(wpa_s, MSG_DEBUG, "OWE: learned transition mode OWE SSID: %s", + wpa_ssid_txt(pos, ssid_len)); + os_memcpy(bss->ssid, pos, ssid_len); + bss->ssid_len = ssid_len; +#endif /* CONFIG_OWE */ +} + + struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s, int i, struct wpa_bss *bss, struct wpa_ssid *group, - int only_first_ssid) + int only_first_ssid, int debug_print) { u8 wpa_ie_len, rsn_ie_len; int wpa; struct wpa_blacklist *e; const u8 *ie; struct wpa_ssid *ssid; - int osen; + int osen, rsn_osen = 0; #ifdef CONFIG_MBO const u8 *assoc_disallow; #endif /* CONFIG_MBO */ + const u8 *match_ssid; + size_t match_ssid_len; + struct wpa_ie_data data; ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE); wpa_ie_len = ie ? ie[1] : 0; ie = wpa_bss_get_ie(bss, WLAN_EID_RSN); rsn_ie_len = ie ? ie[1] : 0; + if (ie && wpa_parse_wpa_ie_rsn(ie, 2 + ie[1], &data) == 0 && + (data.key_mgmt & WPA_KEY_MGMT_OSEN)) + rsn_osen = 1; ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE); osen = ie != NULL; - wpa_dbg(wpa_s, MSG_DEBUG, "%d: " MACSTR " ssid='%s' " - "wpa_ie_len=%u rsn_ie_len=%u caps=0x%x level=%d freq=%d %s%s%s", - i, MAC2STR(bss->bssid), wpa_ssid_txt(bss->ssid, bss->ssid_len), - wpa_ie_len, rsn_ie_len, bss->caps, bss->level, bss->freq, - wpa_bss_get_vendor_ie(bss, WPS_IE_VENDOR_TYPE) ? " wps" : "", - (wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE) || - wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE)) ? - " p2p" : "", - osen ? " osen=1" : ""); + if (debug_print) { + wpa_dbg(wpa_s, MSG_DEBUG, "%d: " MACSTR + " ssid='%s' wpa_ie_len=%u rsn_ie_len=%u caps=0x%x level=%d freq=%d %s%s%s", + i, MAC2STR(bss->bssid), + wpa_ssid_txt(bss->ssid, bss->ssid_len), + wpa_ie_len, rsn_ie_len, bss->caps, bss->level, + bss->freq, + wpa_bss_get_vendor_ie(bss, WPS_IE_VENDOR_TYPE) ? + " wps" : "", + (wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE) || + wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE)) + ? " p2p" : "", + osen ? " osen=1" : ""); + } e = wpa_blacklist_get(wpa_s, bss->bssid); if (e) { @@ -890,24 +1070,34 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s, limit = 0; } if (e->count > limit) { - wpa_dbg(wpa_s, MSG_DEBUG, " skip - blacklisted " - "(count=%d limit=%d)", e->count, limit); + if (debug_print) { + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - blacklisted (count=%d limit=%d)", + e->count, limit); + } return NULL; } } - if (bss->ssid_len == 0) { - wpa_dbg(wpa_s, MSG_DEBUG, " skip - SSID not known"); + match_ssid = bss->ssid; + match_ssid_len = bss->ssid_len; + owe_trans_ssid(wpa_s, bss, &match_ssid, &match_ssid_len); + + if (match_ssid_len == 0) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, " skip - SSID not known"); return NULL; } if (disallowed_bssid(wpa_s, bss->bssid)) { - wpa_dbg(wpa_s, MSG_DEBUG, " skip - BSSID disallowed"); + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, " skip - BSSID disallowed"); return NULL; } - if (disallowed_ssid(wpa_s, bss->ssid, bss->ssid_len)) { - wpa_dbg(wpa_s, MSG_DEBUG, " skip - SSID disallowed"); + if (disallowed_ssid(wpa_s, match_ssid, match_ssid_len)) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, " skip - SSID disallowed"); return NULL; } @@ -918,21 +1108,25 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s, int res; if (wpas_network_disabled(wpa_s, ssid)) { - wpa_dbg(wpa_s, MSG_DEBUG, " skip - disabled"); + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, " skip - disabled"); continue; } res = wpas_temp_disabled(wpa_s, ssid); if (res > 0) { - wpa_dbg(wpa_s, MSG_DEBUG, " skip - disabled " - "temporarily for %d second(s)", res); + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - disabled temporarily for %d second(s)", + res); continue; } #ifdef CONFIG_WPS if ((ssid->key_mgmt & WPA_KEY_MGMT_WPS) && e && e->count > 0) { - wpa_dbg(wpa_s, MSG_DEBUG, " skip - blacklisted " - "(WPS)"); + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - blacklisted (WPS)"); continue; } @@ -956,15 +1150,19 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s, check_ssid = 0; if (check_ssid && - (bss->ssid_len != ssid->ssid_len || - os_memcmp(bss->ssid, ssid->ssid, bss->ssid_len) != 0)) { - wpa_dbg(wpa_s, MSG_DEBUG, " skip - SSID mismatch"); + (match_ssid_len != ssid->ssid_len || + os_memcmp(match_ssid, ssid->ssid, match_ssid_len) != 0)) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - SSID mismatch"); continue; } if (ssid->bssid_set && os_memcmp(bss->bssid, ssid->bssid, ETH_ALEN) != 0) { - wpa_dbg(wpa_s, MSG_DEBUG, " skip - BSSID mismatch"); + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - BSSID mismatch"); continue; } @@ -972,8 +1170,9 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s, if (ssid->num_bssid_blacklist && addr_in_list(bss->bssid, ssid->bssid_blacklist, ssid->num_bssid_blacklist)) { - wpa_dbg(wpa_s, MSG_DEBUG, - " skip - BSSID blacklisted"); + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - BSSID blacklisted"); continue; } @@ -981,79 +1180,108 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s, if (ssid->num_bssid_whitelist && !addr_in_list(bss->bssid, ssid->bssid_whitelist, ssid->num_bssid_whitelist)) { - wpa_dbg(wpa_s, MSG_DEBUG, - " skip - BSSID not in whitelist"); + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - BSSID not in whitelist"); continue; } - if (!wpa_supplicant_ssid_bss_match(wpa_s, ssid, bss)) + if (!wpa_supplicant_ssid_bss_match(wpa_s, ssid, bss, + debug_print)) continue; if (!osen && !wpa && !(ssid->key_mgmt & WPA_KEY_MGMT_NONE) && !(ssid->key_mgmt & WPA_KEY_MGMT_WPS) && + !(ssid->key_mgmt & WPA_KEY_MGMT_OWE) && !(ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)) { - wpa_dbg(wpa_s, MSG_DEBUG, " skip - non-WPA network " - "not allowed"); + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - non-WPA network not allowed"); continue; } if (wpa && !wpa_key_mgmt_wpa(ssid->key_mgmt) && has_wep_key(ssid)) { - wpa_dbg(wpa_s, MSG_DEBUG, " skip - ignore WPA/WPA2 AP for WEP network block"); + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - ignore WPA/WPA2 AP for WEP network block"); continue; } - if ((ssid->key_mgmt & WPA_KEY_MGMT_OSEN) && !osen) { - wpa_dbg(wpa_s, MSG_DEBUG, " skip - non-OSEN network " - "not allowed"); + if ((ssid->key_mgmt & WPA_KEY_MGMT_OSEN) && !osen && + !rsn_osen) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - non-OSEN network not allowed"); continue; } if (!wpa_supplicant_match_privacy(bss, ssid)) { - wpa_dbg(wpa_s, MSG_DEBUG, " skip - privacy " - "mismatch"); + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - privacy mismatch"); continue; } if (ssid->mode != IEEE80211_MODE_MESH && !bss_is_ess(bss) && !bss_is_pbss(bss)) { - wpa_dbg(wpa_s, MSG_DEBUG, - " skip - not ESS, PBSS, or MBSS"); + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - not ESS, PBSS, or MBSS"); continue; } if (ssid->pbss != 2 && ssid->pbss != bss_is_pbss(bss)) { - wpa_dbg(wpa_s, MSG_DEBUG, " skip - PBSS mismatch (ssid %d bss %d)", - ssid->pbss, bss_is_pbss(bss)); + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - PBSS mismatch (ssid %d bss %d)", + ssid->pbss, bss_is_pbss(bss)); continue; } if (!freq_allowed(ssid->freq_list, bss->freq)) { - wpa_dbg(wpa_s, MSG_DEBUG, " skip - frequency not " - "allowed"); + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - frequency not allowed"); continue; } #ifdef CONFIG_MESH if (ssid->mode == IEEE80211_MODE_MESH && ssid->frequency > 0 && ssid->frequency != bss->freq) { - wpa_dbg(wpa_s, MSG_DEBUG, " skip - frequency not allowed (mesh)"); + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - frequency not allowed (mesh)"); continue; } #endif /* CONFIG_MESH */ - if (!rate_match(wpa_s, bss)) { - wpa_dbg(wpa_s, MSG_DEBUG, " skip - rate sets do " - "not match"); + if (!rate_match(wpa_s, bss, debug_print)) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - rate sets do not match"); continue; } +#ifndef CONFIG_IBSS_RSN + if (ssid->mode == WPAS_MODE_IBSS && + !(ssid->key_mgmt & (WPA_KEY_MGMT_NONE | + WPA_KEY_MGMT_WPA_NONE))) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - IBSS RSN not supported in the build"); + continue; + } +#endif /* !CONFIG_IBSS_RSN */ + #ifdef CONFIG_P2P if (ssid->p2p_group && !wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE) && !wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE)) { - wpa_dbg(wpa_s, MSG_DEBUG, " skip - no P2P IE seen"); + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - no P2P IE seen"); continue; } @@ -1063,20 +1291,26 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s, ie = wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE); if (ie == NULL) { - wpa_dbg(wpa_s, MSG_DEBUG, " skip - no P2P element"); + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - no P2P element"); continue; } p2p_ie = wpa_bss_get_vendor_ie_multi( bss, P2P_IE_VENDOR_TYPE); if (p2p_ie == NULL) { - wpa_dbg(wpa_s, MSG_DEBUG, " skip - could not fetch P2P element"); + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - could not fetch P2P element"); continue; } if (p2p_parse_dev_addr_in_p2p_ie(p2p_ie, dev_addr) < 0 || os_memcmp(dev_addr, ssid->go_p2p_dev_addr, ETH_ALEN) != 0) { - wpa_dbg(wpa_s, MSG_DEBUG, " skip - no matching GO P2P Device Address in P2P element"); + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - no matching GO P2P Device Address in P2P element"); wpabuf_free(p2p_ie); continue; } @@ -1096,8 +1330,9 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s, os_reltime_sub(&wpa_s->scan_min_time, &bss->last_update, &diff); - wpa_dbg(wpa_s, MSG_DEBUG, - " skip - scan result not recent enough (%u.%06u seconds too old)", + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - scan result not recent enough (%u.%06u seconds too old)", (unsigned int) diff.sec, (unsigned int) diff.usec); continue; @@ -1110,15 +1345,17 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s, assoc_disallow = wpas_mbo_get_bss_attr( bss, MBO_ATTR_ID_ASSOC_DISALLOW); if (assoc_disallow && assoc_disallow[1] >= 1) { - wpa_dbg(wpa_s, MSG_DEBUG, - " skip - MBO association disallowed (reason %u)", + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - MBO association disallowed (reason %u)", assoc_disallow[2]); continue; } - if (wpa_is_bss_tmp_disallowed(wpa_s, bss->bssid)) { - wpa_dbg(wpa_s, MSG_DEBUG, - " skip - MBO retry delay has not passed yet"); + if (wpa_is_bss_tmp_disallowed(wpa_s, bss)) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - AP temporarily disallowed"); continue; } #ifdef CONFIG_TESTING_OPTIONS @@ -1126,6 +1363,19 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s, #endif /* CONFIG_TESTING_OPTIONS */ #endif /* CONFIG_MBO */ +#ifdef CONFIG_DPP + if ((ssid->key_mgmt & WPA_KEY_MGMT_DPP) && + !wpa_sm_pmksa_exists(wpa_s->wpa, bss->bssid, ssid) && + (!ssid->dpp_connector || + !ssid->dpp_netaccesskey || + !ssid->dpp_csign)) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - no PMKSA entry for DPP"); + continue; + } +#endif /* CONFIG_DPP */ + /* Matching configuration found */ return ssid; } @@ -1143,6 +1393,25 @@ wpa_supplicant_select_bss(struct wpa_supplicant *wpa_s, { unsigned int i; + if (wpa_s->current_ssid) { + struct wpa_ssid *ssid; + + wpa_dbg(wpa_s, MSG_DEBUG, + "Scan results matching the currently selected network"); + for (i = 0; i < wpa_s->last_scan_res_used; i++) { + struct wpa_bss *bss = wpa_s->last_scan_res[i]; + + ssid = wpa_scan_res_match(wpa_s, i, bss, group, + only_first_ssid, 0); + if (ssid != wpa_s->current_ssid) + continue; + wpa_dbg(wpa_s, MSG_DEBUG, "%u: " MACSTR + " freq=%d level=%d snr=%d est_throughput=%u", + i, MAC2STR(bss->bssid), bss->freq, bss->level, + bss->snr, bss->est_throughput); + } + } + if (only_first_ssid) wpa_dbg(wpa_s, MSG_DEBUG, "Try to find BSS matching pre-selected network id=%d", group->id); @@ -1152,8 +1421,11 @@ wpa_supplicant_select_bss(struct wpa_supplicant *wpa_s, for (i = 0; i < wpa_s->last_scan_res_used; i++) { struct wpa_bss *bss = wpa_s->last_scan_res[i]; + + wpa_s->owe_transition_select = 1; *selected_ssid = wpa_scan_res_match(wpa_s, i, bss, group, - only_first_ssid); + only_first_ssid, 1); + wpa_s->owe_transition_select = 0; if (!*selected_ssid) continue; wpa_dbg(wpa_s, MSG_DEBUG, " selected BSS " MACSTR @@ -1334,6 +1606,17 @@ wpa_supplicant_pick_new_network(struct wpa_supplicant *wpa_s) { if (wpas_network_disabled(wpa_s, ssid)) continue; +#ifndef CONFIG_IBSS_RSN + if (ssid->mode == WPAS_MODE_IBSS && + !(ssid->key_mgmt & (WPA_KEY_MGMT_NONE | + WPA_KEY_MGMT_WPA_NONE))) { + wpa_msg(wpa_s, MSG_INFO, + "IBSS RSN not supported in the build - cannot use the profile for SSID '%s'", + wpa_ssid_txt(ssid->ssid, + ssid->ssid_len)); + continue; + } +#endif /* !CONFIG_IBSS_RSN */ if (ssid->mode == IEEE80211_MODE_IBSS || ssid->mode == IEEE80211_MODE_AP || ssid->mode == IEEE80211_MODE_MESH) @@ -1377,8 +1660,9 @@ static int wpa_supplicant_need_to_roam(struct wpa_supplicant *wpa_s, { struct wpa_bss *current_bss = NULL; #ifndef CONFIG_NO_ROAMING - int min_diff; + int min_diff, diff; int to_5ghz; + int cur_est, sel_est; #endif /* CONFIG_NO_ROAMING */ if (wpa_s->reassociate) @@ -1412,12 +1696,13 @@ static int wpa_supplicant_need_to_roam(struct wpa_supplicant *wpa_s, #ifndef CONFIG_NO_ROAMING wpa_dbg(wpa_s, MSG_DEBUG, "Considering within-ESS reassociation"); wpa_dbg(wpa_s, MSG_DEBUG, "Current BSS: " MACSTR - " level=%d snr=%d est_throughput=%u", - MAC2STR(current_bss->bssid), current_bss->level, + " freq=%d level=%d snr=%d est_throughput=%u", + MAC2STR(current_bss->bssid), + current_bss->freq, current_bss->level, current_bss->snr, current_bss->est_throughput); wpa_dbg(wpa_s, MSG_DEBUG, "Selected BSS: " MACSTR - " level=%d snr=%d est_throughput=%u", - MAC2STR(selected->bssid), selected->level, + " freq=%d level=%d snr=%d est_throughput=%u", + MAC2STR(selected->bssid), selected->freq, selected->level, selected->snr, selected->est_throughput); if (wpa_s->current_ssid->bssid_set && @@ -1443,6 +1728,14 @@ static int wpa_supplicant_need_to_roam(struct wpa_supplicant *wpa_s, return 0; } + if (current_bss->est_throughput > selected->est_throughput + 5000) { + wpa_dbg(wpa_s, MSG_DEBUG, + "Skip roam - Current BSS has better estimated throughput"); + return 0; + } + + cur_est = current_bss->est_throughput; + sel_est = selected->est_throughput; min_diff = 2; if (current_bss->level < 0) { if (current_bss->level < -85) @@ -1455,20 +1748,42 @@ static int wpa_supplicant_need_to_roam(struct wpa_supplicant *wpa_s, min_diff = 4; else min_diff = 5; + if (cur_est > sel_est * 1.5) + min_diff += 10; + else if (cur_est > sel_est * 1.2) + min_diff += 5; + else if (cur_est > sel_est * 1.1) + min_diff += 2; + else if (cur_est > sel_est) + min_diff++; } if (to_5ghz) { + int reduce = 2; + /* Make it easier to move to 5 GHz band */ - if (min_diff > 2) - min_diff -= 2; + if (sel_est > cur_est * 1.5) + reduce = 5; + else if (sel_est > cur_est * 1.2) + reduce = 4; + else if (sel_est > cur_est * 1.1) + reduce = 3; + + if (min_diff > reduce) + min_diff -= reduce; else min_diff = 0; } - if (abs(current_bss->level - selected->level) < min_diff) { - wpa_dbg(wpa_s, MSG_DEBUG, "Skip roam - too small difference " - "in signal level"); + diff = abs(current_bss->level - selected->level); + if (diff < min_diff) { + wpa_dbg(wpa_s, MSG_DEBUG, + "Skip roam - too small difference in signal level (%d < %d)", + diff, min_diff); return 0; } + wpa_dbg(wpa_s, MSG_DEBUG, + "Allow reassociation due to difference in signal level (%d >= %d)", + diff, min_diff); return 1; #else /* CONFIG_NO_ROAMING */ return 0; @@ -1476,11 +1791,18 @@ static int wpa_supplicant_need_to_roam(struct wpa_supplicant *wpa_s, } -/* Return != 0 if no scan results could be fetched or if scan results should not - * be shared with other virtual interfaces. */ +/* + * Return a negative value if no scan results could be fetched or if scan + * results should not be shared with other virtual interfaces. + * Return 0 if scan results were fetched and may be shared with other + * interfaces. + * Return 1 if scan results may be shared with other virtual interfaces but may + * not trigger any operations. + * Return 2 if the interface was removed and cannot be used. + */ static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s, union wpa_event_data *data, - int own_request) + int own_request, int update_only) { struct wpa_scan_results *scan_res = NULL; int ret = 0; @@ -1530,6 +1852,11 @@ static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s, } #endif /* CONFIG_NO_RANDOM_POOL */ + if (update_only) { + ret = 1; + goto scan_work_done; + } + if (own_request && wpa_s->scan_res_handler && !(data && data->scan_info.external_scan)) { void (*scan_res_handler)(struct wpa_supplicant *wpa_s, @@ -1538,7 +1865,7 @@ static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s, scan_res_handler = wpa_s->scan_res_handler; wpa_s->scan_res_handler = NULL; scan_res_handler(wpa_s, scan_res); - ret = -2; + ret = 1; goto scan_work_done; } @@ -1579,6 +1906,10 @@ static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s, if (sme_proc_obss_scan(wpa_s) > 0) goto scan_work_done; + if (own_request && data && + wpas_beacon_rep_scan_process(wpa_s, scan_res, &data->scan_info) > 0) + goto scan_work_done; + if ((wpa_s->conf->ap_scan == 2 && !wpas_wps_searching(wpa_s))) goto scan_work_done; @@ -1641,6 +1972,7 @@ static int wpas_select_network_from_last_scan(struct wpa_supplicant *wpa_s, if (wpa_s->p2p_mgmt) return 0; /* no normal connection on p2p_mgmt interface */ + wpa_s->owe_transition_search = 0; selected = wpa_supplicant_pick_network(wpa_s, &ssid); #ifdef CONFIG_MESH @@ -1674,8 +2006,9 @@ static int wpas_select_network_from_last_scan(struct wpa_supplicant *wpa_s, if (new_scan) wpa_supplicant_rsn_preauth_scan_results(wpa_s); /* - * Do not notify other virtual radios of scan results since we do not - * want them to start other associations at the same time. + * Do not allow other virtual radios to trigger operations based + * on these scan results since we do not want them to start + * other associations at the same time. */ return 1; } else { @@ -1741,6 +2074,17 @@ static int wpas_select_network_from_last_scan(struct wpa_supplicant *wpa_s, return 0; } #endif /* CONFIG_WPS */ +#ifdef CONFIG_OWE + if (wpa_s->owe_transition_search) { + wpa_dbg(wpa_s, MSG_DEBUG, + "OWE: Use shorter wait during transition mode search"); + timeout_sec = 0; + timeout_usec = 500000; + wpa_supplicant_req_new_scan(wpa_s, timeout_sec, + timeout_usec); + return 0; + } +#endif /* CONFIG_OWE */ if (wpa_supplicant_req_sched_scan(wpa_s)) wpa_supplicant_req_new_scan(wpa_s, timeout_sec, timeout_usec); @@ -1759,7 +2103,7 @@ static int wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s, struct wpa_supplicant *ifs; int res; - res = _wpa_supplicant_event_scan_results(wpa_s, data, 1); + res = _wpa_supplicant_event_scan_results(wpa_s, data, 1, 0); if (res == 2) { /* * Interface may have been removed, so must not dereference @@ -1767,7 +2111,8 @@ static int wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s, */ return 1; } - if (res != 0) { + + if (res < 0) { /* * If no scan results could be fetched, then no need to * notify those interfaces that did not actually request @@ -1787,7 +2132,10 @@ static int wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s, if (ifs != wpa_s) { wpa_printf(MSG_DEBUG, "%s: Updating scan results from " "sibling", ifs->ifname); - _wpa_supplicant_event_scan_results(ifs, data, 0); + res = _wpa_supplicant_event_scan_results(ifs, data, 0, + res > 0); + if (res < 0) + return 0; } } @@ -1804,6 +2152,8 @@ int wpa_supplicant_fast_associate(struct wpa_supplicant *wpa_s) #else /* CONFIG_NO_SCAN_PROCESSING */ struct os_reltime now; + wpa_s->ignore_post_flush_scan_res = 0; + if (wpa_s->last_scan_res_used == 0) return -1; @@ -1934,6 +2284,57 @@ static void interworking_process_assoc_resp(struct wpa_supplicant *wpa_s, #endif /* CONFIG_INTERWORKING */ +static void multi_ap_process_assoc_resp(struct wpa_supplicant *wpa_s, + const u8 *ies, size_t ies_len) +{ + struct ieee802_11_elems elems; + const u8 *map_sub_elem, *pos; + size_t len; + + if (!wpa_s->current_ssid || + !wpa_s->current_ssid->multi_ap_backhaul_sta || + !ies || + ieee802_11_parse_elems(ies, ies_len, &elems, 1) == ParseFailed) + return; + + if (!elems.multi_ap || elems.multi_ap_len < 7) { + wpa_printf(MSG_INFO, "AP doesn't support Multi-AP protocol"); + goto fail; + } + + pos = elems.multi_ap + 4; + len = elems.multi_ap_len - 4; + + map_sub_elem = get_ie(pos, len, MULTI_AP_SUB_ELEM_TYPE); + if (!map_sub_elem || map_sub_elem[1] < 1) { + wpa_printf(MSG_INFO, "invalid Multi-AP sub elem type"); + goto fail; + } + + if (!(map_sub_elem[2] & MULTI_AP_BACKHAUL_BSS)) { + if ((map_sub_elem[2] & MULTI_AP_FRONTHAUL_BSS) && + wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS) { + wpa_printf(MSG_INFO, + "WPS active, accepting fronthaul-only BSS"); + /* Don't set 4addr mode in this case, so just return */ + return; + } + wpa_printf(MSG_INFO, "AP doesn't support backhaul BSS"); + goto fail; + } + + if (wpa_drv_set_4addr_mode(wpa_s, 1) < 0) { + wpa_printf(MSG_ERROR, "Failed to set 4addr mode"); + goto fail; + } + wpa_s->enabled_4addr_mode = 1; + return; + +fail: + wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING); +} + + #ifdef CONFIG_FST static int wpas_fst_update_mbie(struct wpa_supplicant *wpa_s, const u8 *ie, size_t ie_len) @@ -1983,9 +2384,9 @@ static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s, { int l, len, found = 0, wpa_found, rsn_found; const u8 *p; -#ifdef CONFIG_IEEE80211R +#if defined(CONFIG_IEEE80211R) || defined(CONFIG_OWE) u8 bssid[ETH_ALEN]; -#endif /* CONFIG_IEEE80211R */ +#endif /* CONFIG_IEEE80211R || CONFIG_OWE */ wpa_dbg(wpa_s, MSG_DEBUG, "Association info event"); if (data->assoc_info.req_ies) @@ -2006,6 +2407,13 @@ static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s, interworking_process_assoc_resp(wpa_s, data->assoc_info.resp_ies, data->assoc_info.resp_ies_len); #endif /* CONFIG_INTERWORKING */ + if (wpa_s->hw_capab == CAPAB_VHT && + get_ie(data->assoc_info.resp_ies, + data->assoc_info.resp_ies_len, WLAN_EID_VHT_CAP)) + wpa_s->ieee80211ac = 1; + + multi_ap_process_assoc_resp(wpa_s, data->assoc_info.resp_ies, + data->assoc_info.resp_ies_len); } if (data->assoc_info.beacon_ies) wpa_hexdump(MSG_DEBUG, "beacon_ies", @@ -2015,6 +2423,26 @@ static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s, wpa_dbg(wpa_s, MSG_DEBUG, "freq=%u MHz", data->assoc_info.freq); + wpa_s->connection_set = 0; + if (data->assoc_info.req_ies && data->assoc_info.resp_ies) { + struct ieee802_11_elems req_elems, resp_elems; + + if (ieee802_11_parse_elems(data->assoc_info.req_ies, + data->assoc_info.req_ies_len, + &req_elems, 0) != ParseFailed && + ieee802_11_parse_elems(data->assoc_info.resp_ies, + data->assoc_info.resp_ies_len, + &resp_elems, 0) != ParseFailed) { + wpa_s->connection_set = 1; + wpa_s->connection_ht = req_elems.ht_capabilities && + resp_elems.ht_capabilities; + wpa_s->connection_vht = req_elems.vht_capabilities && + resp_elems.vht_capabilities; + wpa_s->connection_he = req_elems.he_capabilities && + resp_elems.he_capabilities; + } + } + p = data->assoc_info.req_ies; l = data->assoc_info.req_ies_len; @@ -2043,6 +2471,58 @@ static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s, if (!found && data->assoc_info.req_ies) wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0); +#ifdef CONFIG_FILS +#ifdef CONFIG_SME + if ((wpa_s->sme.auth_alg == WPA_AUTH_ALG_FILS || + wpa_s->sme.auth_alg == WPA_AUTH_ALG_FILS_SK_PFS) && + (!data->assoc_info.resp_frame || + fils_process_assoc_resp(wpa_s->wpa, + data->assoc_info.resp_frame, + data->assoc_info.resp_frame_len) < 0)) { + wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_UNSPECIFIED); + return -1; + } +#endif /* CONFIG_SME */ + + /* Additional processing for FILS when SME is in driver */ + if (wpa_s->auth_alg == WPA_AUTH_ALG_FILS && + !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME)) + wpa_sm_set_reset_fils_completed(wpa_s->wpa, 1); +#endif /* CONFIG_FILS */ + +#ifdef CONFIG_OWE + if (wpa_s->key_mgmt == WPA_KEY_MGMT_OWE && + (wpa_drv_get_bssid(wpa_s, bssid) < 0 || + owe_process_assoc_resp(wpa_s->wpa, bssid, + data->assoc_info.resp_ies, + data->assoc_info.resp_ies_len) < 0)) { + wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_UNSPECIFIED); + return -1; + } +#endif /* CONFIG_OWE */ + +#ifdef CONFIG_DPP2 + wpa_sm_set_dpp_z(wpa_s->wpa, NULL); + if (wpa_s->key_mgmt == WPA_KEY_MGMT_DPP && wpa_s->dpp_pfs) { + struct ieee802_11_elems elems; + + if (ieee802_11_parse_elems(data->assoc_info.resp_ies, + data->assoc_info.resp_ies_len, + &elems, 0) == ParseFailed || + !elems.owe_dh) + goto no_pfs; + if (dpp_pfs_process(wpa_s->dpp_pfs, elems.owe_dh, + elems.owe_dh_len) < 0) { + wpa_supplicant_deauthenticate(wpa_s, + WLAN_REASON_UNSPECIFIED); + return -1; + } + + wpa_sm_set_dpp_z(wpa_s->wpa, wpa_s->dpp_pfs->secret); + } +no_pfs: +#endif /* CONFIG_DPP2 */ + #ifdef CONFIG_IEEE80211R #ifdef CONFIG_SME if (wpa_s->sme.auth_alg == WPA_AUTH_ALG_FT) { @@ -2264,6 +2744,13 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s, ft_completed = wpa_ft_is_completed(wpa_s->wpa); if (data && wpa_supplicant_event_associnfo(wpa_s, data) < 0) return; + /* + * FILS authentication can share the same mechanism to mark the + * connection fully authenticated, so set ft_completed also based on + * FILS result. + */ + if (!ft_completed) + ft_completed = wpa_fils_is_completed(wpa_s->wpa); if (wpa_drv_get_bssid(wpa_s, bssid) < 0) { wpa_dbg(wpa_s, MSG_ERROR, "Failed to get BSSID"); @@ -2274,6 +2761,16 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s, wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATED); if (os_memcmp(bssid, wpa_s->bssid, ETH_ALEN) != 0) { + if (os_reltime_initialized(&wpa_s->session_start)) { + os_reltime_age(&wpa_s->session_start, + &wpa_s->session_length); + wpa_s->session_start.sec = 0; + wpa_s->session_start.usec = 0; + wpas_notify_session_length(wpa_s); + } else { + wpas_notify_auth_changed(wpa_s); + os_get_reltime(&wpa_s->session_start); + } wpa_dbg(wpa_s, MSG_DEBUG, "Associated to a new BSS: BSSID=" MACSTR, MAC2STR(bssid)); new_bss = 1; @@ -2333,7 +2830,9 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s, eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE); eapol_sm_notify_portValid(wpa_s->eapol, FALSE); } - if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) || ft_completed || + if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) || + wpa_s->key_mgmt == WPA_KEY_MGMT_DPP || + wpa_s->key_mgmt == WPA_KEY_MGMT_OWE || ft_completed || already_authorized) eapol_sm_notify_eap_success(wpa_s->eapol, FALSE); /* 802.1X::portControl = Auto */ @@ -2362,8 +2861,17 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s, } wpa_supplicant_cancel_scan(wpa_s); - if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) && - wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) { + if (ft_completed) { + /* + * FT protocol completed - make sure EAPOL state machine ends + * up in authenticated. + */ + wpa_supplicant_cancel_auth_timeout(wpa_s); + wpa_supplicant_set_state(wpa_s, WPA_COMPLETED); + eapol_sm_notify_portValid(wpa_s->eapol, TRUE); + eapol_sm_notify_eap_success(wpa_s->eapol, TRUE); + } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) && + wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) { /* * We are done; the driver will take care of RSN 4-way * handshake. @@ -2372,7 +2880,7 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s, wpa_supplicant_set_state(wpa_s, WPA_COMPLETED); eapol_sm_notify_portValid(wpa_s->eapol, TRUE); eapol_sm_notify_eap_success(wpa_s->eapol, TRUE); - } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) && + } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X) && wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) { /* * The driver will take care of RSN 4-way handshake, so we need @@ -2380,15 +2888,6 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s, * waiting for WPA supplicant. */ eapol_sm_notify_portValid(wpa_s->eapol, TRUE); - } else if (ft_completed) { - /* - * FT protocol completed - make sure EAPOL state machine ends - * up in authenticated. - */ - wpa_supplicant_cancel_auth_timeout(wpa_s); - wpa_supplicant_set_state(wpa_s, WPA_COMPLETED); - eapol_sm_notify_portValid(wpa_s->eapol, TRUE); - eapol_sm_notify_eap_success(wpa_s->eapol, TRUE); } wpa_s->last_eapol_matches_bssid = 0; @@ -2397,7 +2896,7 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s, struct os_reltime now, age; os_get_reltime(&now); os_reltime_sub(&now, &wpa_s->pending_eapol_rx_time, &age); - if (age.sec == 0 && age.usec < 100000 && + if (age.sec == 0 && age.usec < 200000 && os_memcmp(wpa_s->pending_eapol_rx_src, bssid, ETH_ALEN) == 0) { wpa_dbg(wpa_s, MSG_DEBUG, "Process pending EAPOL " @@ -2448,6 +2947,16 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s, if (wpa_s->reassoc_same_bss) wmm_ac_restore_tspecs(wpa_s); } + +#ifdef CONFIG_FILS + if (wpa_key_mgmt_fils(wpa_s->key_mgmt)) { + struct wpa_bss *bss = wpa_bss_get_bssid(wpa_s, bssid); + const u8 *fils_cache_id = wpa_bss_get_fils_cache_id(bss); + + if (fils_cache_id) + wpa_sm_set_fils_cache_id(wpa_s->wpa, fils_cache_id); + } +#endif /* CONFIG_FILS */ } @@ -2624,7 +3133,7 @@ static void wpa_supplicant_event_disassoc_finish(struct wpa_supplicant *wpa_s, !disallowed_ssid(wpa_s, fast_reconnect->ssid, fast_reconnect->ssid_len) && !wpas_temp_disabled(wpa_s, fast_reconnect_ssid) && - !wpa_is_bss_tmp_disallowed(wpa_s, fast_reconnect->bssid)) { + !wpa_is_bss_tmp_disallowed(wpa_s, fast_reconnect)) { #ifndef CONFIG_NO_SCAN_PROCESSING wpa_dbg(wpa_s, MSG_DEBUG, "Try to reconnect to the same BSS"); if (wpa_supplicant_connect(wpa_s, fast_reconnect, @@ -2839,18 +3348,6 @@ wpa_supplicant_event_interface_status(struct wpa_supplicant *wpa_s, } -#ifdef CONFIG_PEERKEY -static void -wpa_supplicant_event_stkstart(struct wpa_supplicant *wpa_s, - union wpa_event_data *data) -{ - if (data == NULL) - return; - wpa_sm_stkstart(wpa_s->wpa, data->stkstart.peer); -} -#endif /* CONFIG_PEERKEY */ - - #ifdef CONFIG_TDLS static void wpa_supplicant_event_tdls(struct wpa_supplicant *wpa_s, union wpa_event_data *data) @@ -3209,10 +3706,11 @@ static const char * reg_type_str(enum reg_type type) } -static void wpa_supplicant_update_channel_list( - struct wpa_supplicant *wpa_s, struct channel_list_changed *info) +void wpa_supplicant_update_channel_list(struct wpa_supplicant *wpa_s, + struct channel_list_changed *info) { struct wpa_supplicant *ifs; + u8 dfs_domain; /* * To allow backwards compatibility with higher level layers that @@ -3223,10 +3721,13 @@ static void wpa_supplicant_update_channel_list( for (ifs = wpa_s; ifs->parent && ifs != ifs->parent; ifs = ifs->parent) ; - wpa_msg(ifs, MSG_INFO, WPA_EVENT_REGDOM_CHANGE "init=%s type=%s%s%s", - reg_init_str(info->initiator), reg_type_str(info->type), - info->alpha2[0] ? " alpha2=" : "", - info->alpha2[0] ? info->alpha2 : ""); + if (info) { + wpa_msg(ifs, MSG_INFO, + WPA_EVENT_REGDOM_CHANGE "init=%s type=%s%s%s", + reg_init_str(info->initiator), reg_type_str(info->type), + info->alpha2[0] ? " alpha2=" : "", + info->alpha2[0] ? info->alpha2 : ""); + } if (wpa_s->drv_priv == NULL) return; /* Ignore event during drv initialization */ @@ -3237,7 +3738,7 @@ static void wpa_supplicant_update_channel_list( ifs->ifname); free_hw_features(ifs); ifs->hw.modes = wpa_drv_get_hw_feature_data( - ifs, &ifs->hw.num_modes, &ifs->hw.flags); + ifs, &ifs->hw.num_modes, &ifs->hw.flags, &dfs_domain); /* Restart PNO/sched_scan with updated channel list */ if (ifs->pno) { @@ -3312,6 +3813,15 @@ static void wpas_event_rx_mgmt_action(struct wpa_supplicant *wpa_s, return; #endif /* CONFIG_GAS */ +#ifdef CONFIG_GAS_SERVER + if ((mgmt->u.action.category == WLAN_ACTION_PUBLIC || + mgmt->u.action.category == WLAN_ACTION_PROTECTED_DUAL) && + gas_server_rx(wpa_s->gas_server, mgmt->da, mgmt->sa, mgmt->bssid, + mgmt->u.action.category, + payload, plen, freq) == 0) + return; +#endif /* CONFIG_GAS_SERVER */ + #ifdef CONFIG_TDLS if (category == WLAN_ACTION_PUBLIC && plen >= 4 && payload[0] == WLAN_TDLS_DISCOVERY_RESPONSE) { @@ -3340,6 +3850,7 @@ static void wpas_event_rx_mgmt_action(struct wpa_supplicant *wpa_s, if (category == WLAN_ACTION_RADIO_MEASUREMENT && payload[0] == WLAN_RRM_RADIO_MEASUREMENT_REQUEST) { wpas_rrm_handle_radio_measurement_request(wpa_s, mgmt->sa, + mgmt->da, payload + 1, plen - 1); return; @@ -3366,6 +3877,18 @@ static void wpas_event_rx_mgmt_action(struct wpa_supplicant *wpa_s, } #endif /* CONFIG_FST */ +#ifdef CONFIG_DPP + if (category == WLAN_ACTION_PUBLIC && plen >= 5 && + payload[0] == WLAN_PA_VENDOR_SPECIFIC && + WPA_GET_BE24(&payload[1]) == OUI_WFA && + payload[4] == DPP_OUI_TYPE) { + payload++; + plen--; + wpas_dpp_rx_action(wpa_s, mgmt->sa, payload, plen, freq); + return; + } +#endif /* CONFIG_DPP */ + wpas_p2p_rx_action(wpa_s, mgmt->da, mgmt->sa, mgmt->bssid, category, payload, plen, freq); if (wpa_s->ifmsh) @@ -3406,23 +3929,252 @@ static void wpa_supplicant_notify_avoid_freq(struct wpa_supplicant *wpa_s, } -static void wpa_supplicant_event_assoc_auth(struct wpa_supplicant *wpa_s, - union wpa_event_data *data) +static void wpa_supplicant_event_port_authorized(struct wpa_supplicant *wpa_s) { - wpa_dbg(wpa_s, MSG_DEBUG, - "Connection authorized by device, previous state %d", - wpa_s->wpa_state); if (wpa_s->wpa_state == WPA_ASSOCIATED) { wpa_supplicant_cancel_auth_timeout(wpa_s); wpa_supplicant_set_state(wpa_s, WPA_COMPLETED); eapol_sm_notify_portValid(wpa_s->eapol, TRUE); eapol_sm_notify_eap_success(wpa_s->eapol, TRUE); } +} + + +static unsigned int wpas_event_cac_ms(const struct wpa_supplicant *wpa_s, + int freq) +{ + size_t i; + int j; + + for (i = 0; i < wpa_s->hw.num_modes; i++) { + const struct hostapd_hw_modes *mode = &wpa_s->hw.modes[i]; + + for (j = 0; j < mode->num_channels; j++) { + const struct hostapd_channel_data *chan; + + chan = &mode->channels[j]; + if (chan->freq == freq) + return chan->dfs_cac_ms; + } + } + + return 0; +} + + +static void wpas_event_dfs_cac_started(struct wpa_supplicant *wpa_s, + struct dfs_event *radar) +{ +#if defined(NEED_AP_MLME) && defined(CONFIG_AP) + if (wpa_s->ap_iface || wpa_s->ifmsh) { + wpas_ap_event_dfs_cac_started(wpa_s, radar); + } else +#endif /* NEED_AP_MLME && CONFIG_AP */ + { + unsigned int cac_time = wpas_event_cac_ms(wpa_s, radar->freq); + + cac_time /= 1000; /* convert from ms to sec */ + if (!cac_time) + cac_time = 10 * 60; /* max timeout: 10 minutes */ + + /* Restart auth timeout: CAC time added to initial timeout */ + wpas_auth_timeout_restart(wpa_s, cac_time); + } +} + + +static void wpas_event_dfs_cac_finished(struct wpa_supplicant *wpa_s, + struct dfs_event *radar) +{ +#if defined(NEED_AP_MLME) && defined(CONFIG_AP) + if (wpa_s->ap_iface || wpa_s->ifmsh) { + wpas_ap_event_dfs_cac_finished(wpa_s, radar); + } else +#endif /* NEED_AP_MLME && CONFIG_AP */ + { + /* Restart auth timeout with original value after CAC is + * finished */ + wpas_auth_timeout_restart(wpa_s, 0); + } +} + + +static void wpas_event_dfs_cac_aborted(struct wpa_supplicant *wpa_s, + struct dfs_event *radar) +{ +#if defined(NEED_AP_MLME) && defined(CONFIG_AP) + if (wpa_s->ap_iface || wpa_s->ifmsh) { + wpas_ap_event_dfs_cac_aborted(wpa_s, radar); + } else +#endif /* NEED_AP_MLME && CONFIG_AP */ + { + /* Restart auth timeout with original value after CAC is + * aborted */ + wpas_auth_timeout_restart(wpa_s, 0); + } +} + + +static void wpa_supplicant_event_assoc_auth(struct wpa_supplicant *wpa_s, + union wpa_event_data *data) +{ + wpa_dbg(wpa_s, MSG_DEBUG, + "Connection authorized by device, previous state %d", + wpa_s->wpa_state); + + wpa_supplicant_event_port_authorized(wpa_s); + wpa_sm_set_rx_replay_ctr(wpa_s->wpa, data->assoc_info.key_replay_ctr); wpa_sm_set_ptk_kck_kek(wpa_s->wpa, data->assoc_info.ptk_kck, data->assoc_info.ptk_kck_len, data->assoc_info.ptk_kek, data->assoc_info.ptk_kek_len); +#ifdef CONFIG_FILS + if (wpa_s->auth_alg == WPA_AUTH_ALG_FILS) { + struct wpa_bss *bss = wpa_bss_get_bssid(wpa_s, wpa_s->bssid); + const u8 *fils_cache_id = wpa_bss_get_fils_cache_id(bss); + + /* Update ERP next sequence number */ + eapol_sm_update_erp_next_seq_num( + wpa_s->eapol, data->assoc_info.fils_erp_next_seq_num); + + if (data->assoc_info.fils_pmk && data->assoc_info.fils_pmkid) { + /* Add the new PMK and PMKID to the PMKSA cache */ + wpa_sm_pmksa_cache_add(wpa_s->wpa, + data->assoc_info.fils_pmk, + data->assoc_info.fils_pmk_len, + data->assoc_info.fils_pmkid, + wpa_s->bssid, fils_cache_id); + } else if (data->assoc_info.fils_pmkid) { + /* Update the current PMKSA used for this connection */ + pmksa_cache_set_current(wpa_s->wpa, + data->assoc_info.fils_pmkid, + NULL, NULL, 0, NULL, 0); + } + } +#endif /* CONFIG_FILS */ +} + + +static void wpas_event_assoc_reject(struct wpa_supplicant *wpa_s, + union wpa_event_data *data) +{ + const u8 *bssid = data->assoc_reject.bssid; + + if (!bssid || is_zero_ether_addr(bssid)) + bssid = wpa_s->pending_bssid; + + if (data->assoc_reject.bssid) + wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_ASSOC_REJECT + "bssid=" MACSTR " status_code=%u%s%s%s", + MAC2STR(data->assoc_reject.bssid), + data->assoc_reject.status_code, + data->assoc_reject.timed_out ? " timeout" : "", + data->assoc_reject.timeout_reason ? "=" : "", + data->assoc_reject.timeout_reason ? + data->assoc_reject.timeout_reason : ""); + else + wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_ASSOC_REJECT + "status_code=%u%s%s%s", + data->assoc_reject.status_code, + data->assoc_reject.timed_out ? " timeout" : "", + data->assoc_reject.timeout_reason ? "=" : "", + data->assoc_reject.timeout_reason ? + data->assoc_reject.timeout_reason : ""); + wpa_s->assoc_status_code = data->assoc_reject.status_code; + wpas_notify_assoc_status_code(wpa_s); + +#ifdef CONFIG_OWE + if (data->assoc_reject.status_code == + WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED && + wpa_s->key_mgmt == WPA_KEY_MGMT_OWE && + wpa_s->current_ssid && + wpa_s->current_ssid->owe_group == 0 && + wpa_s->last_owe_group != 21) { + struct wpa_ssid *ssid = wpa_s->current_ssid; + struct wpa_bss *bss = wpa_s->current_bss; + + if (!bss) { + bss = wpa_supplicant_get_new_bss(wpa_s, bssid); + if (!bss) { + wpas_connection_failed(wpa_s, bssid); + wpa_supplicant_mark_disassoc(wpa_s); + return; + } + } + wpa_printf(MSG_DEBUG, "OWE: Try next supported DH group"); + wpas_connect_work_done(wpa_s); + wpa_supplicant_mark_disassoc(wpa_s); + wpa_supplicant_connect(wpa_s, bss, ssid); + return; + } +#endif /* CONFIG_OWE */ + +#ifdef CONFIG_MBO + if (data->assoc_reject.status_code == + WLAN_STATUS_DENIED_POOR_CHANNEL_CONDITIONS && + wpa_s->current_bss && data->assoc_reject.bssid && + data->assoc_reject.resp_ies) { + const u8 *rssi_rej; + + rssi_rej = mbo_get_attr_from_ies( + data->assoc_reject.resp_ies, + data->assoc_reject.resp_ies_len, + OCE_ATTR_ID_RSSI_BASED_ASSOC_REJECT); + if (rssi_rej && rssi_rej[1] == 2) { + wpa_printf(MSG_DEBUG, + "OCE: RSSI-based association rejection from " + MACSTR " (Delta RSSI: %u, Retry Delay: %u)", + MAC2STR(data->assoc_reject.bssid), + rssi_rej[2], rssi_rej[3]); + wpa_bss_tmp_disallow(wpa_s, + data->assoc_reject.bssid, + rssi_rej[3], + rssi_rej[2] + + wpa_s->current_bss->level); + } + } +#endif /* CONFIG_MBO */ + + if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) { + sme_event_assoc_reject(wpa_s, data); + return; + } + + /* Driver-based SME cases */ + +#ifdef CONFIG_SAE + if (wpa_s->current_ssid && + wpa_key_mgmt_sae(wpa_s->current_ssid->key_mgmt) && + !data->assoc_reject.timed_out) { + wpa_dbg(wpa_s, MSG_DEBUG, "SAE: Drop PMKSA cache entry"); + wpa_sm_aborted_cached(wpa_s->wpa); + wpa_sm_pmksa_cache_flush(wpa_s->wpa, wpa_s->current_ssid); + } +#endif /* CONFIG_SAE */ + +#ifdef CONFIG_DPP + if (wpa_s->current_ssid && + wpa_s->current_ssid->key_mgmt == WPA_KEY_MGMT_DPP && + !data->assoc_reject.timed_out) { + wpa_dbg(wpa_s, MSG_DEBUG, "DPP: Drop PMKSA cache entry"); + wpa_sm_aborted_cached(wpa_s->wpa); + wpa_sm_pmksa_cache_flush(wpa_s->wpa, wpa_s->current_ssid); + } +#endif /* CONFIG_DPP */ + +#ifdef CONFIG_FILS + /* Update ERP next sequence number */ + if (wpa_s->auth_alg == WPA_AUTH_ALG_FILS) { + eapol_sm_update_erp_next_seq_num( + wpa_s->eapol, + data->assoc_reject.fils_erp_next_seq_num); + fils_connection_failure(wpa_s); + } +#endif /* CONFIG_FILS */ + + wpas_connection_failed(wpa_s, bssid); + wpa_supplicant_mark_disassoc(wpa_s); } @@ -3431,6 +4183,9 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, { struct wpa_supplicant *wpa_s = ctx; int resched; +#ifndef CONFIG_NO_STDOUT_DEBUG + int level = MSG_DEBUG; +#endif /* CONFIG_NO_STDOUT_DEBUG */ if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED && event != EVENT_INTERFACE_ENABLED && @@ -3444,9 +4199,6 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, } #ifndef CONFIG_NO_STDOUT_DEBUG -{ - int level = MSG_DEBUG; - if (event == EVENT_RX_MGMT && data->rx_mgmt.frame_len >= 24) { const struct ieee80211_hdr *hdr; u16 fc; @@ -3459,7 +4211,6 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, wpa_dbg(wpa_s, level, "Event %s (%d) received", event_to_string(event), event); -} #endif /* CONFIG_NO_STDOUT_DEBUG */ switch (event) { @@ -3471,6 +4222,8 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, "FST: MB IEs updated from auth IE"); #endif /* CONFIG_FST */ sme_event_auth(wpa_s, data); + wpa_s->auth_status_code = data->auth.status_code; + wpas_notify_auth_status_code(wpa_s); break; case EVENT_ASSOC: #ifdef CONFIG_TESTING_OPTIONS @@ -3479,9 +4232,18 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, "EVENT_ASSOC - ignore_auth_resp active!"); break; } + if (wpa_s->testing_resend_assoc) { + wpa_printf(MSG_INFO, + "EVENT_DEAUTH - testing_resend_assoc"); + break; + } #endif /* CONFIG_TESTING_OPTIONS */ wpa_supplicant_event_assoc(wpa_s, data); - if (data && data->assoc_info.authorized) + wpa_s->assoc_status_code = WLAN_STATUS_SUCCESS; + if (data && + (data->assoc_info.authorized || + (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) && + wpa_fils_is_completed(wpa_s->wpa)))) wpa_supplicant_event_assoc_auth(wpa_s, data); if (data) { wpa_msg(wpa_s, MSG_INFO, @@ -3500,6 +4262,11 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, "EVENT_DEAUTH - ignore_auth_resp active!"); break; } + if (wpa_s->testing_resend_assoc) { + wpa_printf(MSG_INFO, + "EVENT_DEAUTH - testing_resend_assoc"); + break; + } #endif /* CONFIG_TESTING_OPTIONS */ wpas_event_deauth(wpa_s, data ? &data->deauth_info : NULL); @@ -3572,11 +4339,6 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, case EVENT_PMKID_CANDIDATE: wpa_supplicant_event_pmkid_candidate(wpa_s, data); break; -#ifdef CONFIG_PEERKEY - case EVENT_STKSTART: - wpa_supplicant_event_stkstart(wpa_s, data); - break; -#endif /* CONFIG_PEERKEY */ #ifdef CONFIG_TDLS case EVENT_TDLS: wpa_supplicant_event_tdls(wpa_s, data); @@ -3598,28 +4360,7 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, break; #endif /* CONFIG_IBSS_RSN */ case EVENT_ASSOC_REJECT: - if (data->assoc_reject.bssid) - wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_ASSOC_REJECT - "bssid=" MACSTR " status_code=%u%s", - MAC2STR(data->assoc_reject.bssid), - data->assoc_reject.status_code, - data->assoc_reject.timed_out ? " timeout" : ""); - else - wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_ASSOC_REJECT - "status_code=%u%s", - data->assoc_reject.status_code, - data->assoc_reject.timed_out ? " timeout" : ""); - wpa_s->assoc_status_code = data->assoc_reject.status_code; - wpas_notify_assoc_status_code(wpa_s); - if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) - sme_event_assoc_reject(wpa_s, data); - else { - const u8 *bssid = data->assoc_reject.bssid; - if (bssid == NULL || is_zero_ether_addr(bssid)) - bssid = wpa_s->pending_bssid; - wpas_connection_failed(wpa_s, bssid); - wpa_supplicant_mark_disassoc(wpa_s); - } + wpas_event_assoc_reject(wpa_s, data); break; case EVENT_AUTH_TIMED_OUT: /* It is possible to get this event from earlier connection */ @@ -3721,6 +4462,7 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, ap_rx_from_unknown_sta(wpa_s, data->rx_from_unknown.addr, data->rx_from_unknown.wds); break; +#endif /* CONFIG_AP */ case EVENT_CH_SWITCH: if (!data || !wpa_s->current_ssid) break; @@ -3737,8 +4479,10 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, wpa_s->assoc_freq = data->ch_switch.freq; wpa_s->current_ssid->frequency = data->ch_switch.freq; +#ifdef CONFIG_AP if (wpa_s->current_ssid->mode == WPAS_MODE_AP || wpa_s->current_ssid->mode == WPAS_MODE_P2P_GO || + wpa_s->current_ssid->mode == WPAS_MODE_MESH || wpa_s->current_ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) { wpas_ap_ch_switch(wpa_s, data->ch_switch.freq, @@ -3748,14 +4492,28 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, data->ch_switch.cf1, data->ch_switch.cf2); } +#endif /* CONFIG_AP */ +#ifdef CONFIG_IEEE80211W + sme_event_ch_switch(wpa_s); +#endif /* CONFIG_IEEE80211W */ wpas_p2p_update_channel_list(wpa_s, WPAS_P2P_CHANNEL_UPDATE_CS); + wnm_clear_coloc_intf_reporting(wpa_s); break; +#ifdef CONFIG_AP #ifdef NEED_AP_MLME case EVENT_DFS_RADAR_DETECTED: if (data) - wpas_event_dfs_radar_detected(wpa_s, &data->dfs_event); + wpas_ap_event_dfs_radar_detected(wpa_s, + &data->dfs_event); break; + case EVENT_DFS_NOP_FINISHED: + if (data) + wpas_ap_event_dfs_cac_nop_finished(wpa_s, + &data->dfs_event); + break; +#endif /* NEED_AP_MLME */ +#endif /* CONFIG_AP */ case EVENT_DFS_CAC_STARTED: if (data) wpas_event_dfs_cac_started(wpa_s, &data->dfs_event); @@ -3768,13 +4526,6 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, if (data) wpas_event_dfs_cac_aborted(wpa_s, &data->dfs_event); break; - case EVENT_DFS_NOP_FINISHED: - if (data) - wpas_event_dfs_cac_nop_finished(wpa_s, - &data->dfs_event); - break; -#endif /* NEED_AP_MLME */ -#endif /* CONFIG_AP */ case EVENT_RX_MGMT: { u16 fc, stype; const struct ieee80211_mgmt *mgmt; @@ -3846,6 +4597,16 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, break; } +#ifdef CONFIG_SAE + if (stype == WLAN_FC_STYPE_AUTH && + !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) && + (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE)) { + sme_external_auth_mgmt_rx( + wpa_s, data->rx_mgmt.frame, + data->rx_mgmt.frame_len); + break; + } +#endif /* CONFIG_SAE */ wpa_dbg(wpa_s, MSG_DEBUG, "AP: ignore received " "management frame in non-AP mode"); break; @@ -3910,6 +4671,10 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, #endif /* CONFIG_OFFCHANNEL */ wpas_p2p_cancel_remain_on_channel_cb( wpa_s, data->remain_on_channel.freq); +#ifdef CONFIG_DPP + wpas_dpp_cancel_remain_on_channel_cb( + wpa_s, data->remain_on_channel.freq); +#endif /* CONFIG_DPP */ break; case EVENT_EAPOL_RX: wpa_supplicant_rx_eapol(wpa_s, data->eapol_rx.src, @@ -3931,6 +4696,9 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, data->signal_change.current_noise, data->signal_change.current_txrate); break; + case EVENT_INTERFACE_MAC_CHANGED: + wpa_supplicant_update_mac_addr(wpa_s); + break; case EVENT_INTERFACE_ENABLED: wpa_dbg(wpa_s, MSG_DEBUG, "Interface was enabled"); if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) { @@ -4097,7 +4865,7 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, break; case EVENT_WPS_BUTTON_PUSHED: #ifdef CONFIG_WPS - wpas_wps_start_pbc(wpa_s, NULL, 0); + wpas_wps_start_pbc(wpa_s, NULL, 0, 0); #endif /* CONFIG_WPS */ break; case EVENT_AVOID_FREQUENCIES: @@ -4131,12 +4899,14 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, #endif /* CONFIG_AP */ break; case EVENT_ACS_CHANNEL_SELECTED: +#ifdef CONFIG_AP #ifdef CONFIG_ACS if (!wpa_s->ap_iface) break; hostapd_acs_channel_selected(wpa_s->ap_iface->bss[0], &data->acs_selected_channels); #endif /* CONFIG_ACS */ +#endif /* CONFIG_AP */ break; case EVENT_P2P_LO_STOP: #ifdef CONFIG_P2P @@ -4146,6 +4916,36 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, data->p2p_lo_stop.reason_code); #endif /* CONFIG_P2P */ break; + case EVENT_BEACON_LOSS: + if (!wpa_s->current_bss || !wpa_s->current_ssid) + break; + wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_BEACON_LOSS); + bgscan_notify_beacon_loss(wpa_s); + break; + case EVENT_EXTERNAL_AUTH: +#ifdef CONFIG_SAE + if (!wpa_s->current_ssid) { + wpa_printf(MSG_DEBUG, "SAE: current_ssid is NULL"); + break; + } + sme_external_auth_trigger(wpa_s, data); +#endif /* CONFIG_SAE */ + break; + case EVENT_PORT_AUTHORIZED: + wpa_supplicant_event_port_authorized(wpa_s); + break; + case EVENT_STATION_OPMODE_CHANGED: +#ifdef CONFIG_AP + if (!wpa_s->ap_iface || !data) + break; + + hostapd_event_sta_opmode_changed(wpa_s->ap_iface->bss[0], + data->sta_opmode.addr, + data->sta_opmode.smps_mode, + data->sta_opmode.chan_width, + data->sta_opmode.rx_nss); +#endif /* CONFIG_AP */ + break; default: wpa_msg(wpa_s, MSG_INFO, "Unknown event %d", event); break; diff --git a/freebsd/contrib/wpa/wpa_supplicant/gas_query.c b/freebsd/contrib/wpa/wpa_supplicant/gas_query.c index c099bc9a..73f02cbe 100644 --- a/freebsd/contrib/wpa/wpa_supplicant/gas_query.c +++ b/freebsd/contrib/wpa/wpa_supplicant/gas_query.c @@ -44,6 +44,7 @@ struct gas_query_pending { unsigned int wait_comeback:1; unsigned int offchannel_tx_started:1; unsigned int retry:1; + unsigned int wildcard_bssid:1; int freq; u16 status_code; struct wpabuf *req; @@ -55,6 +56,7 @@ struct gas_query_pending { const struct wpabuf *adv_proto, const struct wpabuf *resp, u16 status_code); void *ctx; + u8 sa[ETH_ALEN]; }; /** @@ -65,6 +67,9 @@ struct gas_query { struct dl_list pending; /* struct gas_query_pending */ struct gas_query_pending *current; struct wpa_radio_work *work; + struct os_reltime last_mac_addr_rand; + int last_rand_sa_type; + u8 rand_addr[ETH_ALEN]; }; @@ -119,6 +124,8 @@ static const char * gas_result_txt(enum gas_query_result result) return "PEER_ERROR"; case GAS_QUERY_INTERNAL_ERROR: return "INTERNAL_ERROR"; + case GAS_QUERY_STOPPED: + return "STOPPED"; case GAS_QUERY_DELETED_AT_DEINIT: return "DELETED_AT_DEINIT"; } @@ -241,10 +248,17 @@ static void gas_query_tx_status(struct wpa_supplicant *wpa_s, } os_get_reltime(&query->last_oper); - if (result == OFFCHANNEL_SEND_ACTION_SUCCESS) { + if (result == OFFCHANNEL_SEND_ACTION_SUCCESS || + result == OFFCHANNEL_SEND_ACTION_NO_ACK) { eloop_cancel_timeout(gas_query_timeout, gas, query); - eloop_register_timeout(GAS_QUERY_TIMEOUT_PERIOD, 0, - gas_query_timeout, gas, query); + if (result == OFFCHANNEL_SEND_ACTION_NO_ACK) { + wpa_printf(MSG_DEBUG, "GAS: No ACK to GAS request"); + eloop_register_timeout(0, 250000, + gas_query_timeout, gas, query); + } else { + eloop_register_timeout(GAS_QUERY_TIMEOUT_PERIOD, 0, + gas_query_timeout, gas, query); + } if (query->wait_comeback && !query->retry) { eloop_cancel_timeout(gas_query_rx_comeback_timeout, gas, query); @@ -260,7 +274,7 @@ static void gas_query_tx_status(struct wpa_supplicant *wpa_s, } -static int pmf_in_use(struct wpa_supplicant *wpa_s, const u8 *addr) +int pmf_in_use(struct wpa_supplicant *wpa_s, const u8 *addr) { if (wpa_s->current_ssid == NULL || wpa_s->wpa_state < WPA_4WAY_HANDSHAKE || @@ -280,8 +294,9 @@ static int gas_query_tx(struct gas_query *gas, struct gas_query_pending *query, }; wpa_printf(MSG_DEBUG, "GAS: Send action frame to " MACSTR " len=%u " - "freq=%d prot=%d", MAC2STR(query->addr), - (unsigned int) wpabuf_len(req), query->freq, prot); + "freq=%d prot=%d using src addr " MACSTR, + MAC2STR(query->addr), (unsigned int) wpabuf_len(req), + query->freq, prot, MAC2STR(query->sa)); if (prot) { u8 *categ = wpabuf_mhead_u8(req); *categ = WLAN_ACTION_PROTECTED_DUAL; @@ -290,17 +305,20 @@ static int gas_query_tx(struct gas_query *gas, struct gas_query_pending *query, if (gas->wpa_s->max_remain_on_chan && wait_time > gas->wpa_s->max_remain_on_chan) wait_time = gas->wpa_s->max_remain_on_chan; - if (!gas->wpa_s->conf->gas_address3 || - (gas->wpa_s->current_ssid && - gas->wpa_s->wpa_state >= WPA_ASSOCIATED && - os_memcmp(query->addr, gas->wpa_s->bssid, ETH_ALEN) == 0)) + if (!query->wildcard_bssid && + (!gas->wpa_s->conf->gas_address3 || + (gas->wpa_s->current_ssid && + gas->wpa_s->wpa_state >= WPA_ASSOCIATED && + os_memcmp(query->addr, gas->wpa_s->bssid, ETH_ALEN) == 0))) bssid = query->addr; else bssid = wildcard_bssid; + res = offchannel_send_action(gas->wpa_s, query->freq, query->addr, - gas->wpa_s->own_addr, bssid, - wpabuf_head(req), wpabuf_len(req), - wait_time, gas_query_tx_status, 0); + query->sa, bssid, wpabuf_head(req), + wpabuf_len(req), wait_time, + gas_query_tx_status, 0); + if (res == 0) query->offchannel_tx_started = 1; return res; @@ -409,6 +427,7 @@ static void gas_query_rx_initial(struct gas_query *gas, } if (comeback_delay) { + eloop_cancel_timeout(gas_query_timeout, gas, query); query->wait_comeback = 1; gas_query_tx_comeback_req_delay(gas, query, comeback_delay); return; @@ -726,6 +745,58 @@ static int gas_query_new_dialog_token(struct gas_query *gas, const u8 *dst) } +static int gas_query_set_sa(struct gas_query *gas, + struct gas_query_pending *query) +{ + struct wpa_supplicant *wpa_s = gas->wpa_s; + struct os_reltime now; + + if (!wpa_s->conf->gas_rand_mac_addr || + !(wpa_s->current_bss ? + (wpa_s->drv_flags & + WPA_DRIVER_FLAGS_MGMT_TX_RANDOM_TA_CONNECTED) : + (wpa_s->drv_flags & WPA_DRIVER_FLAGS_MGMT_TX_RANDOM_TA))) { + /* Use own MAC address as the transmitter address */ + os_memcpy(query->sa, wpa_s->own_addr, ETH_ALEN); + return 0; + } + + os_get_reltime(&now); + + if (wpa_s->conf->gas_rand_mac_addr == gas->last_rand_sa_type && + gas->last_mac_addr_rand.sec != 0 && + !os_reltime_expired(&now, &gas->last_mac_addr_rand, + wpa_s->conf->gas_rand_addr_lifetime)) { + wpa_printf(MSG_DEBUG, + "GAS: Use the previously selected random transmitter address " + MACSTR, MAC2STR(gas->rand_addr)); + os_memcpy(query->sa, gas->rand_addr, ETH_ALEN); + return 0; + } + + if (wpa_s->conf->gas_rand_mac_addr == 1 && + random_mac_addr(gas->rand_addr) < 0) { + wpa_printf(MSG_ERROR, "GAS: Failed to get random address"); + return -1; + } + + if (wpa_s->conf->gas_rand_mac_addr == 2 && + random_mac_addr_keep_oui(gas->rand_addr) < 0) { + wpa_printf(MSG_ERROR, + "GAS: Failed to get random address with same OUI"); + return -1; + } + + wpa_printf(MSG_DEBUG, "GAS: Use a new random transmitter address " + MACSTR, MAC2STR(gas->rand_addr)); + os_memcpy(query->sa, gas->rand_addr, ETH_ALEN); + os_get_reltime(&gas->last_mac_addr_rand); + gas->last_rand_sa_type = wpa_s->conf->gas_rand_mac_addr; + + return 0; +} + + /** * gas_query_req - Request a GAS query * @gas: GAS query data from gas_query_init() @@ -738,7 +809,7 @@ static int gas_query_new_dialog_token(struct gas_query *gas, const u8 *dst) * Returns: dialog token (>= 0) on success or -1 on failure */ int gas_query_req(struct gas_query *gas, const u8 *dst, int freq, - struct wpabuf *req, + int wildcard_bssid, struct wpabuf *req, void (*cb)(void *ctx, const u8 *dst, u8 dialog_token, enum gas_query_result result, const struct wpabuf *adv_proto, @@ -760,8 +831,13 @@ int gas_query_req(struct gas_query *gas, const u8 *dst, int freq, return -1; query->gas = gas; + if (gas_query_set_sa(gas, query)) { + os_free(query); + return -1; + } os_memcpy(query->addr, dst, ETH_ALEN); query->dialog_token = dialog_token; + query->wildcard_bssid = !!wildcard_bssid; query->freq = freq; query->cb = cb; query->ctx = ctx; @@ -783,3 +859,27 @@ int gas_query_req(struct gas_query *gas, const u8 *dst, int freq, return dialog_token; } + + +int gas_query_stop(struct gas_query *gas, u8 dialog_token) +{ + struct gas_query_pending *query; + + dl_list_for_each(query, &gas->pending, struct gas_query_pending, list) { + if (query->dialog_token == dialog_token) { + if (!gas->work) { + /* The pending radio work has not yet been + * started, but the pending entry has a + * reference to the soon to be freed query. + * Need to remove that radio work now to avoid + * leaving behind a reference to freed memory. + */ + radio_remove_pending_work(gas->wpa_s, query); + } + gas_query_done(gas, query, GAS_QUERY_STOPPED); + return 0; + } + } + + return -1; +} diff --git a/freebsd/contrib/wpa/wpa_supplicant/gas_query.h b/freebsd/contrib/wpa/wpa_supplicant/gas_query.h index ef82097e..d2b45544 100644 --- a/freebsd/contrib/wpa/wpa_supplicant/gas_query.h +++ b/freebsd/contrib/wpa/wpa_supplicant/gas_query.h @@ -19,6 +19,7 @@ void gas_query_deinit(struct gas_query *gas); int gas_query_rx(struct gas_query *gas, const u8 *da, const u8 *sa, const u8 *bssid, u8 categ, const u8 *data, size_t len, int freq); +int pmf_in_use(struct wpa_supplicant *wpa_s, const u8 *addr); /** * enum gas_query_result - GAS query result @@ -29,16 +30,18 @@ enum gas_query_result { GAS_QUERY_TIMEOUT, GAS_QUERY_PEER_ERROR, GAS_QUERY_INTERNAL_ERROR, + GAS_QUERY_STOPPED, GAS_QUERY_DELETED_AT_DEINIT }; int gas_query_req(struct gas_query *gas, const u8 *dst, int freq, - struct wpabuf *req, + int wildcard_bssid, struct wpabuf *req, void (*cb)(void *ctx, const u8 *dst, u8 dialog_token, enum gas_query_result result, const struct wpabuf *adv_proto, const struct wpabuf *resp, u16 status_code), void *ctx); +int gas_query_stop(struct gas_query *gas, u8 dialog_token); #else /* CONFIG_GAS */ diff --git a/freebsd/contrib/wpa/wpa_supplicant/hs20_supplicant.c b/freebsd/contrib/wpa/wpa_supplicant/hs20_supplicant.c index 44be415a..eb085c0d 100644 --- a/freebsd/contrib/wpa/wpa_supplicant/hs20_supplicant.c +++ b/freebsd/contrib/wpa/wpa_supplicant/hs20_supplicant.c @@ -51,9 +51,12 @@ struct osu_provider { u8 bssid[ETH_ALEN]; u8 osu_ssid[SSID_MAX_LEN]; u8 osu_ssid_len; + u8 osu_ssid2[SSID_MAX_LEN]; + u8 osu_ssid2_len; char server_uri[256]; u32 osu_methods; /* bit 0 = OMA-DM, bit 1 = SOAP-XML SPP */ char osu_nai[256]; + char osu_nai2[256]; struct osu_lang_string friendly_name[OSU_MAX_ITEMS]; size_t friendly_name_count; struct osu_lang_string serv_desc[OSU_MAX_ITEMS]; @@ -94,8 +97,7 @@ void hs20_configure_frame_filters(struct wpa_supplicant *wpa_s) return; } - /* Check if Proxy ARP is enabled (2nd byte in the IE) */ - if (ext_capa[3] & BIT(4)) + if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_PROXY_ARP)) filter |= WPA_DATA_FRAME_FILTER_FLAG_ARP | WPA_DATA_FRAME_FILTER_FLAG_NA; @@ -103,15 +105,22 @@ void hs20_configure_frame_filters(struct wpa_supplicant *wpa_s) } -void wpas_hs20_add_indication(struct wpabuf *buf, int pps_mo_id) +void wpas_hs20_add_indication(struct wpabuf *buf, int pps_mo_id, int ap_release) { + int release; u8 conf; + release = (HS20_VERSION >> 4) + 1; + if (ap_release > 0 && release > ap_release) + release = ap_release; + if (release < 2) + pps_mo_id = -1; + wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC); wpabuf_put_u8(buf, pps_mo_id >= 0 ? 7 : 5); wpabuf_put_be24(buf, OUI_WFA); wpabuf_put_u8(buf, HS20_INDICATION_OUI_TYPE); - conf = HS20_VERSION; + conf = (release - 1) << 4; if (pps_mo_id >= 0) conf |= HS20_PPS_MO_ID_PRESENT; wpabuf_put_u8(buf, conf); @@ -120,6 +129,37 @@ void wpas_hs20_add_indication(struct wpabuf *buf, int pps_mo_id) } +void wpas_hs20_add_roam_cons_sel(struct wpabuf *buf, + const struct wpa_ssid *ssid) +{ + if (!ssid->roaming_consortium_selection || + !ssid->roaming_consortium_selection_len) + return; + + wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC); + wpabuf_put_u8(buf, 4 + ssid->roaming_consortium_selection_len); + wpabuf_put_be24(buf, OUI_WFA); + wpabuf_put_u8(buf, HS20_ROAMING_CONS_SEL_OUI_TYPE); + wpabuf_put_data(buf, ssid->roaming_consortium_selection, + ssid->roaming_consortium_selection_len); +} + + +int get_hs20_version(struct wpa_bss *bss) +{ + const u8 *ie; + + if (!bss) + return 0; + + ie = wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE); + if (!ie || ie[1] < 5) + return 0; + + return ((ie[6] >> 4) & 0x0f) + 1; +} + + int is_hs20_network(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, struct wpa_bss *bss) { @@ -250,7 +290,7 @@ int hs20_anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst, u32 stypes, if (buf == NULL) return -1; - res = gas_query_req(wpa_s->gas, dst, freq, buf, anqp_resp_cb, wpa_s); + res = gas_query_req(wpa_s->gas, dst, freq, 0, buf, anqp_resp_cb, wpa_s); if (res < 0) { wpa_printf(MSG_DEBUG, "ANQP: Failed to send Query Request"); wpabuf_free(buf); @@ -393,7 +433,7 @@ static void hs20_set_osu_access_permission(const char *osu_dir, return; } - if (chown(fname, statbuf.st_uid, statbuf.st_gid) < 0) { + if (lchown(fname, statbuf.st_uid, statbuf.st_gid) < 0) { wpa_printf(MSG_WARNING, "Cannot change the ownership for %s", fname); } @@ -431,10 +471,9 @@ static int hs20_process_icon_binary_file(struct wpa_supplicant *wpa_s, dl_list_for_each(icon, &wpa_s->icon_head, struct icon_entry, list) { if (icon->dialog_token == dialog_token && !icon->image && os_memcmp(icon->bssid, sa, ETH_ALEN) == 0) { - icon->image = os_malloc(slen); + icon->image = os_memdup(pos, slen); if (!icon->image) return -1; - os_memcpy(icon->image, pos, slen); icon->image_len = slen; hs20_remove_duplicate_icons(wpa_s, icon); wpa_msg(wpa_s, MSG_INFO, @@ -648,6 +687,25 @@ void hs20_parse_rx_hs20_anqp_resp(struct wpa_supplicant *wpa_s, wpa_s, NULL); } break; + case HS20_STYPE_OPERATOR_ICON_METADATA: + wpa_msg(wpa_s, MSG_INFO, RX_HS20_ANQP MACSTR + " Operator Icon Metadata", MAC2STR(sa)); + wpa_hexdump(MSG_DEBUG, "Operator Icon Metadata", pos, slen); + if (anqp) { + wpabuf_free(anqp->hs20_operator_icon_metadata); + anqp->hs20_operator_icon_metadata = + wpabuf_alloc_copy(pos, slen); + } + break; + case HS20_STYPE_OSU_PROVIDERS_NAI_LIST: + wpa_msg(wpa_s, MSG_INFO, RX_HS20_ANQP MACSTR + " OSU Providers NAI List", MAC2STR(sa)); + if (anqp) { + wpabuf_free(anqp->hs20_osu_providers_nai_list); + anqp->hs20_osu_providers_nai_list = + wpabuf_alloc_copy(pos, slen); + } + break; default: wpa_printf(MSG_DEBUG, "HS20: Unsupported subtype %u", subtype); break; @@ -727,8 +785,15 @@ static void hs20_osu_fetch_done(struct wpa_supplicant *wpa_s) wpa_ssid_txt(osu->osu_ssid, osu->osu_ssid_len)); } + if (osu->osu_ssid2_len) { + fprintf(f, "osu_ssid2=%s\n", + wpa_ssid_txt(osu->osu_ssid2, + osu->osu_ssid2_len)); + } if (osu->osu_nai[0]) fprintf(f, "osu_nai=%s\n", osu->osu_nai); + if (osu->osu_nai2[0]) + fprintf(f, "osu_nai2=%s\n", osu->osu_nai2); for (j = 0; j < osu->friendly_name_count; j++) { fprintf(f, "friendly_name=%s:%s\n", osu->friendly_name[j].lang, @@ -792,6 +857,7 @@ void hs20_next_osu_icon(struct wpa_supplicant *wpa_s) static void hs20_osu_add_prov(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, const u8 *osu_ssid, u8 osu_ssid_len, + const u8 *osu_ssid2, u8 osu_ssid2_len, const u8 *pos, size_t len) { struct osu_provider *prov; @@ -813,6 +879,9 @@ static void hs20_osu_add_prov(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, os_memcpy(prov->bssid, bss->bssid, ETH_ALEN); os_memcpy(prov->osu_ssid, osu_ssid, osu_ssid_len); prov->osu_ssid_len = osu_ssid_len; + if (osu_ssid2) + os_memcpy(prov->osu_ssid2, osu_ssid2, osu_ssid2_len); + prov->osu_ssid2_len = osu_ssid2_len; /* OSU Friendly Name Length */ if (end - pos < 2) { @@ -994,18 +1063,30 @@ void hs20_osu_icon_fetch(struct wpa_supplicant *wpa_s) struct wpabuf *prov_anqp; const u8 *pos, *end; u16 len; - const u8 *osu_ssid; - u8 osu_ssid_len; + const u8 *osu_ssid, *osu_ssid2; + u8 osu_ssid_len, osu_ssid2_len; u8 num_providers; hs20_free_osu_prov(wpa_s); dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) { + struct wpa_ie_data data; + const u8 *ie; + if (bss->anqp == NULL) continue; prov_anqp = bss->anqp->hs20_osu_providers_list; if (prov_anqp == NULL) continue; + ie = wpa_bss_get_ie(bss, WLAN_EID_RSN); + if (ie && wpa_parse_wpa_ie(ie, 2 + ie[1], &data) == 0 && + (data.key_mgmt & WPA_KEY_MGMT_OSEN)) { + osu_ssid2 = bss->ssid; + osu_ssid2_len = bss->ssid_len; + } else { + osu_ssid2 = NULL; + osu_ssid2_len = 0; + } wpa_printf(MSG_DEBUG, "HS 2.0: Parsing OSU Providers list from " MACSTR, MAC2STR(bss->bssid)); wpa_hexdump_buf(MSG_DEBUG, "HS 2.0: OSU Providers list", @@ -1047,7 +1128,8 @@ void hs20_osu_icon_fetch(struct wpa_supplicant *wpa_s) if (len > (unsigned int) (end - pos)) break; hs20_osu_add_prov(wpa_s, bss, osu_ssid, - osu_ssid_len, pos, len); + osu_ssid_len, osu_ssid2, + osu_ssid2_len, pos, len); pos += len; } @@ -1056,6 +1138,35 @@ void hs20_osu_icon_fetch(struct wpa_supplicant *wpa_s) "extra data after OSU Providers", (int) (end - pos)); } + + prov_anqp = bss->anqp->hs20_osu_providers_nai_list; + if (!prov_anqp) + continue; + wpa_printf(MSG_DEBUG, + "HS 2.0: Parsing OSU Providers NAI List from " + MACSTR, MAC2STR(bss->bssid)); + wpa_hexdump_buf(MSG_DEBUG, "HS 2.0: OSU Providers NAI List", + prov_anqp); + pos = wpabuf_head(prov_anqp); + end = pos + wpabuf_len(prov_anqp); + num_providers = 0; + while (end - pos > 0) { + len = *pos++; + if (end - pos < len) { + wpa_printf(MSG_DEBUG, + "HS 2.0: Not enough room for OSU_NAI"); + break; + } + if (num_providers >= wpa_s->osu_prov_count) { + wpa_printf(MSG_DEBUG, + "HS 2.0: Ignore unexpected OSU Provider NAI List entries"); + break; + } + os_memcpy(wpa_s->osu_prov[num_providers].osu_nai2, + pos, len); + pos += len; + num_providers++; + } } wpa_s->fetch_osu_icon_in_progress = 1; @@ -1209,6 +1320,18 @@ void hs20_rx_deauth_imminent_notice(struct wpa_supplicant *wpa_s, u8 code, } +void hs20_rx_t_c_acceptance(struct wpa_supplicant *wpa_s, const char *url) +{ + if (!wpa_sm_pmf_enabled(wpa_s->wpa)) { + wpa_printf(MSG_DEBUG, + "HS 2.0: Ignore Terms and Conditions Acceptance since PMF was not enabled"); + return; + } + + wpa_msg(wpa_s, MSG_INFO, HS20_T_C_ACCEPTANCE "%s", url); +} + + void hs20_init(struct wpa_supplicant *wpa_s) { dl_list_init(&wpa_s->icon_head); diff --git a/freebsd/contrib/wpa/wpa_supplicant/hs20_supplicant.h b/freebsd/contrib/wpa/wpa_supplicant/hs20_supplicant.h index 0dd559fd..e43414bc 100644 --- a/freebsd/contrib/wpa/wpa_supplicant/hs20_supplicant.h +++ b/freebsd/contrib/wpa/wpa_supplicant/hs20_supplicant.h @@ -9,7 +9,10 @@ #define HS20_SUPPLICANT_H void hs20_configure_frame_filters(struct wpa_supplicant *wpa_s); -void wpas_hs20_add_indication(struct wpabuf *buf, int pps_mo_id); +void wpas_hs20_add_indication(struct wpabuf *buf, int pps_mo_id, + int ap_release); +void wpas_hs20_add_roam_cons_sel(struct wpabuf *buf, + const struct wpa_ssid *ssid); int hs20_anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst, u32 stypes, const u8 *payload, size_t payload_len, int inmem); @@ -18,6 +21,7 @@ void hs20_put_anqp_req(u32 stypes, const u8 *payload, size_t payload_len, void hs20_parse_rx_hs20_anqp_resp(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, const u8 *sa, const u8 *data, size_t slen, u8 dialog_token); +int get_hs20_version(struct wpa_bss *bss); int is_hs20_network(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, struct wpa_bss *bss); int hs20_get_pps_mo_id(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid); @@ -27,6 +31,7 @@ void hs20_rx_subscription_remediation(struct wpa_supplicant *wpa_s, const char *url, u8 osu_method); void hs20_rx_deauth_imminent_notice(struct wpa_supplicant *wpa_s, u8 code, u16 reauth_delay, const char *url); +void hs20_rx_t_c_acceptance(struct wpa_supplicant *wpa_s, const char *url); void hs20_free_osu_prov(struct wpa_supplicant *wpa_s); void hs20_next_osu_icon(struct wpa_supplicant *wpa_s); diff --git a/freebsd/contrib/wpa/wpa_supplicant/interworking.c b/freebsd/contrib/wpa/wpa_supplicant/interworking.c index 89f9a9be..44829a66 100644 --- a/freebsd/contrib/wpa/wpa_supplicant/interworking.c +++ b/freebsd/contrib/wpa/wpa_supplicant/interworking.c @@ -108,10 +108,12 @@ static struct wpabuf * anqp_build_req(u16 info_ids[], size_t num_ids, if (buf == NULL) return NULL; - len_pos = gas_anqp_add_element(buf, ANQP_QUERY_LIST); - for (i = 0; i < num_ids; i++) - wpabuf_put_le16(buf, info_ids[i]); - gas_anqp_set_element_len(buf, len_pos); + if (num_ids > 0) { + len_pos = gas_anqp_add_element(buf, ANQP_QUERY_LIST); + for (i = 0; i < num_ids; i++) + wpabuf_put_le16(buf, info_ids[i]); + gas_anqp_set_element_len(buf, len_pos); + } if (extra) wpabuf_put_buf(buf, extra); @@ -148,6 +150,8 @@ static int cred_with_roaming_consortium(struct wpa_supplicant *wpa_s) return 1; if (cred->required_roaming_consortium_len) return 1; + if (cred->num_roaming_consortiums) + return 1; } return 0; } @@ -301,8 +305,10 @@ static int interworking_anqp_send_req(struct wpa_supplicant *wpa_s, wpabuf_put_u8(extra, HS20_STYPE_CONNECTION_CAPABILITY); if (all) wpabuf_put_u8(extra, HS20_STYPE_OPERATING_CLASS); - if (all) + if (all) { wpabuf_put_u8(extra, HS20_STYPE_OSU_PROVIDERS_LIST); + wpabuf_put_u8(extra, HS20_STYPE_OSU_PROVIDERS_NAI_LIST); + } gas_anqp_set_element_len(extra, len_pos); } #endif /* CONFIG_HS20 */ @@ -312,7 +318,7 @@ static int interworking_anqp_send_req(struct wpa_supplicant *wpa_s, if (buf == NULL) return -1; - res = gas_query_req(wpa_s->gas, bss->bssid, bss->freq, buf, + res = gas_query_req(wpa_s->gas, bss->bssid, bss->freq, 0, buf, interworking_anqp_resp_cb, wpa_s); if (res < 0) { wpa_msg(wpa_s, MSG_DEBUG, "ANQP: Failed to send Query Request"); @@ -954,6 +960,7 @@ static int interworking_set_hs20_params(struct wpa_supplicant *wpa_s, "WPA-EAP WPA-EAP-SHA256" : "WPA-EAP"; if (wpa_config_set(ssid, "key_mgmt", key_mgmt, 0) < 0 || wpa_config_set(ssid, "proto", "RSN", 0) < 0 || + wpa_config_set(ssid, "ieee80211w", "1", 0) < 0 || wpa_config_set(ssid, "pairwise", "CCMP", 0) < 0) return -1; return 0; @@ -1145,6 +1152,23 @@ static int roaming_consortium_match(const u8 *ie, const struct wpabuf *anqp, } +static int cred_roaming_consortiums_match(const u8 *ie, + const struct wpabuf *anqp, + const struct wpa_cred *cred) +{ + unsigned int i; + + for (i = 0; i < cred->num_roaming_consortiums; i++) { + if (roaming_consortium_match(ie, anqp, + cred->roaming_consortiums[i], + cred->roaming_consortiums_len[i])) + return 1; + } + + return 0; +} + + static int cred_no_required_oi_match(struct wpa_cred *cred, struct wpa_bss *bss) { const u8 *ie; @@ -1349,27 +1373,28 @@ static struct wpa_cred * interworking_credentials_available_roaming_consortium( { struct wpa_cred *cred, *selected = NULL; const u8 *ie; + const struct wpabuf *anqp; int is_excluded = 0; ie = wpa_bss_get_ie(bss, WLAN_EID_ROAMING_CONSORTIUM); + anqp = bss->anqp ? bss->anqp->roaming_consortium : NULL; - if (ie == NULL && - (bss->anqp == NULL || bss->anqp->roaming_consortium == NULL)) + if (!ie && !anqp) return NULL; if (wpa_s->conf->cred == NULL) return NULL; for (cred = wpa_s->conf->cred; cred; cred = cred->next) { - if (cred->roaming_consortium_len == 0) + if (cred->roaming_consortium_len == 0 && + cred->num_roaming_consortiums == 0) continue; - if (!roaming_consortium_match(ie, - bss->anqp ? - bss->anqp->roaming_consortium : - NULL, - cred->roaming_consortium, - cred->roaming_consortium_len)) + if ((cred->roaming_consortium_len == 0 || + !roaming_consortium_match(ie, anqp, + cred->roaming_consortium, + cred->roaming_consortium_len)) && + !cred_roaming_consortiums_match(ie, anqp, cred)) continue; if (cred_no_required_oi_match(cred, bss)) @@ -1535,6 +1560,9 @@ static int interworking_connect_roaming_consortium( struct wpa_bss *bss, int only_add) { struct wpa_ssid *ssid; + const u8 *ie; + const struct wpabuf *anqp; + unsigned int i; wpa_msg(wpa_s, MSG_DEBUG, "Interworking: Connect with " MACSTR " based on roaming consortium match", MAC2STR(bss->bssid)); @@ -1564,6 +1592,26 @@ static int interworking_connect_roaming_consortium( if (interworking_set_hs20_params(wpa_s, ssid) < 0) goto fail; + ie = wpa_bss_get_ie(bss, WLAN_EID_ROAMING_CONSORTIUM); + anqp = bss->anqp ? bss->anqp->roaming_consortium : NULL; + for (i = 0; (ie || anqp) && i < cred->num_roaming_consortiums; i++) { + if (!roaming_consortium_match( + ie, anqp, cred->roaming_consortiums[i], + cred->roaming_consortiums_len[i])) + continue; + + ssid->roaming_consortium_selection = + os_malloc(cred->roaming_consortiums_len[i]); + if (!ssid->roaming_consortium_selection) + goto fail; + os_memcpy(ssid->roaming_consortium_selection, + cred->roaming_consortiums[i], + cred->roaming_consortiums_len[i]); + ssid->roaming_consortium_selection_len = + cred->roaming_consortiums_len[i]; + break; + } + if (cred->eap_method == NULL) { wpa_msg(wpa_s, MSG_DEBUG, "Interworking: No EAP method set for credential using roaming consortium"); @@ -1771,9 +1819,10 @@ int interworking_connect(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, switch (eap->method) { case EAP_TYPE_TTLS: if (eap->inner_method) { - os_snprintf(buf, sizeof(buf), "\"autheap=%s\"", - eap_get_name(EAP_VENDOR_IETF, - eap->inner_method)); + name = eap_get_name(EAP_VENDOR_IETF, eap->inner_method); + if (!name) + goto fail; + os_snprintf(buf, sizeof(buf), "\"autheap=%s\"", name); if (wpa_config_set(ssid, "phase2", buf, 0) < 0) goto fail; break; @@ -1896,7 +1945,7 @@ static struct wpa_cred * interworking_credentials_available_3gpp( size_t len; wpa_msg(wpa_s, MSG_DEBUG, "Interworking: IMSI not available - try to read again through eap_proxy"); - wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, + wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, -1, wpa_s->imsi, &len); if (wpa_s->mnc_len > 0) { @@ -2532,7 +2581,8 @@ static void interworking_select_network(struct wpa_supplicant *wpa_s) wpa_msg(wpa_s, MSG_INFO, INTERWORKING_SELECTED MACSTR, MAC2STR(selected->bssid)); interworking_connect(wpa_s, selected, 0); - } + } else if (wpa_s->wpa_state == WPA_SCANNING) + wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); } @@ -2578,7 +2628,6 @@ static void interworking_next_anqp_fetch(struct wpa_supplicant *wpa_s) { struct wpa_bss *bss; int found = 0; - const u8 *ie; wpa_printf(MSG_DEBUG, "Interworking: next_anqp_fetch - " "fetch_anqp_in_progress=%d fetch_osu_icon_in_progress=%d", @@ -2601,8 +2650,7 @@ static void interworking_next_anqp_fetch(struct wpa_supplicant *wpa_s) dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) { if (!(bss->caps & IEEE80211_CAP_ESS)) continue; - ie = wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB); - if (ie == NULL || ie[1] < 4 || !(ie[5] & 0x80)) + if (!wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_INTERWORKING)) continue; /* AP does not support Interworking */ if (disallowed_bssid(wpa_s, bss->bssid) || disallowed_ssid(wpa_s, bss->ssid, bss->ssid_len)) @@ -2695,7 +2743,7 @@ void interworking_stop_fetch_anqp(struct wpa_supplicant *wpa_s) int anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst, u16 info_ids[], size_t num_ids, u32 subtypes, - int get_cell_pref) + u32 mbo_subtypes) { struct wpabuf *buf; struct wpabuf *extra_buf = NULL; @@ -2729,13 +2777,14 @@ int anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst, #endif /* CONFIG_HS20 */ #ifdef CONFIG_MBO - if (get_cell_pref) { + if (mbo_subtypes) { struct wpabuf *mbo; - mbo = mbo_build_anqp_buf(wpa_s, bss); + mbo = mbo_build_anqp_buf(wpa_s, bss, mbo_subtypes); if (mbo) { if (wpabuf_resize(&extra_buf, wpabuf_len(mbo))) { wpabuf_free(extra_buf); + wpabuf_free(mbo); return -1; } wpabuf_put_buf(extra_buf, mbo); @@ -2749,7 +2798,7 @@ int anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst, if (buf == NULL) return -1; - res = gas_query_req(wpa_s->gas, dst, freq, buf, anqp_resp_cb, wpa_s); + res = gas_query_req(wpa_s->gas, dst, freq, 0, buf, anqp_resp_cb, wpa_s); if (res < 0) { wpa_msg(wpa_s, MSG_DEBUG, "ANQP: Failed to send Query Request"); wpabuf_free(buf); @@ -2798,6 +2847,31 @@ static void anqp_add_extra(struct wpa_supplicant *wpa_s, } +static void interworking_parse_venue_url(struct wpa_supplicant *wpa_s, + const u8 *data, size_t len) +{ + const u8 *pos = data, *end = data + len; + char url[255]; + + while (end - pos >= 2) { + u8 slen, num; + + slen = *pos++; + if (slen < 1 || slen > end - pos) { + wpa_printf(MSG_DEBUG, + "ANQP: Truncated Venue URL Duple field"); + return; + } + + num = *pos++; + os_memcpy(url, pos, slen - 1); + url[slen - 1] = '\0'; + wpa_msg(wpa_s, MSG_INFO, RX_VENUE_URL "%u %s", num, url); + pos += slen - 1; + } +} + + static void interworking_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, const u8 *sa, u16 info_id, @@ -2806,9 +2880,7 @@ static void interworking_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s, { const u8 *pos = data; struct wpa_bss_anqp *anqp = NULL; -#ifdef CONFIG_HS20 u8 type; -#endif /* CONFIG_HS20 */ if (bss) anqp = bss->anqp; @@ -2894,12 +2966,35 @@ static void interworking_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s, anqp->domain_name = wpabuf_alloc_copy(pos, slen); } break; +#ifdef CONFIG_FILS + case ANQP_FILS_REALM_INFO: + wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR + " FILS Realm Information", MAC2STR(sa)); + wpa_hexdump_ascii(MSG_MSGDUMP, "ANQP: FILS Realm Information", + pos, slen); + if (anqp) { + wpabuf_free(anqp->fils_realm_info); + anqp->fils_realm_info = wpabuf_alloc_copy(pos, slen); + } + break; +#endif /* CONFIG_FILS */ + case ANQP_VENUE_URL: + wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR " Venue URL", + MAC2STR(sa)); + anqp_add_extra(wpa_s, anqp, info_id, pos, slen); + + if (!pmf_in_use(wpa_s, sa)) { + wpa_printf(MSG_DEBUG, + "ANQP: Ignore Venue URL since PMF was not enabled"); + break; + } + interworking_parse_venue_url(wpa_s, pos, slen); + break; case ANQP_VENDOR_SPECIFIC: if (slen < 3) return; switch (WPA_GET_BE24(pos)) { -#ifdef CONFIG_HS20 case OUI_WFA: pos += 3; slen -= 3; @@ -2910,19 +3005,26 @@ static void interworking_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s, slen--; switch (type) { +#ifdef CONFIG_HS20 case HS20_ANQP_OUI_TYPE: hs20_parse_rx_hs20_anqp_resp(wpa_s, bss, sa, pos, slen, dialog_token); break; +#endif /* CONFIG_HS20 */ +#ifdef CONFIG_MBO + case MBO_ANQP_OUI_TYPE: + mbo_parse_rx_anqp_resp(wpa_s, bss, sa, + pos, slen); + break; +#endif /* CONFIG_MBO */ default: wpa_msg(wpa_s, MSG_DEBUG, - "HS20: Unsupported ANQP vendor type %u", + "ANQP: Unsupported ANQP vendor type %u", type); break; } break; -#endif /* CONFIG_HS20 */ default: wpa_msg(wpa_s, MSG_DEBUG, "Interworking: Unsupported vendor-specific ANQP OUI %06x", @@ -3135,7 +3237,7 @@ int gas_send_request(struct wpa_supplicant *wpa_s, const u8 *dst, } else wpabuf_put_le16(buf, 0); - res = gas_query_req(wpa_s->gas, dst, freq, buf, gas_resp_cb, wpa_s); + res = gas_query_req(wpa_s->gas, dst, freq, 0, buf, gas_resp_cb, wpa_s); if (res < 0) { wpa_msg(wpa_s, MSG_DEBUG, "GAS: Failed to send Query Request"); wpabuf_free(buf); diff --git a/freebsd/contrib/wpa/wpa_supplicant/interworking.h b/freebsd/contrib/wpa/wpa_supplicant/interworking.h index 3d222926..37ee2e90 100644 --- a/freebsd/contrib/wpa/wpa_supplicant/interworking.h +++ b/freebsd/contrib/wpa/wpa_supplicant/interworking.h @@ -13,7 +13,7 @@ enum gas_query_result; int anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst, u16 info_ids[], size_t num_ids, u32 subtypes, - int get_cell_pref); + u32 mbo_subtypes); void anqp_resp_cb(void *ctx, const u8 *dst, u8 dialog_token, enum gas_query_result result, const struct wpabuf *adv_proto, diff --git a/freebsd/contrib/wpa/wpa_supplicant/main.c b/freebsd/contrib/wpa/wpa_supplicant/main.c index 99c86920..0bd79a1e 100644 --- a/freebsd/contrib/wpa/wpa_supplicant/main.c +++ b/freebsd/contrib/wpa/wpa_supplicant/main.c @@ -38,9 +38,9 @@ static void usage(void) "s" #endif /* CONFIG_DEBUG_SYSLOG */ "t" -#ifdef CONFIG_DBUS +#ifdef CONFIG_CTRL_IFACE_DBUS_NEW "u" -#endif /* CONFIG_DBUS */ +#endif /* CONFIG_CTRL_IFACE_DBUS_NEW */ "vW] [-P<pid file>] " "[-g<global ctrl>] \\\n" " [-G<group>] \\\n" @@ -108,9 +108,9 @@ static void usage(void) " -T = record to Linux tracing in addition to logging\n" " (records all messages regardless of debug verbosity)\n" #endif /* CONFIG_DEBUG_LINUX_TRACING */ -#ifdef CONFIG_DBUS +#ifdef CONFIG_CTRL_IFACE_DBUS_NEW " -u = enable DBus control interface\n" -#endif /* CONFIG_DBUS */ +#endif /* CONFIG_CTRL_IFACE_DBUS_NEW */ " -v = show version\n" " -W = wait for a control interface monitor before starting\n"); @@ -235,6 +235,11 @@ int main(int argc, char *argv[]) wpa_supplicant_fd_workaround(1); +#ifdef CONFIG_DRIVER_NDIS + void driver_ndis_init_ops(void); + driver_ndis_init_ops(); +#endif /* CONFIG_DRIVER_NDIS */ + for (;;) { c = getopt(argc, argv, "b:Bc:C:D:de:f:g:G:hi:I:KLMm:No:O:p:P:qsTtuvW"); @@ -331,11 +336,11 @@ int main(int argc, char *argv[]) case 't': params.wpa_debug_timestamp++; break; -#ifdef CONFIG_DBUS +#ifdef CONFIG_CTRL_IFACE_DBUS_NEW case 'u': params.dbus_ctrl_interface = 1; break; -#endif /* CONFIG_DBUS */ +#endif /* CONFIG_CTRL_IFACE_DBUS_NEW */ case 'v': printf("%s\n", wpa_supplicant_version); exitcode = 0; diff --git a/freebsd/contrib/wpa/wpa_supplicant/notify.c b/freebsd/contrib/wpa/wpa_supplicant/notify.c index 020a9a7b..c1fb8aed 100644 --- a/freebsd/contrib/wpa/wpa_supplicant/notify.c +++ b/freebsd/contrib/wpa/wpa_supplicant/notify.c @@ -17,7 +17,6 @@ #include "wps_supplicant.h" #include "binder/binder.h" #include "dbus/dbus_common.h" -#include "dbus/dbus_old.h" #include "dbus/dbus_new.h" #include "rsn_supp/wpa.h" #include "fst/fst.h" @@ -29,13 +28,13 @@ int wpas_notify_supplicant_initialized(struct wpa_global *global) { -#ifdef CONFIG_DBUS +#ifdef CONFIG_CTRL_IFACE_DBUS_NEW if (global->params.dbus_ctrl_interface) { global->dbus = wpas_dbus_init(global); if (global->dbus == NULL) return -1; } -#endif /* CONFIG_DBUS */ +#endif /* CONFIG_CTRL_IFACE_DBUS_NEW */ #ifdef CONFIG_BINDER global->binder = wpas_binder_init(global); @@ -49,10 +48,10 @@ int wpas_notify_supplicant_initialized(struct wpa_global *global) void wpas_notify_supplicant_deinitialized(struct wpa_global *global) { -#ifdef CONFIG_DBUS +#ifdef CONFIG_CTRL_IFACE_DBUS_NEW if (global->dbus) wpas_dbus_deinit(global->dbus); -#endif /* CONFIG_DBUS */ +#endif /* CONFIG_CTRL_IFACE_DBUS_NEW */ #ifdef CONFIG_BINDER if (global->binder) @@ -66,9 +65,6 @@ int wpas_notify_iface_added(struct wpa_supplicant *wpa_s) if (wpa_s->p2p_mgmt) return 0; - if (wpas_dbus_register_iface(wpa_s)) - return -1; - if (wpas_dbus_register_interface(wpa_s)) return -1; @@ -81,9 +77,6 @@ void wpas_notify_iface_removed(struct wpa_supplicant *wpa_s) if (wpa_s->p2p_mgmt) return; - /* unregister interface in old DBus ctrl iface */ - wpas_dbus_unregister_iface(wpa_s); - /* unregister interface in new DBus ctrl iface */ wpas_dbus_unregister_interface(wpa_s); } @@ -96,10 +89,6 @@ void wpas_notify_state_changed(struct wpa_supplicant *wpa_s, if (wpa_s->p2p_mgmt) return; - /* notify the old DBus API */ - wpa_supplicant_dbus_notify_state_change(wpa_s, new_state, - old_state); - /* notify the new DBus API */ wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_STATE); @@ -142,6 +131,15 @@ void wpas_notify_disconnect_reason(struct wpa_supplicant *wpa_s) } +void wpas_notify_auth_status_code(struct wpa_supplicant *wpa_s) +{ + if (wpa_s->p2p_mgmt) + return; + + wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_AUTH_STATUS_CODE); +} + + void wpas_notify_assoc_status_code(struct wpa_supplicant *wpa_s) { if (wpa_s->p2p_mgmt) @@ -151,6 +149,42 @@ void wpas_notify_assoc_status_code(struct wpa_supplicant *wpa_s) } +void wpas_notify_roam_time(struct wpa_supplicant *wpa_s) +{ + if (wpa_s->p2p_mgmt) + return; + + wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_ROAM_TIME); +} + + +void wpas_notify_roam_complete(struct wpa_supplicant *wpa_s) +{ + if (wpa_s->p2p_mgmt) + return; + + wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_ROAM_COMPLETE); +} + + +void wpas_notify_session_length(struct wpa_supplicant *wpa_s) +{ + if (wpa_s->p2p_mgmt) + return; + + wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_SESSION_LENGTH); +} + + +void wpas_notify_bss_tm_status(struct wpa_supplicant *wpa_s) +{ + if (wpa_s->p2p_mgmt) + return; + + wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_BSS_TM_STATUS); +} + + void wpas_notify_network_changed(struct wpa_supplicant *wpa_s) { if (wpa_s->p2p_mgmt) @@ -224,9 +258,6 @@ void wpas_notify_scanning(struct wpa_supplicant *wpa_s) if (wpa_s->p2p_mgmt) return; - /* notify the old DBus API */ - wpa_supplicant_dbus_notify_scanning(wpa_s); - /* notify the new DBus API */ wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_SCANNING); } @@ -246,9 +277,6 @@ void wpas_notify_scan_results(struct wpa_supplicant *wpa_s) if (wpa_s->p2p_mgmt) return; - /* notify the old DBus API */ - wpa_supplicant_dbus_notify_scan_results(wpa_s); - wpas_wps_notify_scan_results(wpa_s); } @@ -260,8 +288,6 @@ void wpas_notify_wps_credential(struct wpa_supplicant *wpa_s, return; #ifdef CONFIG_WPS - /* notify the old DBus API */ - wpa_supplicant_dbus_notify_wps_cred(wpa_s, cred); /* notify the new DBus API */ wpas_dbus_signal_wps_cred(wpa_s, cred); #endif /* CONFIG_WPS */ @@ -671,12 +697,12 @@ void wpas_notify_p2p_provision_discovery(struct wpa_supplicant *wpa_s, void wpas_notify_p2p_group_started(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, int persistent, - int client) + int client, const u8 *ip) { /* Notify a group has been started */ wpas_dbus_register_p2p_group(wpa_s, ssid); - wpas_dbus_signal_p2p_group_started(wpa_s, client, persistent); + wpas_dbus_signal_p2p_group_started(wpa_s, client, persistent, ip); } @@ -722,6 +748,9 @@ static void wpas_notify_ap_sta_authorized(struct wpa_supplicant *wpa_s, wpas_dbus_signal_p2p_peer_joined(wpa_s, p2p_dev_addr); #endif /* CONFIG_P2P */ + /* Register the station */ + wpas_dbus_register_sta(wpa_s, sta); + /* Notify listeners a new station has been authorized */ wpas_dbus_signal_sta_authorized(wpa_s, sta); } @@ -742,6 +771,9 @@ static void wpas_notify_ap_sta_deauthorized(struct wpa_supplicant *wpa_s, /* Notify listeners a station has been deauthorized */ wpas_dbus_signal_sta_deauthorized(wpa_s, sta); + + /* Unregister the station */ + wpas_dbus_unregister_sta(wpa_s, sta); } @@ -789,9 +821,6 @@ void wpas_notify_certification(struct wpa_supplicant *wpa_s, int depth, "depth=%d %s", depth, altsubject[i]); } - /* notify the old DBus API */ - wpa_supplicant_dbus_notify_certification(wpa_s, depth, subject, - cert_hash, cert); /* notify the new DBus API */ wpas_dbus_signal_certification(wpa_s, depth, subject, altsubject, num_altsubject, cert_hash, cert); @@ -818,6 +847,12 @@ void wpas_notify_eap_status(struct wpa_supplicant *wpa_s, const char *status, } +void wpas_notify_eap_error(struct wpa_supplicant *wpa_s, int error_code) +{ + wpa_msg(wpa_s, MSG_ERROR, WPA_EVENT_EAP_ERROR_CODE "%d", error_code); +} + + void wpas_notify_network_bssid_set_changed(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid) { @@ -852,3 +887,49 @@ void wpas_notify_network_type_changed(struct wpa_supplicant *wpa_s, } #endif /* CONFIG_P2P */ } + + +#ifdef CONFIG_MESH + +void wpas_notify_mesh_group_started(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid) +{ + if (wpa_s->p2p_mgmt) + return; + + wpas_dbus_signal_mesh_group_started(wpa_s, ssid); +} + + +void wpas_notify_mesh_group_removed(struct wpa_supplicant *wpa_s, + const u8 *meshid, u8 meshid_len, + int reason_code) +{ + if (wpa_s->p2p_mgmt) + return; + + wpas_dbus_signal_mesh_group_removed(wpa_s, meshid, meshid_len, + reason_code); +} + + +void wpas_notify_mesh_peer_connected(struct wpa_supplicant *wpa_s, + const u8 *peer_addr) +{ + if (wpa_s->p2p_mgmt) + return; + + wpas_dbus_signal_mesh_peer_connected(wpa_s, peer_addr); +} + + +void wpas_notify_mesh_peer_disconnected(struct wpa_supplicant *wpa_s, + const u8 *peer_addr, int reason_code) +{ + if (wpa_s->p2p_mgmt) + return; + + wpas_dbus_signal_mesh_peer_disconnected(wpa_s, peer_addr, reason_code); +} + +#endif /* CONFIG_MESH */ diff --git a/freebsd/contrib/wpa/wpa_supplicant/notify.h b/freebsd/contrib/wpa/wpa_supplicant/notify.h index 8cce0f30..65f513ea 100644 --- a/freebsd/contrib/wpa/wpa_supplicant/notify.h +++ b/freebsd/contrib/wpa/wpa_supplicant/notify.h @@ -23,7 +23,12 @@ void wpas_notify_state_changed(struct wpa_supplicant *wpa_s, enum wpa_states new_state, enum wpa_states old_state); void wpas_notify_disconnect_reason(struct wpa_supplicant *wpa_s); +void wpas_notify_auth_status_code(struct wpa_supplicant *wpa_s); void wpas_notify_assoc_status_code(struct wpa_supplicant *wpa_s); +void wpas_notify_roam_time(struct wpa_supplicant *wpa_s); +void wpas_notify_roam_complete(struct wpa_supplicant *wpa_s); +void wpas_notify_session_length(struct wpa_supplicant *wpa_s); +void wpas_notify_bss_tm_status(struct wpa_supplicant *wpa_s); void wpas_notify_network_changed(struct wpa_supplicant *wpa_s); void wpas_notify_ap_scan_changed(struct wpa_supplicant *wpa_s); void wpas_notify_bssid_changed(struct wpa_supplicant *wpa_s); @@ -114,7 +119,7 @@ void wpas_notify_p2p_provision_discovery(struct wpa_supplicant *wpa_s, unsigned int generated_pin); void wpas_notify_p2p_group_started(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, int persistent, - int client); + int client, const u8 *ip); void wpas_notify_p2p_group_formation_failure(struct wpa_supplicant *wpa_s, const char *reason); void wpas_notify_persistent_group_added(struct wpa_supplicant *wpa_s, @@ -134,6 +139,7 @@ void wpas_notify_preq(struct wpa_supplicant *wpa_s, const u8 *ie, size_t ie_len, u32 ssi_signal); void wpas_notify_eap_status(struct wpa_supplicant *wpa_s, const char *status, const char *parameter); +void wpas_notify_eap_error(struct wpa_supplicant *wpa_s, int error_code); void wpas_notify_network_bssid_set_changed(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid); void wpas_notify_network_type_changed(struct wpa_supplicant *wpa_s, @@ -141,5 +147,14 @@ void wpas_notify_network_type_changed(struct wpa_supplicant *wpa_s, void wpas_notify_p2p_invitation_received(struct wpa_supplicant *wpa_s, const u8 *sa, const u8 *go_dev_addr, const u8 *bssid, int id, int op_freq); +void wpas_notify_mesh_group_started(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid); +void wpas_notify_mesh_group_removed(struct wpa_supplicant *wpa_s, + const u8 *meshid, u8 meshid_len, + int reason_code); +void wpas_notify_mesh_peer_connected(struct wpa_supplicant *wpa_s, + const u8 *peer_addr); +void wpas_notify_mesh_peer_disconnected(struct wpa_supplicant *wpa_s, + const u8 *peer_addr, int reason_code); #endif /* NOTIFY_H */ diff --git a/freebsd/contrib/wpa/wpa_supplicant/offchannel.c b/freebsd/contrib/wpa/wpa_supplicant/offchannel.c index a269fdaf..fbf8ae12 100644 --- a/freebsd/contrib/wpa/wpa_supplicant/offchannel.c +++ b/freebsd/contrib/wpa/wpa_supplicant/offchannel.c @@ -312,6 +312,8 @@ int offchannel_send_action(struct wpa_supplicant *wpa_s, unsigned int freq, iface = wpas_get_tx_interface(wpa_s, src); wpa_s->action_tx_wait_time = wait_time; + if (wait_time) + wpa_s->action_tx_wait_time_used = 1; ret = wpa_drv_send_action( iface, wpa_s->pending_action_freq, @@ -400,13 +402,14 @@ void offchannel_send_action_done(struct wpa_supplicant *wpa_s) wpabuf_free(wpa_s->pending_action_tx); wpa_s->pending_action_tx = NULL; if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_TX && - wpa_s->action_tx_wait_time) + (wpa_s->action_tx_wait_time || wpa_s->action_tx_wait_time_used)) wpa_drv_send_action_cancel_wait(wpa_s); else if (wpa_s->off_channel_freq || wpa_s->roc_waiting_drv_freq) { wpa_drv_cancel_remain_on_channel(wpa_s); wpa_s->off_channel_freq = 0; wpa_s->roc_waiting_drv_freq = 0; } + wpa_s->action_tx_wait_time_used = 0; } diff --git a/freebsd/contrib/wpa/wpa_supplicant/op_classes.c b/freebsd/contrib/wpa/wpa_supplicant/op_classes.c new file mode 100644 index 00000000..8b517af7 --- /dev/null +++ b/freebsd/contrib/wpa/wpa_supplicant/op_classes.c @@ -0,0 +1,389 @@ +#include <machine/rtems-bsd-user-space.h> + +/* + * Operating classes + * Copyright(c) 2015 Intel Deutschland GmbH + * Contact Information: + * Intel Linux Wireless <ilw@linux.intel.com> + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "common/ieee802_11_common.h" +#include "wpa_supplicant_i.h" + + +static enum chan_allowed allow_channel(struct hostapd_hw_modes *mode, u8 chan, + unsigned int *flags) +{ + int i; + + for (i = 0; i < mode->num_channels; i++) { + if (mode->channels[i].chan == chan) + break; + } + + if (i == mode->num_channels || + (mode->channels[i].flag & HOSTAPD_CHAN_DISABLED)) + return NOT_ALLOWED; + + if (flags) + *flags = mode->channels[i].flag; + + if (mode->channels[i].flag & HOSTAPD_CHAN_NO_IR) + return NO_IR; + + return ALLOWED; +} + + +static int get_center_80mhz(struct hostapd_hw_modes *mode, u8 channel) +{ + u8 center_channels[] = { 42, 58, 106, 122, 138, 155 }; + size_t i; + + if (mode->mode != HOSTAPD_MODE_IEEE80211A) + return 0; + + for (i = 0; i < ARRAY_SIZE(center_channels); i++) { + /* + * In 80 MHz, the bandwidth "spans" 12 channels (e.g., 36-48), + * so the center channel is 6 channels away from the start/end. + */ + if (channel >= center_channels[i] - 6 && + channel <= center_channels[i] + 6) + return center_channels[i]; + } + + return 0; +} + + +static enum chan_allowed verify_80mhz(struct hostapd_hw_modes *mode, u8 channel) +{ + u8 center_chan; + unsigned int i; + unsigned int no_ir = 0; + + center_chan = get_center_80mhz(mode, channel); + if (!center_chan) + return NOT_ALLOWED; + + /* check all the channels are available */ + for (i = 0; i < 4; i++) { + unsigned int flags; + u8 adj_chan = center_chan - 6 + i * 4; + + if (allow_channel(mode, adj_chan, &flags) == NOT_ALLOWED) + return NOT_ALLOWED; + + if ((i == 0 && !(flags & HOSTAPD_CHAN_VHT_10_70)) || + (i == 1 && !(flags & HOSTAPD_CHAN_VHT_30_50)) || + (i == 2 && !(flags & HOSTAPD_CHAN_VHT_50_30)) || + (i == 3 && !(flags & HOSTAPD_CHAN_VHT_70_10))) + return NOT_ALLOWED; + + if (flags & HOSTAPD_CHAN_NO_IR) + no_ir = 1; + } + + if (no_ir) + return NO_IR; + + return ALLOWED; +} + + +static int get_center_160mhz(struct hostapd_hw_modes *mode, u8 channel) +{ + u8 center_channels[] = { 50, 114 }; + unsigned int i; + + if (mode->mode != HOSTAPD_MODE_IEEE80211A) + return 0; + + for (i = 0; i < ARRAY_SIZE(center_channels); i++) { + /* + * In 160 MHz, the bandwidth "spans" 28 channels (e.g., 36-64), + * so the center channel is 14 channels away from the start/end. + */ + if (channel >= center_channels[i] - 14 && + channel <= center_channels[i] + 14) + return center_channels[i]; + } + + return 0; +} + + +static enum chan_allowed verify_160mhz(struct hostapd_hw_modes *mode, + u8 channel) +{ + u8 center_chan; + unsigned int i; + unsigned int no_ir = 0; + + center_chan = get_center_160mhz(mode, channel); + if (!center_chan) + return NOT_ALLOWED; + + /* Check all the channels are available */ + for (i = 0; i < 8; i++) { + unsigned int flags; + u8 adj_chan = center_chan - 14 + i * 4; + + if (allow_channel(mode, adj_chan, &flags) == NOT_ALLOWED) + return NOT_ALLOWED; + + if ((i == 0 && !(flags & HOSTAPD_CHAN_VHT_10_150)) || + (i == 1 && !(flags & HOSTAPD_CHAN_VHT_30_130)) || + (i == 2 && !(flags & HOSTAPD_CHAN_VHT_50_110)) || + (i == 3 && !(flags & HOSTAPD_CHAN_VHT_70_90)) || + (i == 4 && !(flags & HOSTAPD_CHAN_VHT_90_70)) || + (i == 5 && !(flags & HOSTAPD_CHAN_VHT_110_50)) || + (i == 6 && !(flags & HOSTAPD_CHAN_VHT_130_30)) || + (i == 7 && !(flags & HOSTAPD_CHAN_VHT_150_10))) + return NOT_ALLOWED; + + if (flags & HOSTAPD_CHAN_NO_IR) + no_ir = 1; + } + + if (no_ir) + return NO_IR; + + return ALLOWED; +} + + +enum chan_allowed verify_channel(struct hostapd_hw_modes *mode, u8 channel, + u8 bw) +{ + unsigned int flag = 0; + enum chan_allowed res, res2; + + res2 = res = allow_channel(mode, channel, &flag); + if (bw == BW40MINUS) { + if (!(flag & HOSTAPD_CHAN_HT40MINUS)) + return NOT_ALLOWED; + res2 = allow_channel(mode, channel - 4, NULL); + } else if (bw == BW40PLUS) { + if (!(flag & HOSTAPD_CHAN_HT40PLUS)) + return NOT_ALLOWED; + res2 = allow_channel(mode, channel + 4, NULL); + } else if (bw == BW80) { + /* + * channel is a center channel and as such, not necessarily a + * valid 20 MHz channels. Override earlier allow_channel() + * result and use only the 80 MHz specific version. + */ + res2 = res = verify_80mhz(mode, channel); + } else if (bw == BW160) { + /* + * channel is a center channel and as such, not necessarily a + * valid 20 MHz channels. Override earlier allow_channel() + * result and use only the 160 MHz specific version. + */ + res2 = res = verify_160mhz(mode, channel); + } else if (bw == BW80P80) { + /* + * channel is a center channel and as such, not necessarily a + * valid 20 MHz channels. Override earlier allow_channel() + * result and use only the 80 MHz specific version. + */ + res2 = res = verify_80mhz(mode, channel); + } + + if (res == NOT_ALLOWED || res2 == NOT_ALLOWED) + return NOT_ALLOWED; + + if (res == NO_IR || res2 == NO_IR) + return NO_IR; + + return ALLOWED; +} + + +static int wpas_op_class_supported(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid, + const struct oper_class_map *op_class) +{ + int chan; + size_t i; + struct hostapd_hw_modes *mode; + int found; + int z; + int freq2 = 0; + int freq5 = 0; + + mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, op_class->mode); + if (!mode) + return 0; + + /* If we are configured to disable certain things, take that into + * account here. */ + if (ssid->freq_list && ssid->freq_list[0]) { + for (z = 0; ; z++) { + int f = ssid->freq_list[z]; + + if (f == 0) + break; /* end of list */ + if (f > 4000 && f < 6000) + freq5 = 1; + else if (f > 2400 && f < 2500) + freq2 = 1; + } + } else { + /* No frequencies specified, can use anything hardware supports. + */ + freq2 = freq5 = 1; + } + + if (op_class->op_class >= 115 && op_class->op_class <= 130 && !freq5) + return 0; + if (op_class->op_class >= 81 && op_class->op_class <= 84 && !freq2) + return 0; + +#ifdef CONFIG_HT_OVERRIDES + if (ssid->disable_ht) { + switch (op_class->op_class) { + case 83: + case 84: + case 104: + case 105: + case 116: + case 117: + case 119: + case 120: + case 122: + case 123: + case 126: + case 127: + case 128: + case 129: + case 130: + /* Disable >= 40 MHz channels if HT is disabled */ + return 0; + } + } +#endif /* CONFIG_HT_OVERRIDES */ + +#ifdef CONFIG_VHT_OVERRIDES + if (ssid->disable_vht) { + if (op_class->op_class >= 128 && op_class->op_class <= 130) { + /* Disable >= 80 MHz channels if VHT is disabled */ + return 0; + } + } +#endif /* CONFIG_VHT_OVERRIDES */ + + if (op_class->op_class == 128) { + u8 channels[] = { 42, 58, 106, 122, 138, 155 }; + + for (i = 0; i < ARRAY_SIZE(channels); i++) { + if (verify_channel(mode, channels[i], op_class->bw) != + NOT_ALLOWED) + return 1; + } + + return 0; + } + + if (op_class->op_class == 129) { + /* Check if either 160 MHz channels is allowed */ + return verify_channel(mode, 50, op_class->bw) != NOT_ALLOWED || + verify_channel(mode, 114, op_class->bw) != NOT_ALLOWED; + } + + if (op_class->op_class == 130) { + /* Need at least two non-contiguous 80 MHz segments */ + found = 0; + + if (verify_channel(mode, 42, op_class->bw) != NOT_ALLOWED || + verify_channel(mode, 58, op_class->bw) != NOT_ALLOWED) + found++; + if (verify_channel(mode, 106, op_class->bw) != NOT_ALLOWED || + verify_channel(mode, 122, op_class->bw) != NOT_ALLOWED || + verify_channel(mode, 138, op_class->bw) != NOT_ALLOWED) + found++; + if (verify_channel(mode, 106, op_class->bw) != NOT_ALLOWED && + verify_channel(mode, 138, op_class->bw) != NOT_ALLOWED) + found++; + if (verify_channel(mode, 155, op_class->bw) != NOT_ALLOWED) + found++; + + if (found >= 2) + return 1; + + return 0; + } + + found = 0; + for (chan = op_class->min_chan; chan <= op_class->max_chan; + chan += op_class->inc) { + if (verify_channel(mode, chan, op_class->bw) != NOT_ALLOWED) { + found = 1; + break; + } + } + + return found; +} + + +size_t wpas_supp_op_class_ie(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid, + int freq, u8 *pos, size_t len) +{ + struct wpabuf *buf; + u8 op, current, chan; + u8 *ie_len; + size_t res; + + /* + * Assume 20 MHz channel for now. + * TODO: Use the secondary channel and VHT channel width that will be + * used after association. + */ + if (ieee80211_freq_to_channel_ext(freq, 0, VHT_CHANWIDTH_USE_HT, + ¤t, &chan) == NUM_HOSTAPD_MODES) + return 0; + + /* + * Need 3 bytes for EID, length, and current operating class, plus + * 1 byte for every other supported operating class. + */ + buf = wpabuf_alloc(global_op_class_size + 3); + if (!buf) + return 0; + + wpabuf_put_u8(buf, WLAN_EID_SUPPORTED_OPERATING_CLASSES); + /* Will set the length later, putting a placeholder */ + ie_len = wpabuf_put(buf, 1); + wpabuf_put_u8(buf, current); + + for (op = 0; global_op_class[op].op_class; op++) { + if (wpas_op_class_supported(wpa_s, ssid, &global_op_class[op])) + wpabuf_put_u8(buf, global_op_class[op].op_class); + } + + *ie_len = wpabuf_len(buf) - 2; + if (*ie_len < 2 || wpabuf_len(buf) > len) { + wpa_printf(MSG_ERROR, + "Failed to add supported operating classes IE"); + res = 0; + } else { + os_memcpy(pos, wpabuf_head(buf), wpabuf_len(buf)); + res = wpabuf_len(buf); + wpa_hexdump_buf(MSG_DEBUG, + "Added supported operating classes IE", buf); + } + + wpabuf_free(buf); + return res; +} diff --git a/freebsd/contrib/wpa/wpa_supplicant/p2p_supplicant.h b/freebsd/contrib/wpa/wpa_supplicant/p2p_supplicant.h index 63910d1c..24ec2caf 100644 --- a/freebsd/contrib/wpa/wpa_supplicant/p2p_supplicant.h +++ b/freebsd/contrib/wpa/wpa_supplicant/p2p_supplicant.h @@ -37,18 +37,18 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr, int persistent_group, int auto_join, int join, int auth, int go_intent, int freq, unsigned int vht_center_freq2, int persistent_id, int pd, int ht40, int vht, - unsigned int vht_chwidth, const u8 *group_ssid, + unsigned int vht_chwidth, int he, const u8 *group_ssid, size_t group_ssid_len); int wpas_p2p_handle_frequency_conflicts(struct wpa_supplicant *wpa_s, int freq, struct wpa_ssid *ssid); int wpas_p2p_group_add(struct wpa_supplicant *wpa_s, int persistent_group, int freq, int vht_center_freq2, int ht40, int vht, - int max_oper_chwidth); + int max_oper_chwidth, int he); int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, int addr_allocated, int force_freq, int neg_freq, int vht_center_freq2, int ht40, - int vht, int max_oper_chwidth, + int vht, int max_oper_chwidth, int he, const struct p2p_channels *channels, int connection_timeout, int force_scan); struct p2p_group * wpas_p2p_group_init(struct wpa_supplicant *wpa_s, @@ -117,7 +117,7 @@ int wpas_p2p_reject(struct wpa_supplicant *wpa_s, const u8 *addr); int wpas_p2p_invite(struct wpa_supplicant *wpa_s, const u8 *peer_addr, struct wpa_ssid *ssid, const u8 *go_dev_addr, int freq, int vht_center_freq2, int ht40, int vht, - int max_oper_chwidth, int pref_freq); + int max_oper_chwidth, int pref_freq, int he); int wpas_p2p_invite_group(struct wpa_supplicant *wpa_s, const char *ifname, const u8 *peer_addr, const u8 *go_dev_addr); int wpas_p2p_presence_req(struct wpa_supplicant *wpa_s, u32 duration1, @@ -211,6 +211,7 @@ int wpas_p2p_lo_start(struct wpa_supplicant *wpa_s, unsigned int freq, unsigned int period, unsigned int interval, unsigned int count); int wpas_p2p_lo_stop(struct wpa_supplicant *wpa_s); +int wpas_p2p_mac_setup(struct wpa_supplicant *wpa_s); #else /* CONFIG_P2P */ diff --git a/freebsd/contrib/wpa/wpa_supplicant/rrm.c b/freebsd/contrib/wpa/wpa_supplicant/rrm.c new file mode 100644 index 00000000..8cff1253 --- /dev/null +++ b/freebsd/contrib/wpa/wpa_supplicant/rrm.c @@ -0,0 +1,1577 @@ +#include <machine/rtems-bsd-user-space.h> + +/* + * wpa_supplicant - Radio Measurements + * Copyright (c) 2003-2016, Jouni Malinen <j@w1.fi> + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "includes.h" + +#include "utils/common.h" +#include "utils/eloop.h" +#include "common/ieee802_11_common.h" +#include "wpa_supplicant_i.h" +#include "driver_i.h" +#include "bss.h" +#include "scan.h" +#include "p2p_supplicant.h" + + +static void wpas_rrm_neighbor_rep_timeout_handler(void *data, void *user_ctx) +{ + struct rrm_data *rrm = data; + + if (!rrm->notify_neighbor_rep) { + wpa_printf(MSG_ERROR, + "RRM: Unexpected neighbor report timeout"); + return; + } + + wpa_printf(MSG_DEBUG, "RRM: Notifying neighbor report - NONE"); + rrm->notify_neighbor_rep(rrm->neighbor_rep_cb_ctx, NULL); + + rrm->notify_neighbor_rep = NULL; + rrm->neighbor_rep_cb_ctx = NULL; +} + + +/* + * wpas_rrm_reset - Clear and reset all RRM data in wpa_supplicant + * @wpa_s: Pointer to wpa_supplicant + */ +void wpas_rrm_reset(struct wpa_supplicant *wpa_s) +{ + wpa_s->rrm.rrm_used = 0; + + eloop_cancel_timeout(wpas_rrm_neighbor_rep_timeout_handler, &wpa_s->rrm, + NULL); + if (wpa_s->rrm.notify_neighbor_rep) + wpas_rrm_neighbor_rep_timeout_handler(&wpa_s->rrm, NULL); + wpa_s->rrm.next_neighbor_rep_token = 1; + wpas_clear_beacon_rep_data(wpa_s); +} + + +/* + * wpas_rrm_process_neighbor_rep - Handle incoming neighbor report + * @wpa_s: Pointer to wpa_supplicant + * @report: Neighbor report buffer, prefixed by a 1-byte dialog token + * @report_len: Length of neighbor report buffer + */ +void wpas_rrm_process_neighbor_rep(struct wpa_supplicant *wpa_s, + const u8 *report, size_t report_len) +{ + struct wpabuf *neighbor_rep; + + wpa_hexdump(MSG_DEBUG, "RRM: New Neighbor Report", report, report_len); + if (report_len < 1) + return; + + if (report[0] != wpa_s->rrm.next_neighbor_rep_token - 1) { + wpa_printf(MSG_DEBUG, + "RRM: Discarding neighbor report with token %d (expected %d)", + report[0], wpa_s->rrm.next_neighbor_rep_token - 1); + return; + } + + eloop_cancel_timeout(wpas_rrm_neighbor_rep_timeout_handler, &wpa_s->rrm, + NULL); + + if (!wpa_s->rrm.notify_neighbor_rep) { + wpa_printf(MSG_ERROR, "RRM: Unexpected neighbor report"); + return; + } + + /* skipping the first byte, which is only an id (dialog token) */ + neighbor_rep = wpabuf_alloc(report_len - 1); + if (!neighbor_rep) { + wpas_rrm_neighbor_rep_timeout_handler(&wpa_s->rrm, NULL); + return; + } + wpabuf_put_data(neighbor_rep, report + 1, report_len - 1); + wpa_printf(MSG_DEBUG, "RRM: Notifying neighbor report (token = %d)", + report[0]); + wpa_s->rrm.notify_neighbor_rep(wpa_s->rrm.neighbor_rep_cb_ctx, + neighbor_rep); + wpa_s->rrm.notify_neighbor_rep = NULL; + wpa_s->rrm.neighbor_rep_cb_ctx = NULL; +} + + +#if defined(__CYGWIN__) || defined(CONFIG_NATIVE_WINDOWS) +/* Workaround different, undefined for Windows, error codes used here */ +#define ENOTCONN -1 +#define EOPNOTSUPP -1 +#define ECANCELED -1 +#endif + +/* Measurement Request element + Location Subject + Maximum Age subelement */ +#define MEASURE_REQUEST_LCI_LEN (3 + 1 + 4) +/* Measurement Request element + Location Civic Request */ +#define MEASURE_REQUEST_CIVIC_LEN (3 + 5) + + +/** + * wpas_rrm_send_neighbor_rep_request - Request a neighbor report from our AP + * @wpa_s: Pointer to wpa_supplicant + * @ssid: if not null, this is sent in the request. Otherwise, no SSID IE + * is sent in the request. + * @lci: if set, neighbor request will include LCI request + * @civic: if set, neighbor request will include civic location request + * @cb: Callback function to be called once the requested report arrives, or + * timed out after RRM_NEIGHBOR_REPORT_TIMEOUT seconds. + * In the former case, 'neighbor_rep' is a newly allocated wpabuf, and it's + * the requester's responsibility to free it. + * In the latter case NULL will be sent in 'neighbor_rep'. + * @cb_ctx: Context value to send the callback function + * Returns: 0 in case of success, negative error code otherwise + * + * In case there is a previous request which has not been answered yet, the + * new request fails. The caller may retry after RRM_NEIGHBOR_REPORT_TIMEOUT. + * Request must contain a callback function. + */ +int wpas_rrm_send_neighbor_rep_request(struct wpa_supplicant *wpa_s, + const struct wpa_ssid_value *ssid, + int lci, int civic, + void (*cb)(void *ctx, + struct wpabuf *neighbor_rep), + void *cb_ctx) +{ + struct wpabuf *buf; + const u8 *rrm_ie; + + if (wpa_s->wpa_state != WPA_COMPLETED || wpa_s->current_ssid == NULL) { + wpa_printf(MSG_DEBUG, "RRM: No connection, no RRM."); + return -ENOTCONN; + } + + if (!wpa_s->rrm.rrm_used) { + wpa_printf(MSG_DEBUG, "RRM: No RRM in current connection."); + return -EOPNOTSUPP; + } + + rrm_ie = wpa_bss_get_ie(wpa_s->current_bss, + WLAN_EID_RRM_ENABLED_CAPABILITIES); + if (!rrm_ie || !(wpa_s->current_bss->caps & IEEE80211_CAP_RRM) || + !(rrm_ie[2] & WLAN_RRM_CAPS_NEIGHBOR_REPORT)) { + wpa_printf(MSG_DEBUG, + "RRM: No network support for Neighbor Report."); + return -EOPNOTSUPP; + } + + /* Refuse if there's a live request */ + if (wpa_s->rrm.notify_neighbor_rep) { + wpa_printf(MSG_DEBUG, + "RRM: Currently handling previous Neighbor Report."); + return -EBUSY; + } + + /* 3 = action category + action code + dialog token */ + buf = wpabuf_alloc(3 + (ssid ? 2 + ssid->ssid_len : 0) + + (lci ? 2 + MEASURE_REQUEST_LCI_LEN : 0) + + (civic ? 2 + MEASURE_REQUEST_CIVIC_LEN : 0)); + if (buf == NULL) { + wpa_printf(MSG_DEBUG, + "RRM: Failed to allocate Neighbor Report Request"); + return -ENOMEM; + } + + wpa_printf(MSG_DEBUG, "RRM: Neighbor report request (for %s), token=%d", + (ssid ? wpa_ssid_txt(ssid->ssid, ssid->ssid_len) : ""), + wpa_s->rrm.next_neighbor_rep_token); + + wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT); + wpabuf_put_u8(buf, WLAN_RRM_NEIGHBOR_REPORT_REQUEST); + wpabuf_put_u8(buf, wpa_s->rrm.next_neighbor_rep_token); + if (ssid) { + wpabuf_put_u8(buf, WLAN_EID_SSID); + wpabuf_put_u8(buf, ssid->ssid_len); + wpabuf_put_data(buf, ssid->ssid, ssid->ssid_len); + } + + if (lci) { + /* IEEE P802.11-REVmc/D5.0 9.4.2.21 */ + wpabuf_put_u8(buf, WLAN_EID_MEASURE_REQUEST); + wpabuf_put_u8(buf, MEASURE_REQUEST_LCI_LEN); + + /* + * Measurement token; nonzero number that is unique among the + * Measurement Request elements in a particular frame. + */ + wpabuf_put_u8(buf, 1); /* Measurement Token */ + + /* + * Parallel, Enable, Request, and Report bits are 0, Duration is + * reserved. + */ + wpabuf_put_u8(buf, 0); /* Measurement Request Mode */ + wpabuf_put_u8(buf, MEASURE_TYPE_LCI); /* Measurement Type */ + + /* IEEE P802.11-REVmc/D5.0 9.4.2.21.10 - LCI request */ + /* Location Subject */ + wpabuf_put_u8(buf, LOCATION_SUBJECT_REMOTE); + + /* Optional Subelements */ + /* + * IEEE P802.11-REVmc/D5.0 Figure 9-170 + * The Maximum Age subelement is required, otherwise the AP can + * send only data that was determined after receiving the + * request. Setting it here to unlimited age. + */ + wpabuf_put_u8(buf, LCI_REQ_SUBELEM_MAX_AGE); + wpabuf_put_u8(buf, 2); + wpabuf_put_le16(buf, 0xffff); + } + + if (civic) { + /* IEEE P802.11-REVmc/D5.0 9.4.2.21 */ + wpabuf_put_u8(buf, WLAN_EID_MEASURE_REQUEST); + wpabuf_put_u8(buf, MEASURE_REQUEST_CIVIC_LEN); + + /* + * Measurement token; nonzero number that is unique among the + * Measurement Request elements in a particular frame. + */ + wpabuf_put_u8(buf, 2); /* Measurement Token */ + + /* + * Parallel, Enable, Request, and Report bits are 0, Duration is + * reserved. + */ + wpabuf_put_u8(buf, 0); /* Measurement Request Mode */ + /* Measurement Type */ + wpabuf_put_u8(buf, MEASURE_TYPE_LOCATION_CIVIC); + + /* IEEE P802.11-REVmc/D5.0 9.4.2.21.14: + * Location Civic request */ + /* Location Subject */ + wpabuf_put_u8(buf, LOCATION_SUBJECT_REMOTE); + wpabuf_put_u8(buf, 0); /* Civic Location Type: IETF RFC 4776 */ + /* Location Service Interval Units: Seconds */ + wpabuf_put_u8(buf, 0); + /* Location Service Interval: 0 - Only one report is requested + */ + wpabuf_put_le16(buf, 0); + /* No optional subelements */ + } + + wpa_s->rrm.next_neighbor_rep_token++; + + if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid, + wpa_s->own_addr, wpa_s->bssid, + wpabuf_head(buf), wpabuf_len(buf), 0) < 0) { + wpa_printf(MSG_DEBUG, + "RRM: Failed to send Neighbor Report Request"); + wpabuf_free(buf); + return -ECANCELED; + } + + wpa_s->rrm.neighbor_rep_cb_ctx = cb_ctx; + wpa_s->rrm.notify_neighbor_rep = cb; + eloop_register_timeout(RRM_NEIGHBOR_REPORT_TIMEOUT, 0, + wpas_rrm_neighbor_rep_timeout_handler, + &wpa_s->rrm, NULL); + + wpabuf_free(buf); + return 0; +} + + +static int wpas_rrm_report_elem(struct wpabuf **buf, u8 token, u8 mode, u8 type, + const u8 *data, size_t data_len) +{ + if (wpabuf_resize(buf, 5 + data_len)) + return -1; + + wpabuf_put_u8(*buf, WLAN_EID_MEASURE_REPORT); + wpabuf_put_u8(*buf, 3 + data_len); + wpabuf_put_u8(*buf, token); + wpabuf_put_u8(*buf, mode); + wpabuf_put_u8(*buf, type); + + if (data_len) + wpabuf_put_data(*buf, data, data_len); + + return 0; +} + + +static int +wpas_rrm_build_lci_report(struct wpa_supplicant *wpa_s, + const struct rrm_measurement_request_element *req, + struct wpabuf **buf) +{ + u8 subject; + u16 max_age = 0; + struct os_reltime t, diff; + unsigned long diff_l; + const u8 *subelem; + const u8 *request = req->variable; + size_t len = req->len - 3; + + if (len < 1) + return -1; + + if (!wpa_s->lci) + goto reject; + + subject = *request++; + len--; + + wpa_printf(MSG_DEBUG, "Measurement request location subject=%u", + subject); + + if (subject != LOCATION_SUBJECT_REMOTE) { + wpa_printf(MSG_INFO, + "Not building LCI report - bad location subject"); + return 0; + } + + /* Subelements are formatted exactly like elements */ + wpa_hexdump(MSG_DEBUG, "LCI request subelements", request, len); + subelem = get_ie(request, len, LCI_REQ_SUBELEM_MAX_AGE); + if (subelem && subelem[1] == 2) + max_age = WPA_GET_LE16(subelem + 2); + + if (os_get_reltime(&t)) + goto reject; + + os_reltime_sub(&t, &wpa_s->lci_time, &diff); + /* LCI age is calculated in 10th of a second units. */ + diff_l = diff.sec * 10 + diff.usec / 100000; + + if (max_age != 0xffff && max_age < diff_l) + goto reject; + + if (wpas_rrm_report_elem(buf, req->token, + MEASUREMENT_REPORT_MODE_ACCEPT, req->type, + wpabuf_head_u8(wpa_s->lci), + wpabuf_len(wpa_s->lci)) < 0) { + wpa_printf(MSG_DEBUG, "Failed to add LCI report element"); + return -1; + } + + return 0; + +reject: + if (!is_multicast_ether_addr(wpa_s->rrm.dst_addr) && + wpas_rrm_report_elem(buf, req->token, + MEASUREMENT_REPORT_MODE_REJECT_INCAPABLE, + req->type, NULL, 0) < 0) { + wpa_printf(MSG_DEBUG, "RRM: Failed to add report element"); + return -1; + } + + return 0; +} + + +static void wpas_rrm_send_msr_report_mpdu(struct wpa_supplicant *wpa_s, + const u8 *data, size_t len) +{ + struct wpabuf *report = wpabuf_alloc(len + 3); + + if (!report) + return; + + wpabuf_put_u8(report, WLAN_ACTION_RADIO_MEASUREMENT); + wpabuf_put_u8(report, WLAN_RRM_RADIO_MEASUREMENT_REPORT); + wpabuf_put_u8(report, wpa_s->rrm.token); + + wpabuf_put_data(report, data, len); + + if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid, + wpa_s->own_addr, wpa_s->bssid, + wpabuf_head(report), wpabuf_len(report), 0)) { + wpa_printf(MSG_ERROR, + "RRM: Radio measurement report failed: Sending Action frame failed"); + } + + wpabuf_free(report); +} + + +static int wpas_rrm_beacon_rep_update_last_frame(u8 *pos, size_t len) +{ + struct rrm_measurement_report_element *msr_rep; + u8 *end = pos + len; + u8 *msr_rep_end; + struct rrm_measurement_beacon_report *rep = NULL; + u8 *subelem; + + /* Find the last beacon report element */ + while (end - pos >= (int) sizeof(*msr_rep)) { + msr_rep = (struct rrm_measurement_report_element *) pos; + msr_rep_end = pos + msr_rep->len + 2; + + if (msr_rep->eid != WLAN_EID_MEASURE_REPORT || + msr_rep_end > end) { + /* Should not happen. This indicates a bug. */ + wpa_printf(MSG_ERROR, + "RRM: non-measurement report element in measurement report frame"); + return -1; + } + + if (msr_rep->type == MEASURE_TYPE_BEACON) + rep = (struct rrm_measurement_beacon_report *) + msr_rep->variable; + + pos += pos[1] + 2; + } + + if (!rep) + return 0; + + subelem = rep->variable; + while (subelem + 2 < msr_rep_end && + subelem[0] != WLAN_BEACON_REPORT_SUBELEM_LAST_INDICATION) + subelem += 2 + subelem[1]; + + if (subelem + 2 < msr_rep_end && + subelem[0] == WLAN_BEACON_REPORT_SUBELEM_LAST_INDICATION && + subelem[1] == 1 && + subelem + BEACON_REPORT_LAST_INDICATION_SUBELEM_LEN <= end) + subelem[2] = 1; + + return 0; +} + + +static void wpas_rrm_send_msr_report(struct wpa_supplicant *wpa_s, + struct wpabuf *buf) +{ + int len = wpabuf_len(buf); + u8 *pos = wpabuf_mhead_u8(buf), *next = pos; + +#define MPDU_REPORT_LEN (int) (IEEE80211_MAX_MMPDU_SIZE - IEEE80211_HDRLEN - 3) + + while (len) { + int send_len = (len > MPDU_REPORT_LEN) ? next - pos : len; + + if (send_len == len) + wpas_rrm_beacon_rep_update_last_frame(pos, len); + + if (send_len == len || + (send_len + next[1] + 2) > MPDU_REPORT_LEN) { + wpas_rrm_send_msr_report_mpdu(wpa_s, pos, send_len); + len -= send_len; + pos = next; + } + + if (len) + next += next[1] + 2; + } +#undef MPDU_REPORT_LEN +} + + +static int wpas_add_channel(u8 op_class, u8 chan, u8 num_primary_channels, + int *freqs) +{ + size_t i; + + for (i = 0; i < num_primary_channels; i++) { + u8 primary_chan = chan - (2 * num_primary_channels - 2) + i * 4; + + freqs[i] = ieee80211_chan_to_freq(NULL, op_class, primary_chan); + /* ieee80211_chan_to_freq() is not really meant for this + * conversion of 20 MHz primary channel numbers for wider VHT + * channels, so handle those as special cases here for now. */ + if (freqs[i] < 0 && + (op_class == 128 || op_class == 129 || op_class == 130)) + freqs[i] = 5000 + 5 * primary_chan; + if (freqs[i] < 0) { + wpa_printf(MSG_DEBUG, + "Beacon Report: Invalid channel %u", + chan); + return -1; + } + } + + return 0; +} + + +static int * wpas_add_channels(const struct oper_class_map *op, + struct hostapd_hw_modes *mode, int active, + const u8 *channels, const u8 size) +{ + int *freqs, *next_freq; + u8 num_primary_channels, i; + u8 num_chans; + + num_chans = channels ? size : + (op->max_chan - op->min_chan) / op->inc + 1; + + if (op->bw == BW80 || op->bw == BW80P80) + num_primary_channels = 4; + else if (op->bw == BW160) + num_primary_channels = 8; + else + num_primary_channels = 1; + + /* one extra place for the zero-terminator */ + freqs = os_calloc(num_chans * num_primary_channels + 1, sizeof(*freqs)); + if (!freqs) { + wpa_printf(MSG_ERROR, + "Beacon Report: Failed to allocate freqs array"); + return NULL; + } + + next_freq = freqs; + for (i = 0; i < num_chans; i++) { + u8 chan = channels ? channels[i] : op->min_chan + i * op->inc; + enum chan_allowed res = verify_channel(mode, chan, op->bw); + + if (res == NOT_ALLOWED || (res == NO_IR && active)) + continue; + + if (wpas_add_channel(op->op_class, chan, num_primary_channels, + next_freq) < 0) { + os_free(freqs); + return NULL; + } + + next_freq += num_primary_channels; + } + + if (!freqs[0]) { + os_free(freqs); + return NULL; + } + + return freqs; +} + + +static int * wpas_op_class_freqs(const struct oper_class_map *op, + struct hostapd_hw_modes *mode, int active) +{ + u8 channels_80mhz[] = { 42, 58, 106, 122, 138, 155 }; + u8 channels_160mhz[] = { 50, 114 }; + + /* + * When adding all channels in the operating class, 80 + 80 MHz + * operating classes are like 80 MHz channels because we add all valid + * channels anyway. + */ + if (op->bw == BW80 || op->bw == BW80P80) + return wpas_add_channels(op, mode, active, channels_80mhz, + ARRAY_SIZE(channels_80mhz)); + + if (op->bw == BW160) + return wpas_add_channels(op, mode, active, channels_160mhz, + ARRAY_SIZE(channels_160mhz)); + + return wpas_add_channels(op, mode, active, NULL, 0); +} + + +static int * wpas_channel_report_freqs(struct wpa_supplicant *wpa_s, int active, + const char *country, const u8 *subelems, + size_t len) +{ + int *freqs = NULL, *new_freqs; + const u8 *end = subelems + len; + + while (end - subelems > 2) { + const struct oper_class_map *op; + const u8 *ap_chan_elem, *pos; + u8 left; + struct hostapd_hw_modes *mode; + + ap_chan_elem = get_ie(subelems, end - subelems, + WLAN_BEACON_REQUEST_SUBELEM_AP_CHANNEL); + if (!ap_chan_elem) + break; + pos = ap_chan_elem + 2; + left = ap_chan_elem[1]; + if (left < 1) + break; + subelems = ap_chan_elem + 2 + left; + + op = get_oper_class(country, *pos); + if (!op) { + wpa_printf(MSG_DEBUG, + "Beacon request: unknown operating class in AP Channel Report subelement %u", + *pos); + goto out; + } + pos++; + left--; + + mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, op->mode); + if (!mode) + continue; + + /* + * For 80 + 80 MHz operating classes, this AP Channel Report + * element should be followed by another element specifying + * the second 80 MHz channel. For now just add this 80 MHz + * channel, the second 80 MHz channel will be added when the + * next element is parsed. + * TODO: Verify that this AP Channel Report element is followed + * by a corresponding AP Channel Report element as specified in + * IEEE Std 802.11-2016, 11.11.9.1. + */ + new_freqs = wpas_add_channels(op, mode, active, pos, left); + if (new_freqs) + int_array_concat(&freqs, new_freqs); + + os_free(new_freqs); + } + + return freqs; +out: + os_free(freqs); + return NULL; +} + + +static int * wpas_beacon_request_freqs(struct wpa_supplicant *wpa_s, + u8 op_class, u8 chan, int active, + const u8 *subelems, size_t len) +{ + int *freqs = NULL, *ext_freqs = NULL; + struct hostapd_hw_modes *mode; + const char *country = NULL; + const struct oper_class_map *op; + const u8 *elem; + + if (!wpa_s->current_bss) + return NULL; + elem = wpa_bss_get_ie(wpa_s->current_bss, WLAN_EID_COUNTRY); + if (elem && elem[1] >= 2) + country = (const char *) (elem + 2); + + op = get_oper_class(country, op_class); + if (!op) { + wpa_printf(MSG_DEBUG, + "Beacon request: invalid operating class %d", + op_class); + return NULL; + } + + mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, op->mode); + if (!mode) + return NULL; + + switch (chan) { + case 0: + freqs = wpas_op_class_freqs(op, mode, active); + if (!freqs) + return NULL; + break; + case 255: + /* freqs will be added from AP channel subelements */ + break; + default: + freqs = wpas_add_channels(op, mode, active, &chan, 1); + if (!freqs) + return NULL; + break; + } + + ext_freqs = wpas_channel_report_freqs(wpa_s, active, country, subelems, + len); + if (ext_freqs) { + int_array_concat(&freqs, ext_freqs); + os_free(ext_freqs); + int_array_sort_unique(freqs); + } + + return freqs; +} + + +static int wpas_get_op_chan_phy(int freq, const u8 *ies, size_t ies_len, + u8 *op_class, u8 *chan, u8 *phy_type) +{ + const u8 *ie; + int sec_chan = 0, vht = 0; + struct ieee80211_ht_operation *ht_oper = NULL; + struct ieee80211_vht_operation *vht_oper = NULL; + u8 seg0, seg1; + + ie = get_ie(ies, ies_len, WLAN_EID_HT_OPERATION); + if (ie && ie[1] >= sizeof(struct ieee80211_ht_operation)) { + u8 sec_chan_offset; + + ht_oper = (struct ieee80211_ht_operation *) (ie + 2); + sec_chan_offset = ht_oper->ht_param & + HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK; + if (sec_chan_offset == HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE) + sec_chan = 1; + else if (sec_chan_offset == + HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW) + sec_chan = -1; + } + + ie = get_ie(ies, ies_len, WLAN_EID_VHT_OPERATION); + if (ie && ie[1] >= sizeof(struct ieee80211_vht_operation)) { + vht_oper = (struct ieee80211_vht_operation *) (ie + 2); + + switch (vht_oper->vht_op_info_chwidth) { + case 1: + seg0 = vht_oper->vht_op_info_chan_center_freq_seg0_idx; + seg1 = vht_oper->vht_op_info_chan_center_freq_seg1_idx; + if (seg1 && abs(seg1 - seg0) == 8) + vht = VHT_CHANWIDTH_160MHZ; + else if (seg1) + vht = VHT_CHANWIDTH_80P80MHZ; + else + vht = VHT_CHANWIDTH_80MHZ; + break; + case 2: + vht = VHT_CHANWIDTH_160MHZ; + break; + case 3: + vht = VHT_CHANWIDTH_80P80MHZ; + break; + default: + vht = VHT_CHANWIDTH_USE_HT; + break; + } + } + + if (ieee80211_freq_to_channel_ext(freq, sec_chan, vht, op_class, + chan) == NUM_HOSTAPD_MODES) { + wpa_printf(MSG_DEBUG, + "Cannot determine operating class and channel"); + return -1; + } + + *phy_type = ieee80211_get_phy_type(freq, ht_oper != NULL, + vht_oper != NULL); + if (*phy_type == PHY_TYPE_UNSPECIFIED) { + wpa_printf(MSG_DEBUG, "Cannot determine phy type"); + return -1; + } + + return 0; +} + + +static int wpas_beacon_rep_add_frame_body(struct bitfield *eids, + enum beacon_report_detail detail, + struct wpa_bss *bss, u8 *buf, + size_t buf_len, u8 **ies_buf, + size_t *ie_len, int add_fixed) +{ + u8 *ies = *ies_buf; + size_t ies_len = *ie_len; + u8 *pos = buf; + int rem_len; + + rem_len = 255 - sizeof(struct rrm_measurement_beacon_report) - + sizeof(struct rrm_measurement_report_element) - 2 - + REPORTED_FRAME_BODY_SUBELEM_LEN; + + if (detail > BEACON_REPORT_DETAIL_ALL_FIELDS_AND_ELEMENTS) { + wpa_printf(MSG_DEBUG, + "Beacon Request: Invalid reporting detail: %d", + detail); + return -1; + } + + if (detail == BEACON_REPORT_DETAIL_NONE) + return 0; + + /* + * Minimal frame body subelement size: EID(1) + length(1) + TSF(8) + + * beacon interval(2) + capabilities(2) = 14 bytes + */ + if (add_fixed && buf_len < 14) + return -1; + + *pos++ = WLAN_BEACON_REPORT_SUBELEM_FRAME_BODY; + /* The length will be filled later */ + pos++; + + if (add_fixed) { + WPA_PUT_LE64(pos, bss->tsf); + pos += sizeof(bss->tsf); + WPA_PUT_LE16(pos, bss->beacon_int); + pos += 2; + WPA_PUT_LE16(pos, bss->caps); + pos += 2; + } + + rem_len -= pos - buf; + + /* + * According to IEEE Std 802.11-2016, 9.4.2.22.7, if the reported frame + * body subelement causes the element to exceed the maximum element + * size, the subelement is truncated so that the last IE is a complete + * IE. So even when required to report all IEs, add elements one after + * the other and stop once there is no more room in the measurement + * element. + */ + while (ies_len > 2 && 2U + ies[1] <= ies_len && rem_len > 0) { + if (detail == BEACON_REPORT_DETAIL_ALL_FIELDS_AND_ELEMENTS || + (eids && bitfield_is_set(eids, ies[0]))) { + u8 elen = ies[1]; + + if (2 + elen > buf + buf_len - pos || + 2 + elen > rem_len) + break; + + *pos++ = ies[0]; + *pos++ = elen; + os_memcpy(pos, ies + 2, elen); + pos += elen; + rem_len -= 2 + elen; + } + + ies_len -= 2 + ies[1]; + ies += 2 + ies[1]; + } + + *ie_len = ies_len; + *ies_buf = ies; + + /* Now the length is known */ + buf[1] = pos - buf - 2; + return pos - buf; +} + + +static int wpas_add_beacon_rep_elem(struct beacon_rep_data *data, + struct wpa_bss *bss, + struct wpabuf **wpa_buf, + struct rrm_measurement_beacon_report *rep, + u8 **ie, size_t *ie_len, u8 idx) +{ + int ret; + u8 *buf, *pos; + u32 subelems_len = REPORTED_FRAME_BODY_SUBELEM_LEN + + (data->last_indication ? + BEACON_REPORT_LAST_INDICATION_SUBELEM_LEN : 0); + + /* Maximum element length: Beacon Report element + Reported Frame Body + * subelement + all IEs of the reported Beacon frame + Reported Frame + * Body Fragment ID subelement */ + buf = os_malloc(sizeof(*rep) + 14 + *ie_len + subelems_len); + if (!buf) + return -1; + + os_memcpy(buf, rep, sizeof(*rep)); + + ret = wpas_beacon_rep_add_frame_body(data->eids, data->report_detail, + bss, buf + sizeof(*rep), + 14 + *ie_len, ie, ie_len, + idx == 0); + if (ret < 0) + goto out; + + pos = buf + ret + sizeof(*rep); + pos[0] = WLAN_BEACON_REPORT_SUBELEM_FRAME_BODY_FRAGMENT_ID; + pos[1] = 2; + + /* + * Only one Beacon Report Measurement is supported at a time, so + * the Beacon Report ID can always be set to 1. + */ + pos[2] = 1; + + /* Fragment ID Number (bits 0..6) and More Frame Body Fragments (bit 7) + */ + pos[3] = idx; + if (data->report_detail != BEACON_REPORT_DETAIL_NONE && *ie_len) + pos[3] |= REPORTED_FRAME_BODY_MORE_FRAGMENTS; + else + pos[3] &= ~REPORTED_FRAME_BODY_MORE_FRAGMENTS; + + pos += REPORTED_FRAME_BODY_SUBELEM_LEN; + + if (data->last_indication) { + pos[0] = WLAN_BEACON_REPORT_SUBELEM_LAST_INDICATION; + pos[1] = 1; + + /* This field will be updated later if this is the last frame */ + pos[2] = 0; + } + + ret = wpas_rrm_report_elem(wpa_buf, data->token, + MEASUREMENT_REPORT_MODE_ACCEPT, + MEASURE_TYPE_BEACON, buf, + ret + sizeof(*rep) + subelems_len); +out: + os_free(buf); + return ret; +} + + +static int wpas_add_beacon_rep(struct wpa_supplicant *wpa_s, + struct wpabuf **wpa_buf, struct wpa_bss *bss, + u64 start, u64 parent_tsf) +{ + struct beacon_rep_data *data = &wpa_s->beacon_rep_data; + u8 *ies = (u8 *) (bss + 1); + u8 *pos = ies; + size_t ies_len = bss->ie_len ? bss->ie_len : bss->beacon_ie_len; + struct rrm_measurement_beacon_report rep; + u8 idx = 0; + + if (os_memcmp(data->bssid, broadcast_ether_addr, ETH_ALEN) != 0 && + os_memcmp(data->bssid, bss->bssid, ETH_ALEN) != 0) + return 0; + + if (data->ssid_len && + (data->ssid_len != bss->ssid_len || + os_memcmp(data->ssid, bss->ssid, bss->ssid_len) != 0)) + return 0; + + if (wpas_get_op_chan_phy(bss->freq, ies, ies_len, &rep.op_class, + &rep.channel, &rep.report_info) < 0) + return 0; + + rep.start_time = host_to_le64(start); + rep.duration = host_to_le16(data->scan_params.duration); + rep.rcpi = rssi_to_rcpi(bss->level); + rep.rsni = 255; /* 255 indicates that RSNI is not available */ + os_memcpy(rep.bssid, bss->bssid, ETH_ALEN); + rep.antenna_id = 0; /* unknown */ + rep.parent_tsf = host_to_le32(parent_tsf); + + do { + int ret; + + ret = wpas_add_beacon_rep_elem(data, bss, wpa_buf, &rep, + &pos, &ies_len, idx++); + if (ret) + return ret; + } while (data->report_detail != BEACON_REPORT_DETAIL_NONE && + ies_len >= 2); + + return 0; +} + + +static int wpas_beacon_rep_no_results(struct wpa_supplicant *wpa_s, + struct wpabuf **buf) +{ + return wpas_rrm_report_elem(buf, wpa_s->beacon_rep_data.token, + MEASUREMENT_REPORT_MODE_ACCEPT, + MEASURE_TYPE_BEACON, NULL, 0); +} + + +static void wpas_beacon_rep_table(struct wpa_supplicant *wpa_s, + struct wpabuf **buf) +{ + size_t i; + + for (i = 0; i < wpa_s->last_scan_res_used; i++) { + if (wpas_add_beacon_rep(wpa_s, buf, wpa_s->last_scan_res[i], + 0, 0) < 0) + break; + } + + if (!(*buf)) + wpas_beacon_rep_no_results(wpa_s, buf); + + wpa_hexdump_buf(MSG_DEBUG, "RRM: Radio Measurement report", *buf); +} + + +void wpas_rrm_refuse_request(struct wpa_supplicant *wpa_s) +{ + if (!is_multicast_ether_addr(wpa_s->rrm.dst_addr)) { + struct wpabuf *buf = NULL; + + if (wpas_rrm_report_elem(&buf, wpa_s->beacon_rep_data.token, + MEASUREMENT_REPORT_MODE_REJECT_REFUSED, + MEASURE_TYPE_BEACON, NULL, 0)) { + wpa_printf(MSG_ERROR, "RRM: Memory allocation failed"); + wpabuf_free(buf); + return; + } + + wpas_rrm_send_msr_report(wpa_s, buf); + wpabuf_free(buf); + } + + wpas_clear_beacon_rep_data(wpa_s); +} + + +static void wpas_rrm_scan_timeout(void *eloop_ctx, void *timeout_ctx) +{ + struct wpa_supplicant *wpa_s = eloop_ctx; + struct wpa_driver_scan_params *params = + &wpa_s->beacon_rep_data.scan_params; + u16 prev_duration = params->duration; + + if (!wpa_s->current_bss) + return; + + if (!(wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_SUPPORT_SET_SCAN_DWELL) && + params->duration) { + wpa_printf(MSG_DEBUG, + "RRM: Cannot set scan duration due to missing driver support"); + params->duration = 0; + } + os_get_reltime(&wpa_s->beacon_rep_scan); + if (wpa_s->scanning || wpas_p2p_in_progress(wpa_s) || + wpa_supplicant_trigger_scan(wpa_s, params)) + wpas_rrm_refuse_request(wpa_s); + params->duration = prev_duration; +} + + +static int wpas_rm_handle_beacon_req_subelem(struct wpa_supplicant *wpa_s, + struct beacon_rep_data *data, + u8 sid, u8 slen, const u8 *subelem) +{ + u8 report_info, i; + + switch (sid) { + case WLAN_BEACON_REQUEST_SUBELEM_SSID: + if (!slen) { + wpa_printf(MSG_DEBUG, + "SSID subelement with zero length - wildcard SSID"); + break; + } + + if (slen > SSID_MAX_LEN) { + wpa_printf(MSG_DEBUG, + "Invalid SSID subelement length: %u", slen); + return -1; + } + + data->ssid_len = slen; + os_memcpy(data->ssid, subelem, data->ssid_len); + break; + case WLAN_BEACON_REQUEST_SUBELEM_INFO: + if (slen != 2) { + wpa_printf(MSG_DEBUG, + "Invalid reporting information subelement length: %u", + slen); + return -1; + } + + report_info = subelem[0]; + if (report_info != 0) { + wpa_printf(MSG_DEBUG, + "reporting information=%u is not supported", + report_info); + return 0; + } + break; + case WLAN_BEACON_REQUEST_SUBELEM_DETAIL: + if (slen != 1) { + wpa_printf(MSG_DEBUG, + "Invalid reporting detail subelement length: %u", + slen); + return -1; + } + + data->report_detail = subelem[0]; + if (data->report_detail > + BEACON_REPORT_DETAIL_ALL_FIELDS_AND_ELEMENTS) { + wpa_printf(MSG_DEBUG, "Invalid reporting detail: %u", + subelem[0]); + return -1; + } + + break; + case WLAN_BEACON_REQUEST_SUBELEM_REQUEST: + if (data->report_detail != + BEACON_REPORT_DETAIL_REQUESTED_ONLY) { + wpa_printf(MSG_DEBUG, + "Beacon request: request subelement is present but report detail is %u", + data->report_detail); + return -1; + } + + if (!slen) { + wpa_printf(MSG_DEBUG, + "Invalid request subelement length: %u", + slen); + return -1; + } + + if (data->eids) { + wpa_printf(MSG_DEBUG, + "Beacon Request: Request subelement appears more than once"); + return -1; + } + + data->eids = bitfield_alloc(255); + if (!data->eids) { + wpa_printf(MSG_DEBUG, "Failed to allocate EIDs bitmap"); + return -1; + } + + for (i = 0; i < slen; i++) + bitfield_set(data->eids, subelem[i]); + break; + case WLAN_BEACON_REQUEST_SUBELEM_AP_CHANNEL: + /* Skip - it will be processed when freqs are added */ + break; + case WLAN_BEACON_REQUEST_SUBELEM_LAST_INDICATION: + if (slen != 1) { + wpa_printf(MSG_DEBUG, + "Beacon request: Invalid last indication request subelement length: %u", + slen); + return -1; + } + + data->last_indication = subelem[0]; + break; + default: + wpa_printf(MSG_DEBUG, + "Beacon request: Unknown subelement id %u", sid); + break; + } + + return 1; +} + + +/** + * Returns 0 if the next element can be processed, 1 if some operation was + * triggered, and -1 if processing failed (i.e., the element is in invalid + * format or an internal error occurred). + */ +static int +wpas_rm_handle_beacon_req(struct wpa_supplicant *wpa_s, + u8 elem_token, int duration_mandatory, + const struct rrm_measurement_beacon_request *req, + size_t len, struct wpabuf **buf) +{ + struct beacon_rep_data *data = &wpa_s->beacon_rep_data; + struct wpa_driver_scan_params *params = &data->scan_params; + const u8 *subelems; + size_t elems_len; + u16 rand_interval; + u32 interval_usec; + u32 _rand; + int ret = 0, res; + u8 reject_mode; + + if (len < sizeof(*req)) + return -1; + + if (req->mode != BEACON_REPORT_MODE_PASSIVE && + req->mode != BEACON_REPORT_MODE_ACTIVE && + req->mode != BEACON_REPORT_MODE_TABLE) + return 0; + + subelems = req->variable; + elems_len = len - sizeof(*req); + rand_interval = le_to_host16(req->rand_interval); + + os_free(params->freqs); + os_memset(params, 0, sizeof(*params)); + + data->token = elem_token; + + /* default reporting detail is all fixed length fields and all + * elements */ + data->report_detail = BEACON_REPORT_DETAIL_ALL_FIELDS_AND_ELEMENTS; + os_memcpy(data->bssid, req->bssid, ETH_ALEN); + + while (elems_len >= 2) { + if (subelems[1] > elems_len - 2) { + wpa_printf(MSG_DEBUG, + "Beacon Request: Truncated subelement"); + ret = -1; + goto out; + } + + res = wpas_rm_handle_beacon_req_subelem( + wpa_s, data, subelems[0], subelems[1], &subelems[2]); + if (res < 0) { + ret = res; + goto out; + } else if (!res) { + reject_mode = MEASUREMENT_REPORT_MODE_REJECT_INCAPABLE; + goto out_reject; + } + + elems_len -= 2 + subelems[1]; + subelems += 2 + subelems[1]; + } + + if (req->mode == BEACON_REPORT_MODE_TABLE) { + wpas_beacon_rep_table(wpa_s, buf); + goto out; + } + + params->freqs = wpas_beacon_request_freqs( + wpa_s, req->oper_class, req->channel, + req->mode == BEACON_REPORT_MODE_ACTIVE, + req->variable, len - sizeof(*req)); + if (!params->freqs) { + wpa_printf(MSG_DEBUG, "Beacon request: No valid channels"); + reject_mode = MEASUREMENT_REPORT_MODE_REJECT_REFUSED; + goto out_reject; + } + + params->duration = le_to_host16(req->duration); + params->duration_mandatory = duration_mandatory; + if (!params->duration) { + wpa_printf(MSG_DEBUG, "Beacon request: Duration is 0"); + ret = -1; + goto out; + } + + params->only_new_results = 1; + + if (req->mode == BEACON_REPORT_MODE_ACTIVE) { + params->ssids[params->num_ssids].ssid = data->ssid; + params->ssids[params->num_ssids++].ssid_len = data->ssid_len; + } + + if (os_get_random((u8 *) &_rand, sizeof(_rand)) < 0) + _rand = os_random(); + interval_usec = (_rand % (rand_interval + 1)) * 1024; + eloop_register_timeout(0, interval_usec, wpas_rrm_scan_timeout, wpa_s, + NULL); + return 1; +out_reject: + if (!is_multicast_ether_addr(wpa_s->rrm.dst_addr) && + wpas_rrm_report_elem(buf, elem_token, reject_mode, + MEASURE_TYPE_BEACON, NULL, 0) < 0) { + wpa_printf(MSG_DEBUG, "RRM: Failed to add report element"); + ret = -1; + } +out: + wpas_clear_beacon_rep_data(wpa_s); + return ret; +} + + +static int +wpas_rrm_handle_msr_req_element( + struct wpa_supplicant *wpa_s, + const struct rrm_measurement_request_element *req, + struct wpabuf **buf) +{ + int duration_mandatory; + + wpa_printf(MSG_DEBUG, "Measurement request type %d token %d", + req->type, req->token); + + if (req->mode & MEASUREMENT_REQUEST_MODE_ENABLE) { + /* Enable bit is not supported for now */ + wpa_printf(MSG_DEBUG, "RRM: Enable bit not supported, ignore"); + return 0; + } + + if ((req->mode & MEASUREMENT_REQUEST_MODE_PARALLEL) && + req->type > MEASURE_TYPE_RPI_HIST) { + /* Parallel measurements are not supported for now */ + wpa_printf(MSG_DEBUG, + "RRM: Parallel measurements are not supported, reject"); + goto reject; + } + + duration_mandatory = + !!(req->mode & MEASUREMENT_REQUEST_MODE_DURATION_MANDATORY); + + switch (req->type) { + case MEASURE_TYPE_LCI: + return wpas_rrm_build_lci_report(wpa_s, req, buf); + case MEASURE_TYPE_BEACON: + if (duration_mandatory && + !(wpa_s->drv_rrm_flags & + WPA_DRIVER_FLAGS_SUPPORT_SET_SCAN_DWELL)) { + wpa_printf(MSG_DEBUG, + "RRM: Driver does not support dwell time configuration - reject beacon report with mandatory duration"); + goto reject; + } + return wpas_rm_handle_beacon_req(wpa_s, req->token, + duration_mandatory, + (const void *) req->variable, + req->len - 3, buf); + default: + wpa_printf(MSG_INFO, + "RRM: Unsupported radio measurement type %u", + req->type); + break; + } + +reject: + if (!is_multicast_ether_addr(wpa_s->rrm.dst_addr) && + wpas_rrm_report_elem(buf, req->token, + MEASUREMENT_REPORT_MODE_REJECT_INCAPABLE, + req->type, NULL, 0) < 0) { + wpa_printf(MSG_DEBUG, "RRM: Failed to add report element"); + return -1; + } + + return 0; +} + + +static struct wpabuf * +wpas_rrm_process_msr_req_elems(struct wpa_supplicant *wpa_s, const u8 *pos, + size_t len) +{ + struct wpabuf *buf = NULL; + + while (len) { + const struct rrm_measurement_request_element *req; + int res; + + if (len < 2) { + wpa_printf(MSG_DEBUG, "RRM: Truncated element"); + goto out; + } + + req = (const struct rrm_measurement_request_element *) pos; + if (req->eid != WLAN_EID_MEASURE_REQUEST) { + wpa_printf(MSG_DEBUG, + "RRM: Expected Measurement Request element, but EID is %u", + req->eid); + goto out; + } + + if (req->len < 3) { + wpa_printf(MSG_DEBUG, "RRM: Element length too short"); + goto out; + } + + if (req->len > len - 2) { + wpa_printf(MSG_DEBUG, "RRM: Element length too long"); + goto out; + } + + res = wpas_rrm_handle_msr_req_element(wpa_s, req, &buf); + if (res < 0) + goto out; + + pos += req->len + 2; + len -= req->len + 2; + } + + return buf; + +out: + wpabuf_free(buf); + return NULL; +} + + +void wpas_rrm_handle_radio_measurement_request(struct wpa_supplicant *wpa_s, + const u8 *src, const u8 *dst, + const u8 *frame, size_t len) +{ + struct wpabuf *report; + + if (wpa_s->wpa_state != WPA_COMPLETED) { + wpa_printf(MSG_INFO, + "RRM: Ignoring radio measurement request: Not associated"); + return; + } + + if (!wpa_s->rrm.rrm_used) { + wpa_printf(MSG_INFO, + "RRM: Ignoring radio measurement request: Not RRM network"); + return; + } + + if (len < 3) { + wpa_printf(MSG_INFO, + "RRM: Ignoring too short radio measurement request"); + return; + } + + wpa_s->rrm.token = *frame; + os_memcpy(wpa_s->rrm.dst_addr, dst, ETH_ALEN); + + /* Number of repetitions is not supported */ + + report = wpas_rrm_process_msr_req_elems(wpa_s, frame + 3, len - 3); + if (!report) + return; + + wpas_rrm_send_msr_report(wpa_s, report); + wpabuf_free(report); +} + + +void wpas_rrm_handle_link_measurement_request(struct wpa_supplicant *wpa_s, + const u8 *src, + const u8 *frame, size_t len, + int rssi) +{ + struct wpabuf *buf; + const struct rrm_link_measurement_request *req; + struct rrm_link_measurement_report report; + + if (wpa_s->wpa_state != WPA_COMPLETED) { + wpa_printf(MSG_INFO, + "RRM: Ignoring link measurement request. Not associated"); + return; + } + + if (!wpa_s->rrm.rrm_used) { + wpa_printf(MSG_INFO, + "RRM: Ignoring link measurement request. Not RRM network"); + return; + } + + if (!(wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_TX_POWER_INSERTION)) { + wpa_printf(MSG_INFO, + "RRM: Measurement report failed. TX power insertion not supported"); + return; + } + + req = (const struct rrm_link_measurement_request *) frame; + if (len < sizeof(*req)) { + wpa_printf(MSG_INFO, + "RRM: Link measurement report failed. Request too short"); + return; + } + + os_memset(&report, 0, sizeof(report)); + report.dialog_token = req->dialog_token; + report.tpc.eid = WLAN_EID_TPC_REPORT; + report.tpc.len = 2; + /* Note: The driver is expected to update report.tpc.tx_power and + * report.tpc.link_margin subfields when sending out this frame. + * Similarly, the driver would need to update report.rx_ant_id and + * report.tx_ant_id subfields. */ + report.rsni = 255; /* 255 indicates that RSNI is not available */ + report.rcpi = rssi_to_rcpi(rssi); + + /* action_category + action_code */ + buf = wpabuf_alloc(2 + sizeof(report)); + if (buf == NULL) { + wpa_printf(MSG_ERROR, + "RRM: Link measurement report failed. Buffer allocation failed"); + return; + } + + wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT); + wpabuf_put_u8(buf, WLAN_RRM_LINK_MEASUREMENT_REPORT); + wpabuf_put_data(buf, &report, sizeof(report)); + wpa_hexdump_buf(MSG_DEBUG, "RRM: Link measurement report", buf); + + if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, src, + wpa_s->own_addr, wpa_s->bssid, + wpabuf_head(buf), wpabuf_len(buf), 0)) { + wpa_printf(MSG_ERROR, + "RRM: Link measurement report failed. Send action failed"); + } + wpabuf_free(buf); +} + + +int wpas_beacon_rep_scan_process(struct wpa_supplicant *wpa_s, + struct wpa_scan_results *scan_res, + struct scan_info *info) +{ + size_t i = 0; + struct wpabuf *buf = NULL; + + if (!wpa_s->beacon_rep_data.token) + return 0; + + if (!wpa_s->current_bss) + goto out; + + /* If the measurement was aborted, don't report partial results */ + if (info->aborted) + goto out; + + wpa_printf(MSG_DEBUG, "RRM: TSF BSSID: " MACSTR " current BSS: " MACSTR, + MAC2STR(info->scan_start_tsf_bssid), + MAC2STR(wpa_s->current_bss->bssid)); + if ((wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_SUPPORT_BEACON_REPORT) && + os_memcmp(info->scan_start_tsf_bssid, wpa_s->current_bss->bssid, + ETH_ALEN) != 0) { + wpa_printf(MSG_DEBUG, + "RRM: Ignore scan results due to mismatching TSF BSSID"); + goto out; + } + + for (i = 0; i < scan_res->num; i++) { + struct wpa_bss *bss = + wpa_bss_get_bssid(wpa_s, scan_res->res[i]->bssid); + + if (!bss) + continue; + + if ((wpa_s->drv_rrm_flags & + WPA_DRIVER_FLAGS_SUPPORT_BEACON_REPORT) && + os_memcmp(scan_res->res[i]->tsf_bssid, + wpa_s->current_bss->bssid, ETH_ALEN) != 0) { + wpa_printf(MSG_DEBUG, + "RRM: Ignore scan result for " MACSTR + " due to mismatching TSF BSSID" MACSTR, + MAC2STR(scan_res->res[i]->bssid), + MAC2STR(scan_res->res[i]->tsf_bssid)); + continue; + } + + /* + * Don't report results that were not received during the + * current measurement. + */ + if (!(wpa_s->drv_rrm_flags & + WPA_DRIVER_FLAGS_SUPPORT_BEACON_REPORT)) { + struct os_reltime update_time, diff; + + /* For now, allow 8 ms older results due to some + * unknown issue with cfg80211 BSS table updates during + * a scan with the current BSS. + * TODO: Fix this more properly to avoid having to have + * this type of hacks in place. */ + calculate_update_time(&scan_res->fetch_time, + scan_res->res[i]->age, + &update_time); + os_reltime_sub(&wpa_s->beacon_rep_scan, + &update_time, &diff); + if (os_reltime_before(&update_time, + &wpa_s->beacon_rep_scan) && + (diff.sec || diff.usec >= 8000)) { + wpa_printf(MSG_DEBUG, + "RRM: Ignore scan result for " MACSTR + " due to old update (age(ms) %u, calculated age %u.%06u seconds)", + MAC2STR(scan_res->res[i]->bssid), + scan_res->res[i]->age, + (unsigned int) diff.sec, + (unsigned int) diff.usec); + continue; + } + } else if (info->scan_start_tsf > + scan_res->res[i]->parent_tsf) { + continue; + } + + if (wpas_add_beacon_rep(wpa_s, &buf, bss, info->scan_start_tsf, + scan_res->res[i]->parent_tsf) < 0) + break; + } + + if (!buf && wpas_beacon_rep_no_results(wpa_s, &buf)) + goto out; + + wpa_hexdump_buf(MSG_DEBUG, "RRM: Radio Measurement report", buf); + + wpas_rrm_send_msr_report(wpa_s, buf); + wpabuf_free(buf); + +out: + wpas_clear_beacon_rep_data(wpa_s); + return 1; +} + + +void wpas_clear_beacon_rep_data(struct wpa_supplicant *wpa_s) +{ + struct beacon_rep_data *data = &wpa_s->beacon_rep_data; + + eloop_cancel_timeout(wpas_rrm_scan_timeout, wpa_s, NULL); + bitfield_free(data->eids); + os_free(data->scan_params.freqs); + os_memset(data, 0, sizeof(*data)); +} diff --git a/freebsd/contrib/wpa/wpa_supplicant/scan.c b/freebsd/contrib/wpa/wpa_supplicant/scan.c index 4fd269a8..41f95fb8 100644 --- a/freebsd/contrib/wpa/wpa_supplicant/scan.c +++ b/freebsd/contrib/wpa/wpa_supplicant/scan.c @@ -2,7 +2,7 @@ /* * WPA Supplicant - Scanning - * Copyright (c) 2003-2014, Jouni Malinen <j@w1.fi> + * Copyright (c) 2003-2019, Jouni Malinen <j@w1.fi> * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -119,9 +119,19 @@ int wpa_supplicant_enabled_networks(struct wpa_supplicant *wpa_s) static void wpa_supplicant_assoc_try(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid) { + int min_temp_disabled = 0; + while (ssid) { - if (!wpas_network_disabled(wpa_s, ssid)) - break; + if (!wpas_network_disabled(wpa_s, ssid)) { + int temp_disabled = wpas_temp_disabled(wpa_s, ssid); + + if (temp_disabled <= 0) + break; + + if (!min_temp_disabled || + temp_disabled < min_temp_disabled) + min_temp_disabled = temp_disabled; + } ssid = ssid->next; } @@ -130,7 +140,7 @@ static void wpa_supplicant_assoc_try(struct wpa_supplicant *wpa_s, wpa_dbg(wpa_s, MSG_DEBUG, "wpa_supplicant_assoc_try: Reached " "end of scan list - go back to beginning"); wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN; - wpa_supplicant_req_scan(wpa_s, 0, 0); + wpa_supplicant_req_scan(wpa_s, min_temp_disabled, 0); return; } if (ssid->next) { @@ -178,10 +188,22 @@ static void wpas_trigger_scan_cb(struct wpa_radio_work *work, int deinit) params->only_new_results = 1; } ret = wpa_drv_scan(wpa_s, params); + /* + * Store the obtained vendor scan cookie (if any) in wpa_s context. + * The current design is to allow only one scan request on each + * interface, hence having this scan cookie stored in wpa_s context is + * fine for now. + * + * Revisit this logic if concurrent scan operations per interface + * is supported. + */ + if (ret == 0) + wpa_s->curr_scan_cookie = params->scan_cookie; wpa_scan_free_params(params); work->ctx = NULL; if (ret) { - int retry = wpa_s->last_scan_req != MANUAL_SCAN_REQ; + int retry = wpa_s->last_scan_req != MANUAL_SCAN_REQ && + !wpa_s->beacon_rep_data.token; if (wpa_s->disconnected) retry = 0; @@ -199,7 +221,14 @@ static void wpas_trigger_scan_cb(struct wpa_radio_work *work, int deinit) /* Restore scan_req since we will try to scan again */ wpa_s->scan_req = wpa_s->last_scan_req; wpa_supplicant_req_scan(wpa_s, 1, 0); + } else if (wpa_s->scan_res_handler) { + /* Clear the scan_res_handler */ + wpa_s->scan_res_handler = NULL; } + + if (wpa_s->beacon_rep_data.token) + wpas_rrm_refuse_request(wpa_s); + return; } @@ -428,6 +457,33 @@ static void wpas_add_interworking_elements(struct wpa_supplicant *wpa_s, #endif /* CONFIG_INTERWORKING */ +#ifdef CONFIG_MBO +static void wpas_fils_req_param_add_max_channel(struct wpa_supplicant *wpa_s, + struct wpabuf **ie) +{ + if (wpabuf_resize(ie, 5)) { + wpa_printf(MSG_DEBUG, + "Failed to allocate space for FILS Request Parameters element"); + return; + } + + /* FILS Request Parameters element */ + wpabuf_put_u8(*ie, WLAN_EID_EXTENSION); + wpabuf_put_u8(*ie, 3); /* FILS Request attribute length */ + wpabuf_put_u8(*ie, WLAN_EID_EXT_FILS_REQ_PARAMS); + /* Parameter control bitmap */ + wpabuf_put_u8(*ie, 0); + /* Max Channel Time field - contains the value of MaxChannelTime + * parameter of the MLME-SCAN.request primitive represented in units of + * TUs, as an unsigned integer. A Max Channel Time field value of 255 + * is used to indicate any duration of more than 254 TUs, or an + * unspecified or unknown duration. (IEEE Std 802.11ai-2016, 9.4.2.178) + */ + wpabuf_put_u8(*ie, 255); +} +#endif /* CONFIG_MBO */ + + void wpa_supplicant_set_default_scan_ies(struct wpa_supplicant *wpa_s) { struct wpabuf *default_ies = NULL; @@ -449,8 +505,10 @@ void wpa_supplicant_set_default_scan_ies(struct wpa_supplicant *wpa_s) wpabuf_put_data(default_ies, ext_capab, ext_capab_len); #ifdef CONFIG_MBO - /* Send cellular capabilities for potential MBO STAs */ - if (wpabuf_resize(&default_ies, 9) == 0) + if (wpa_s->enable_oce & OCE_STA) + wpas_fils_req_param_add_max_channel(wpa_s, &default_ies); + /* Send MBO and OCE capabilities */ + if (wpabuf_resize(&default_ies, 12) == 0) wpas_mbo_scan_ie(wpa_s, default_ies); #endif /* CONFIG_MBO */ @@ -490,6 +548,11 @@ static struct wpabuf * wpa_supplicant_extra_ies(struct wpa_supplicant *wpa_s) wpas_add_interworking_elements(wpa_s, extra_ie); #endif /* CONFIG_INTERWORKING */ +#ifdef CONFIG_MBO + if (wpa_s->enable_oce & OCE_STA) + wpas_fils_req_param_add_max_channel(wpa_s, &extra_ie); +#endif /* CONFIG_MBO */ + #ifdef CONFIG_WPS wps = wpas_wps_in_use(wpa_s, &req_type); @@ -520,8 +583,8 @@ static struct wpabuf * wpa_supplicant_extra_ies(struct wpa_supplicant *wpa_s) #endif /* CONFIG_WPS */ #ifdef CONFIG_HS20 - if (wpa_s->conf->hs20 && wpabuf_resize(&extra_ie, 7) == 0) - wpas_hs20_add_indication(extra_ie, -1); + if (wpa_s->conf->hs20 && wpabuf_resize(&extra_ie, 9) == 0) + wpas_hs20_add_indication(extra_ie, -1, 0); #endif /* CONFIG_HS20 */ #ifdef CONFIG_FST @@ -531,8 +594,8 @@ static struct wpabuf * wpa_supplicant_extra_ies(struct wpa_supplicant *wpa_s) #endif /* CONFIG_FST */ #ifdef CONFIG_MBO - /* Send cellular capabilities for potential MBO STAs */ - if (wpabuf_resize(&extra_ie, 9) == 0) + /* Send MBO and OCE capabilities */ + if (wpabuf_resize(&extra_ie, 12) == 0) wpas_mbo_scan_ie(wpa_s, extra_ie); #endif /* CONFIG_MBO */ @@ -616,6 +679,87 @@ static void wpa_setband_scan_freqs(struct wpa_supplicant *wpa_s, } +static void wpa_add_scan_ssid(struct wpa_supplicant *wpa_s, + struct wpa_driver_scan_params *params, + size_t max_ssids, const u8 *ssid, size_t ssid_len) +{ + unsigned int j; + + for (j = 0; j < params->num_ssids; j++) { + if (params->ssids[j].ssid_len == ssid_len && + params->ssids[j].ssid && + os_memcmp(params->ssids[j].ssid, ssid, ssid_len) == 0) + return; /* already in the list */ + } + + if (params->num_ssids + 1 > max_ssids) { + wpa_printf(MSG_DEBUG, "Over max scan SSIDs for manual request"); + return; + } + + wpa_printf(MSG_DEBUG, "Scan SSID (manual request): %s", + wpa_ssid_txt(ssid, ssid_len)); + + params->ssids[params->num_ssids].ssid = ssid; + params->ssids[params->num_ssids].ssid_len = ssid_len; + params->num_ssids++; +} + + +static void wpa_add_owe_scan_ssid(struct wpa_supplicant *wpa_s, + struct wpa_driver_scan_params *params, + struct wpa_ssid *ssid, size_t max_ssids) +{ +#ifdef CONFIG_OWE + struct wpa_bss *bss; + + if (!(ssid->key_mgmt & WPA_KEY_MGMT_OWE)) + return; + + wpa_printf(MSG_DEBUG, "OWE: Look for transition mode AP. ssid=%s", + wpa_ssid_txt(ssid->ssid, ssid->ssid_len)); + + dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) { + const u8 *owe, *pos, *end; + const u8 *owe_ssid; + size_t owe_ssid_len; + + if (bss->ssid_len != ssid->ssid_len || + os_memcmp(bss->ssid, ssid->ssid, ssid->ssid_len) != 0) + continue; + + owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE); + if (!owe || owe[1] < 4) + continue; + + pos = owe + 6; + end = owe + 2 + owe[1]; + + /* Must include BSSID and ssid_len */ + if (end - pos < ETH_ALEN + 1) + return; + + /* Skip BSSID */ + pos += ETH_ALEN; + owe_ssid_len = *pos++; + owe_ssid = pos; + + if ((size_t) (end - pos) < owe_ssid_len || + owe_ssid_len > SSID_MAX_LEN) + return; + + wpa_printf(MSG_DEBUG, + "OWE: scan_ssids: transition mode OWE ssid=%s", + wpa_ssid_txt(owe_ssid, owe_ssid_len)); + + wpa_add_scan_ssid(wpa_s, params, max_ssids, + owe_ssid, owe_ssid_len); + return; + } +#endif /* CONFIG_OWE */ +} + + static void wpa_set_scan_ssids(struct wpa_supplicant *wpa_s, struct wpa_driver_scan_params *params, size_t max_ssids) @@ -630,33 +774,17 @@ static void wpa_set_scan_ssids(struct wpa_supplicant *wpa_s, max_ssids = max_ssids > 1 ? max_ssids - 1 : max_ssids; for (i = 0; i < wpa_s->scan_id_count; i++) { - unsigned int j; - ssid = wpa_config_get_network(wpa_s->conf, wpa_s->scan_id[i]); - if (!ssid || !ssid->scan_ssid) + if (!ssid) continue; - - for (j = 0; j < params->num_ssids; j++) { - if (params->ssids[j].ssid_len == ssid->ssid_len && - params->ssids[j].ssid && - os_memcmp(params->ssids[j].ssid, ssid->ssid, - ssid->ssid_len) == 0) - break; - } - if (j < params->num_ssids) - continue; /* already in the list */ - - if (params->num_ssids + 1 > max_ssids) { - wpa_printf(MSG_DEBUG, - "Over max scan SSIDs for manual request"); - break; - } - - wpa_printf(MSG_DEBUG, "Scan SSID (manual request): %s", - wpa_ssid_txt(ssid->ssid, ssid->ssid_len)); - params->ssids[params->num_ssids].ssid = ssid->ssid; - params->ssids[params->num_ssids].ssid_len = ssid->ssid_len; - params->num_ssids++; + if (ssid->scan_ssid) + wpa_add_scan_ssid(wpa_s, params, max_ssids, + ssid->ssid, ssid->ssid_len); + /* + * Also add the SSID of the OWE BSS, to allow discovery of + * transition mode APs more quickly. + */ + wpa_add_owe_scan_ssid(wpa_s, params, ssid, max_ssids); } wpa_s->scan_id_count = 0; @@ -705,10 +833,7 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx) size_t max_ssids; int connect_without_scan = 0; - if (wpa_s->pno || wpa_s->pno_sched_pending) { - wpa_dbg(wpa_s, MSG_DEBUG, "Skip scan - PNO is in progress"); - return; - } + wpa_s->ignore_post_flush_scan_res = 0; if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) { wpa_dbg(wpa_s, MSG_DEBUG, "Skip scan - interface disabled"); @@ -770,6 +895,21 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx) return; } + /* + * Don't cancel the scan based on ongoing PNO; defer it. Some scans are + * used for changing modes inside wpa_supplicant (roaming, + * auto-reconnect, etc). Discarding the scan might hurt these processes. + * The normal use case for PNO is to suspend the host immediately after + * starting PNO, so the periodic 100 ms attempts to run the scan do not + * normally happen in practice multiple times, i.e., this is simply + * restarting scanning once the host is woken up and PNO stopped. + */ + if (wpa_s->pno || wpa_s->pno_sched_pending) { + wpa_dbg(wpa_s, MSG_DEBUG, "Defer scan - PNO is in progress"); + wpa_supplicant_req_scan(wpa_s, 0, 100000); + return; + } + if (wpa_s->conf->ap_scan == 2) max_ssids = 1; else { @@ -911,6 +1051,17 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx) if (params.num_ssids + 1 >= max_ssids) break; } + + if (!wpas_network_disabled(wpa_s, ssid)) { + /* + * Also add the SSID of the OWE BSS, to allow + * discovery of transition mode APs more + * quickly. + */ + wpa_add_owe_scan_ssid(wpa_s, ¶ms, ssid, + max_ssids); + } + ssid = ssid->next; if (ssid == start) break; @@ -997,6 +1148,13 @@ ssid_list_set: wpa_s->manual_scan_freqs = NULL; } + if (params.freqs == NULL && wpa_s->select_network_scan_freqs) { + wpa_dbg(wpa_s, MSG_DEBUG, + "Limit select_network scan to specified channels"); + params.freqs = wpa_s->select_network_scan_freqs; + wpa_s->select_network_scan_freqs = NULL; + } + if (params.freqs == NULL && wpa_s->next_scan_freqs) { wpa_dbg(wpa_s, MSG_DEBUG, "Optimize scan based on previously " "generated frequency list"); @@ -1031,6 +1189,11 @@ ssid_list_set: } } +#ifdef CONFIG_MBO + if (wpa_s->enable_oce & OCE_STA) + params.oce_scan = 1; +#endif /* CONFIG_MBO */ + params.filter_ssids = wpa_supplicant_build_filter_ssids( wpa_s->conf, ¶ms.num_filter_ssids); if (extra_ie) { @@ -1049,7 +1212,8 @@ ssid_list_set: } #endif /* CONFIG_P2P */ - if (wpa_s->mac_addr_rand_enable & MAC_ADDR_RAND_SCAN) { + if ((wpa_s->mac_addr_rand_enable & MAC_ADDR_RAND_SCAN) && + wpa_s->wpa_state <= WPA_SCANNING) { params.mac_addr_rand = 1; if (wpa_s->mac_addr_scan) { params.mac_addr = wpa_s->mac_addr_scan; @@ -1227,6 +1391,26 @@ int wpa_supplicant_delayed_sched_scan(struct wpa_supplicant *wpa_s, } +static void +wpa_scan_set_relative_rssi_params(struct wpa_supplicant *wpa_s, + struct wpa_driver_scan_params *params) +{ + if (wpa_s->wpa_state != WPA_COMPLETED || + !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SCHED_SCAN_RELATIVE_RSSI) || + wpa_s->srp.relative_rssi_set == 0) + return; + + params->relative_rssi_set = 1; + params->relative_rssi = wpa_s->srp.relative_rssi; + + if (wpa_s->srp.relative_adjust_rssi == 0) + return; + + params->relative_adjust_band = wpa_s->srp.relative_adjust_band; + params->relative_adjust_rssi = wpa_s->srp.relative_adjust_rssi; +} + + /** * wpa_supplicant_req_sched_scan - Start a periodic scheduled scan * @wpa_s: Pointer to wpa_supplicant data @@ -1419,6 +1603,11 @@ int wpa_supplicant_req_sched_scan(struct wpa_supplicant *wpa_s) int_array_concat(¶ms.freqs, wpa_s->conf->freq_list); } +#ifdef CONFIG_MBO + if (wpa_s->enable_oce & OCE_STA) + params.oce_scan = 1; +#endif /* CONFIG_MBO */ + scan_params = ¶ms; scan: @@ -1460,18 +1649,24 @@ scan: params.sched_scan_plans_num = 1; } + params.sched_scan_start_delay = wpa_s->conf->sched_scan_start_delay; + if (ssid || !wpa_s->first_sched_scan) { wpa_dbg(wpa_s, MSG_DEBUG, - "Starting sched scan: interval %u timeout %d", + "Starting sched scan after %u seconds: interval %u timeout %d", + params.sched_scan_start_delay, params.sched_scan_plans[0].interval, wpa_s->sched_scan_timeout); } else { - wpa_dbg(wpa_s, MSG_DEBUG, "Starting sched scan (no timeout)"); + wpa_dbg(wpa_s, MSG_DEBUG, + "Starting sched scan after %u seconds (no timeout)", + params.sched_scan_start_delay); } wpa_setband_scan_freqs(wpa_s, scan_params); - if (wpa_s->mac_addr_rand_enable & MAC_ADDR_RAND_SCHED_SCAN) { + if ((wpa_s->mac_addr_rand_enable & MAC_ADDR_RAND_SCHED_SCAN) && + wpa_s->wpa_state <= WPA_SCANNING) { params.mac_addr_rand = 1; if (wpa_s->mac_addr_sched_scan) { params.mac_addr = wpa_s->mac_addr_sched_scan; @@ -1480,6 +1675,8 @@ scan: } } + wpa_scan_set_relative_rssi_params(wpa_s, scan_params); + ret = wpa_supplicant_start_sched_scan(wpa_s, scan_params); wpabuf_free(extra_ie); os_free(params.filter_ssids); @@ -1620,7 +1817,13 @@ static int wpa_scan_get_max_rate(const struct wpa_scan_res *res) */ const u8 * wpa_scan_get_ie(const struct wpa_scan_res *res, u8 ie) { - return get_ie((const u8 *) (res + 1), res->ie_len, ie); + size_t ie_len = res->ie_len; + + /* Use the Beacon frame IEs if res->ie_len is not available */ + if (!ie_len) + ie_len = res->beacon_ie_len; + + return get_ie((const u8 *) (res + 1), ie_len, ie); } @@ -1737,10 +1940,12 @@ struct wpabuf * wpa_scan_get_vendor_ie_multi(const struct wpa_scan_res *res, * This doc https://supportforums.cisco.com/docs/DOC-12954 says, "the general * rule of thumb is that any SNR above 20 is good." This one * http://www.cisco.com/en/US/tech/tk722/tk809/technologies_q_and_a_item09186a00805e9a96.shtml#qa23 - * recommends 25 as a minimum SNR for 54 Mbps data rate. 30 is chosen here as a - * conservative value. + * recommends 25 as a minimum SNR for 54 Mbps data rate. The estimates used in + * scan_est_throughput() allow even smaller SNR values for the maximum rates + * (21 for 54 Mbps, 22 for VHT80 MCS9, 24 for HT40 and HT20 MCS7). Use 25 as a + * somewhat conservative value here. */ -#define GREAT_SNR 30 +#define GREAT_SNR 25 #define IS_5GHZ(n) (n > 4000) @@ -1788,10 +1993,13 @@ static int wpa_scan_result_compar(const void *a, const void *b) } /* if SNR is close, decide by max rate or frequency band */ + if (snr_a && snr_b && abs(snr_b - snr_a) < 7) { + if (wa->est_throughput != wb->est_throughput) + return (int) wb->est_throughput - + (int) wa->est_throughput; + } if ((snr_a && snr_b && abs(snr_b - snr_a) < 5) || (wa->qual && wb->qual && abs(wb->qual - wa->qual) < 10)) { - if (wa->est_throughput != wb->est_throughput) - return wb->est_throughput - wa->est_throughput; if (IS_5GHZ(wa->freq) ^ IS_5GHZ(wb->freq)) return IS_5GHZ(wa->freq) ? -1 : 1; } @@ -2179,10 +2387,22 @@ wpa_supplicant_get_scan_results(struct wpa_supplicant *wpa_s, } #endif /* CONFIG_WPS */ - qsort(scan_res->res, scan_res->num, sizeof(struct wpa_scan_res *), - compar); + if (scan_res->res) { + qsort(scan_res->res, scan_res->num, + sizeof(struct wpa_scan_res *), compar); + } dump_scan_res(scan_res); + if (wpa_s->ignore_post_flush_scan_res) { + /* FLUSH command aborted an ongoing scan and these are the + * results from the aborted scan. Do not process the results to + * maintain flushed state. */ + wpa_dbg(wpa_s, MSG_DEBUG, + "Do not update BSS table based on pending post-FLUSH scan results"); + wpa_s->ignore_post_flush_scan_res = 0; + return scan_res; + } + wpa_bss_update_start(wpa_s); for (i = 0; i < scan_res->num; i++) wpa_bss_update_scan_res(wpa_s, scan_res->res[i], @@ -2264,11 +2484,10 @@ wpa_scan_clone_params(const struct wpa_driver_scan_params *src) for (i = 0; i < src->num_ssids; i++) { if (src->ssids[i].ssid) { - n = os_malloc(src->ssids[i].ssid_len); + n = os_memdup(src->ssids[i].ssid, + src->ssids[i].ssid_len); if (n == NULL) goto failed; - os_memcpy(n, src->ssids[i].ssid, - src->ssids[i].ssid_len); params->ssids[i].ssid = n; params->ssids[i].ssid_len = src->ssids[i].ssid_len; } @@ -2276,30 +2495,26 @@ wpa_scan_clone_params(const struct wpa_driver_scan_params *src) params->num_ssids = src->num_ssids; if (src->extra_ies) { - n = os_malloc(src->extra_ies_len); + n = os_memdup(src->extra_ies, src->extra_ies_len); if (n == NULL) goto failed; - os_memcpy(n, src->extra_ies, src->extra_ies_len); params->extra_ies = n; params->extra_ies_len = src->extra_ies_len; } if (src->freqs) { int len = int_array_len(src->freqs); - params->freqs = os_malloc((len + 1) * sizeof(int)); + params->freqs = os_memdup(src->freqs, (len + 1) * sizeof(int)); if (params->freqs == NULL) goto failed; - os_memcpy(params->freqs, src->freqs, (len + 1) * sizeof(int)); } if (src->filter_ssids) { - params->filter_ssids = os_malloc(sizeof(*params->filter_ssids) * + params->filter_ssids = os_memdup(src->filter_ssids, + sizeof(*params->filter_ssids) * src->num_filter_ssids); if (params->filter_ssids == NULL) goto failed; - os_memcpy(params->filter_ssids, src->filter_ssids, - sizeof(*params->filter_ssids) * - src->num_filter_ssids); params->num_filter_ssids = src->num_filter_ssids; } @@ -2307,17 +2522,18 @@ wpa_scan_clone_params(const struct wpa_driver_scan_params *src) params->p2p_probe = src->p2p_probe; params->only_new_results = src->only_new_results; params->low_priority = src->low_priority; + params->duration = src->duration; + params->duration_mandatory = src->duration_mandatory; + params->oce_scan = src->oce_scan; if (src->sched_scan_plans_num > 0) { params->sched_scan_plans = - os_malloc(sizeof(*src->sched_scan_plans) * + os_memdup(src->sched_scan_plans, + sizeof(*src->sched_scan_plans) * src->sched_scan_plans_num); if (!params->sched_scan_plans) goto failed; - os_memcpy(params->sched_scan_plans, src->sched_scan_plans, - sizeof(*src->sched_scan_plans) * - src->sched_scan_plans_num); params->sched_scan_plans_num = src->sched_scan_plans_num; } @@ -2342,13 +2558,16 @@ wpa_scan_clone_params(const struct wpa_driver_scan_params *src) if (src->bssid) { u8 *bssid; - bssid = os_malloc(ETH_ALEN); + bssid = os_memdup(src->bssid, ETH_ALEN); if (!bssid) goto failed; - os_memcpy(bssid, src->bssid, ETH_ALEN); params->bssid = bssid; } + params->relative_rssi_set = src->relative_rssi_set; + params->relative_rssi = src->relative_rssi; + params->relative_adjust_band = src->relative_adjust_band; + params->relative_adjust_rssi = src->relative_adjust_rssi; return params; failed: @@ -2406,7 +2625,7 @@ int wpas_start_pno(struct wpa_supplicant *wpa_s) return 0; if ((wpa_s->wpa_state > WPA_SCANNING) && - (wpa_s->wpa_state <= WPA_COMPLETED)) { + (wpa_s->wpa_state < WPA_COMPLETED)) { wpa_printf(MSG_ERROR, "PNO: In assoc process"); return -EAGAIN; } @@ -2513,12 +2732,15 @@ int wpas_start_pno(struct wpa_supplicant *wpa_s) params.sched_scan_plans_num = 1; } + params.sched_scan_start_delay = wpa_s->conf->sched_scan_start_delay; + if (params.freqs == NULL && wpa_s->manual_sched_scan_freqs) { wpa_dbg(wpa_s, MSG_DEBUG, "Limit sched scan to specified channels"); params.freqs = wpa_s->manual_sched_scan_freqs; } - if (wpa_s->mac_addr_rand_enable & MAC_ADDR_RAND_PNO) { + if ((wpa_s->mac_addr_rand_enable & MAC_ADDR_RAND_PNO) && + wpa_s->wpa_state <= WPA_SCANNING) { params.mac_addr_rand = 1; if (wpa_s->mac_addr_pno) { params.mac_addr = wpa_s->mac_addr_pno; @@ -2526,6 +2748,8 @@ int wpas_start_pno(struct wpa_supplicant *wpa_s) } } + wpa_scan_set_relative_rssi_params(wpa_s, ¶ms); + ret = wpa_supplicant_start_sched_scan(wpa_s, ¶ms); os_free(params.filter_ssids); if (ret == 0) @@ -2585,6 +2809,13 @@ int wpas_mac_addr_rand_scan_set(struct wpa_supplicant *wpa_s, { u8 *tmp = NULL; + if ((wpa_s->mac_addr_rand_supported & type) != type ) { + wpa_printf(MSG_INFO, + "scan: MAC randomization type %u != supported=%u", + type, wpa_s->mac_addr_rand_supported); + return -1; + } + wpas_mac_addr_rand_scan_clear(wpa_s, type); if (addr) { @@ -2616,18 +2847,20 @@ int wpas_mac_addr_rand_scan_set(struct wpa_supplicant *wpa_s, int wpas_abort_ongoing_scan(struct wpa_supplicant *wpa_s) { - int scan_work = !!wpa_s->scan_work; - -#ifdef CONFIG_P2P - scan_work |= !!wpa_s->p2p_scan_work; -#endif /* CONFIG_P2P */ + struct wpa_radio_work *work; + struct wpa_radio *radio = wpa_s->radio; - if (scan_work && wpa_s->own_scan_running) { + dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) { + if (work->wpa_s != wpa_s || !work->started || + (os_strcmp(work->type, "scan") != 0 && + os_strcmp(work->type, "p2p-scan") != 0)) + continue; wpa_dbg(wpa_s, MSG_DEBUG, "Abort an ongoing scan"); - return wpa_drv_abort_scan(wpa_s); + return wpa_drv_abort_scan(wpa_s, wpa_s->curr_scan_cookie); } - return 0; + wpa_dbg(wpa_s, MSG_DEBUG, "No ongoing scan/p2p-scan found to abort"); + return -1; } diff --git a/freebsd/contrib/wpa/wpa_supplicant/sme.h b/freebsd/contrib/wpa/wpa_supplicant/sme.h index fd5c3b4e..1a7f9e83 100644 --- a/freebsd/contrib/wpa/wpa_supplicant/sme.h +++ b/freebsd/contrib/wpa/wpa_supplicant/sme.h @@ -28,6 +28,7 @@ void sme_event_disassoc(struct wpa_supplicant *wpa_s, struct disassoc_info *info); void sme_event_unprot_disconnect(struct wpa_supplicant *wpa_s, const u8 *sa, const u8 *da, u16 reason_code); +void sme_event_ch_switch(struct wpa_supplicant *wpa_s); void sme_sa_query_rx(struct wpa_supplicant *wpa_s, const u8 *sa, const u8 *data, size_t len); void sme_state_changed(struct wpa_supplicant *wpa_s); @@ -38,6 +39,10 @@ void sme_deinit(struct wpa_supplicant *wpa_s); int sme_proc_obss_scan(struct wpa_supplicant *wpa_s); void sme_sched_obss_scan(struct wpa_supplicant *wpa_s, int enable); +void sme_external_auth_trigger(struct wpa_supplicant *wpa_s, + union wpa_event_data *data); +void sme_external_auth_mgmt_rx(struct wpa_supplicant *wpa_s, + const u8 *auth_frame, size_t len); #else /* CONFIG_SME */ @@ -85,6 +90,10 @@ static inline void sme_event_unprot_disconnect(struct wpa_supplicant *wpa_s, { } +static inline void sme_event_ch_switch(struct wpa_supplicant *wpa_s) +{ +} + static inline void sme_state_changed(struct wpa_supplicant *wpa_s) { } @@ -113,6 +122,16 @@ static inline void sme_sched_obss_scan(struct wpa_supplicant *wpa_s, { } +static inline void sme_external_auth_trigger(struct wpa_supplicant *wpa_s, + union wpa_event_data *data) +{ +} + +static inline void sme_external_auth_mgmt_rx(struct wpa_supplicant *wpa_s, + const u8 *auth_frame, size_t len) +{ +} + #endif /* CONFIG_SME */ #endif /* SME_H */ diff --git a/freebsd/contrib/wpa/wpa_supplicant/wmm_ac.c b/freebsd/contrib/wpa/wpa_supplicant/wmm_ac.c index 4d7b064b..b1a18748 100644 --- a/freebsd/contrib/wpa/wpa_supplicant/wmm_ac.c +++ b/freebsd/contrib/wpa/wpa_supplicant/wmm_ac.c @@ -89,13 +89,10 @@ static int wmm_ac_add_ts(struct wpa_supplicant *wpa_s, const u8 *addr, } /* copy tspec */ - _tspec = os_malloc(sizeof(*_tspec)); + _tspec = os_memdup(tspec, sizeof(*_tspec)); if (!_tspec) return -1; - /* store the admitted TSPEC */ - os_memcpy(_tspec, tspec, sizeof(*_tspec)); - if (dir != WMM_AC_DIR_DOWNLINK) { ret = wpa_drv_add_ts(wpa_s, tsid, addr, up, admitted_time); wpa_printf(MSG_DEBUG, @@ -476,13 +473,8 @@ static int wmm_ac_init(struct wpa_supplicant *wpa_s, const u8 *ies, return -1; } - if (!ies) { - wpa_printf(MSG_ERROR, "WMM AC: Missing IEs"); - return -1; - } - - if (!(wmm_params->info_bitmap & WMM_PARAMS_UAPSD_QUEUES_INFO)) { - wpa_printf(MSG_DEBUG, "WMM AC: Missing U-APSD configuration"); + if (!ies || !(wmm_params->info_bitmap & WMM_PARAMS_UAPSD_QUEUES_INFO)) { + /* WMM AC not in use for this connection */ return -1; } @@ -527,7 +519,7 @@ static void wmm_ac_deinit(struct wpa_supplicant *wpa_s) for (i = 0; i < WMM_AC_NUM; i++) wmm_ac_del_ts(wpa_s, i, TS_DIR_IDX_ALL); - /* delete pending add_ts requset */ + /* delete pending add_ts request */ wmm_ac_del_req(wpa_s, 1); os_free(wpa_s->wmm_ac_assoc_info); diff --git a/freebsd/contrib/wpa/wpa_supplicant/wnm_sta.h b/freebsd/contrib/wpa/wpa_supplicant/wnm_sta.h index 81d81535..29625f8c 100644 --- a/freebsd/contrib/wpa/wpa_supplicant/wnm_sta.h +++ b/freebsd/contrib/wpa/wpa_supplicant/wnm_sta.h @@ -43,6 +43,10 @@ struct neighbor_report { unsigned int rm_capab_present:1; unsigned int bearing_present:1; unsigned int bss_term_present:1; + unsigned int acceptable:1; +#ifdef CONFIG_MBO + unsigned int is_first:1; +#endif /* CONFIG_MBO */ struct measurement_pilot *meas_pilot; struct multiple_bssid *mul_bssid; int freq; @@ -56,13 +60,21 @@ void ieee802_11_rx_wnm_action(struct wpa_supplicant *wpa_s, const struct ieee80211_mgmt *mgmt, size_t len); int wnm_send_bss_transition_mgmt_query(struct wpa_supplicant *wpa_s, - u8 query_reason, int cand_list); + u8 query_reason, + const char *btm_candidates, + int cand_list); + void wnm_deallocate_memory(struct wpa_supplicant *wpa_s); +int wnm_send_coloc_intf_report(struct wpa_supplicant *wpa_s, u8 dialog_token, + const struct wpabuf *elems); +void wnm_set_coloc_intf_elems(struct wpa_supplicant *wpa_s, + struct wpabuf *elems); #ifdef CONFIG_WNM int wnm_scan_process(struct wpa_supplicant *wpa_s, int reply_on_fail); +void wnm_clear_coloc_intf_reporting(struct wpa_supplicant *wpa_s); #else /* CONFIG_WNM */ @@ -72,6 +84,10 @@ static inline int wnm_scan_process(struct wpa_supplicant *wpa_s, return 0; } +static inline void wnm_clear_coloc_intf_reporting(struct wpa_supplicant *wpa_s) +{ +} + #endif /* CONFIG_WNM */ #endif /* WNM_STA_H */ diff --git a/freebsd/contrib/wpa/wpa_supplicant/wpa_supplicant.c b/freebsd/contrib/wpa/wpa_supplicant/wpa_supplicant.c index 7346ae0b..1bc62ce6 100644 --- a/freebsd/contrib/wpa/wpa_supplicant/wpa_supplicant.c +++ b/freebsd/contrib/wpa/wpa_supplicant/wpa_supplicant.c @@ -2,7 +2,7 @@ /* * WPA Supplicant - * Copyright (c) 2003-2016, Jouni Malinen <j@w1.fi> + * Copyright (c) 2003-2019, Jouni Malinen <j@w1.fi> * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -40,6 +40,8 @@ #include "common/wpa_ctrl.h" #include "common/ieee802_11_defs.h" #include "common/hw_features_common.h" +#include "common/gas_server.h" +#include "common/dpp.h" #include "p2p/p2p.h" #include "fst/fst.h" #include "blacklist.h" @@ -61,10 +63,15 @@ #include "wnm_sta.h" #include "wpas_kay.h" #include "mesh.h" +#include "dpp_supplicant.h" +#ifdef CONFIG_MESH +#include "ap/ap_config.h" +#include "ap/hostapd.h" +#endif /* CONFIG_MESH */ const char *const wpa_supplicant_version = "wpa_supplicant v" VERSION_STR "\n" -"Copyright (c) 2003-2016, Jouni Malinen <j@w1.fi> and contributors"; +"Copyright (c) 2003-2019, Jouni Malinen <j@w1.fi> and contributors"; const char *const wpa_supplicant_license = "This software may be distributed under the terms of the BSD license.\n" @@ -114,6 +121,13 @@ const char *const wpa_supplicant_full_license5 = "\n"; #endif /* CONFIG_NO_STDOUT_DEBUG */ + +static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx); +#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL) +static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s); +#endif /* CONFIG_FILS && IEEE8021X_EAPOL */ + + /* Configure default/group WEP keys for static WEP */ int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid) { @@ -232,10 +246,30 @@ void wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s, wpa_dbg(wpa_s, MSG_DEBUG, "Setting authentication timeout: %d sec " "%d usec", sec, usec); eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL); + wpa_s->last_auth_timeout_sec = sec; eloop_register_timeout(sec, usec, wpa_supplicant_timeout, wpa_s, NULL); } +/* + * wpas_auth_timeout_restart - Restart and change timeout for authentication + * @wpa_s: Pointer to wpa_supplicant data + * @sec_diff: difference in seconds applied to original timeout value + */ +void wpas_auth_timeout_restart(struct wpa_supplicant *wpa_s, int sec_diff) +{ + int new_sec = wpa_s->last_auth_timeout_sec + sec_diff; + + if (eloop_is_timeout_registered(wpa_supplicant_timeout, wpa_s, NULL)) { + wpa_dbg(wpa_s, MSG_DEBUG, + "Authentication timeout restart: %d sec", new_sec); + eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL); + eloop_register_timeout(new_sec, 0, wpa_supplicant_timeout, + wpa_s, NULL); + } +} + + /** * wpa_supplicant_cancel_auth_timeout - Cancel authentication timeout * @wpa_s: Pointer to wpa_supplicant data @@ -249,6 +283,9 @@ void wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *wpa_s) wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling authentication timeout"); eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL); wpa_blacklist_del(wpa_s, wpa_s->bssid); + os_free(wpa_s->last_con_fail_realm); + wpa_s->last_con_fail_realm = NULL; + wpa_s->last_con_fail_realm_len = 0; } @@ -331,7 +368,12 @@ void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s) eapol_sm_notify_config(wpa_s->eapol, &ssid->eap, &eapol_conf); - ieee802_1x_alloc_kay_sm(wpa_s, ssid); +#ifdef CONFIG_MACSEC + if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE && ssid->mka_psk_set) + ieee802_1x_create_preshared_mka(wpa_s, ssid); + else + ieee802_1x_alloc_kay_sm(wpa_s, ssid); +#endif /* CONFIG_MACSEC */ #endif /* IEEE8021X_EAPOL */ } @@ -405,18 +447,32 @@ void free_hw_features(struct wpa_supplicant *wpa_s) } -static void free_bss_tmp_disallowed(struct wpa_supplicant *wpa_s) +void free_bss_tmp_disallowed(struct wpa_supplicant *wpa_s) { struct wpa_bss_tmp_disallowed *bss, *prev; dl_list_for_each_safe(bss, prev, &wpa_s->bss_tmp_disallowed, struct wpa_bss_tmp_disallowed, list) { + eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss); dl_list_del(&bss->list); os_free(bss); } } +void wpas_flush_fils_hlp_req(struct wpa_supplicant *wpa_s) +{ + struct fils_hlp_req *req; + + while ((req = dl_list_first(&wpa_s->fils_hlp_req, struct fils_hlp_req, + list)) != NULL) { + dl_list_del(&req->list); + wpabuf_free(req->pkt); + os_free(req); + } +} + + static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s) { int i; @@ -436,6 +492,10 @@ static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s) #ifdef CONFIG_TESTING_OPTIONS l2_packet_deinit(wpa_s->l2_test); wpa_s->l2_test = NULL; + os_free(wpa_s->get_pref_freq_list_override); + wpa_s->get_pref_freq_list_override = NULL; + wpabuf_free(wpa_s->last_assoc_req_wpa_ie); + wpa_s->last_assoc_req_wpa_ie = NULL; #endif /* CONFIG_TESTING_OPTIONS */ if (wpa_s->conf != NULL) { @@ -450,6 +510,10 @@ static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s) os_free(wpa_s->confanother); wpa_s->confanother = NULL; + os_free(wpa_s->last_con_fail_realm); + wpa_s->last_con_fail_realm = NULL; + wpa_s->last_con_fail_realm_len = 0; + wpa_sm_set_eapol(wpa_s->wpa, NULL); eapol_sm_deinit(wpa_s->eapol); wpa_s->eapol = NULL; @@ -508,6 +572,8 @@ static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s) os_free(wpa_s->manual_scan_freqs); wpa_s->manual_scan_freqs = NULL; + os_free(wpa_s->select_network_scan_freqs); + wpa_s->select_network_scan_freqs = NULL; os_free(wpa_s->manual_sched_scan_freqs); wpa_s->manual_sched_scan_freqs = NULL; @@ -526,6 +592,8 @@ static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s) radio_remove_works(wpa_s, "gas-query", 0); gas_query_deinit(wpa_s->gas); wpa_s->gas = NULL; + gas_server_deinit(wpa_s->gas_server); + wpa_s->gas_server = NULL; free_hw_features(wpa_s); @@ -582,6 +650,34 @@ static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s) wpabuf_free(wpa_s->lci); wpa_s->lci = NULL; + wpas_clear_beacon_rep_data(wpa_s); + +#ifdef CONFIG_PMKSA_CACHE_EXTERNAL +#ifdef CONFIG_MESH + { + struct external_pmksa_cache *entry; + + while ((entry = dl_list_last(&wpa_s->mesh_external_pmksa_cache, + struct external_pmksa_cache, + list)) != NULL) { + dl_list_del(&entry->list); + os_free(entry->pmksa_cache); + os_free(entry); + } + } +#endif /* CONFIG_MESH */ +#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */ + + wpas_flush_fils_hlp_req(wpa_s); + + wpabuf_free(wpa_s->ric_ies); + wpa_s->ric_ies = NULL; + +#ifdef CONFIG_DPP + wpas_dpp_deinit(wpa_s); + dpp_global_deinit(wpa_s->dpp); + wpa_s->dpp = NULL; +#endif /* CONFIG_DPP */ } @@ -755,6 +851,23 @@ void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s, wpa_supplicant_state_txt(wpa_s->wpa_state), wpa_supplicant_state_txt(state)); + if (state == WPA_COMPLETED && + os_reltime_initialized(&wpa_s->roam_start)) { + os_reltime_age(&wpa_s->roam_start, &wpa_s->roam_time); + wpa_s->roam_start.sec = 0; + wpa_s->roam_start.usec = 0; + wpas_notify_auth_changed(wpa_s); + wpas_notify_roam_time(wpa_s); + wpas_notify_roam_complete(wpa_s); + } else if (state == WPA_DISCONNECTED && + os_reltime_initialized(&wpa_s->roam_start)) { + wpa_s->roam_start.sec = 0; + wpa_s->roam_start.usec = 0; + wpa_s->roam_time.sec = 0; + wpa_s->roam_time.usec = 0; + wpas_notify_roam_complete(wpa_s); + } + if (state == WPA_INTERFACE_DISABLED) { /* Assure normal scan when interface is restored */ wpa_s->normal_scans = 0; @@ -795,12 +908,24 @@ void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s, if (state == WPA_COMPLETED && wpa_s->new_connection) { struct wpa_ssid *ssid = wpa_s->current_ssid; + int fils_hlp_sent = 0; + +#ifdef CONFIG_SME + if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) && + wpa_auth_alg_fils(wpa_s->sme.auth_alg)) + fils_hlp_sent = 1; +#endif /* CONFIG_SME */ + if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) && + wpa_auth_alg_fils(wpa_s->auth_alg)) + fils_hlp_sent = 1; + #if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG) wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to " - MACSTR " completed [id=%d id_str=%s]", + MACSTR " completed [id=%d id_str=%s%s]", MAC2STR(wpa_s->bssid), ssid ? ssid->id : -1, - ssid && ssid->id_str ? ssid->id_str : ""); + ssid && ssid->id_str ? ssid->id_str : "", + fils_hlp_sent ? " FILS_HLP_SENT" : ""); #endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */ wpas_clear_temp_disabled(wpa_s, ssid, 1); wpa_blacklist_clear(wpa_s); @@ -815,6 +940,11 @@ void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s, wpas_p2p_completed(wpa_s); sme_sched_obss_scan(wpa_s, 1); + +#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL) + if (!fils_hlp_sent && ssid && ssid->eap.erp) + wpas_update_fils_connect_params(wpa_s); +#endif /* CONFIG_FILS && IEEE8021X_EAPOL */ } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING || state == WPA_ASSOCIATED) { wpa_s->new_connection = 1; @@ -833,7 +963,7 @@ void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s, wpa_supplicant_stop_bgscan(wpa_s); #endif /* CONFIG_BGSCAN */ - if (state == WPA_AUTHENTICATING) + if (state > WPA_SCANNING) wpa_supplicant_stop_autoscan(wpa_s); if (state == WPA_DISCONNECTED || state == WPA_INACTIVE) @@ -929,7 +1059,13 @@ int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s) "file '%s' - exiting", wpa_s->confname); return -1; } - wpa_config_read(wpa_s->confanother, conf); + if (wpa_s->confanother && + !wpa_config_read(wpa_s->confanother, conf)) { + wpa_msg(wpa_s, MSG_ERROR, + "Failed to parse the configuration file '%s' - exiting", + wpa_s->confanother); + return -1; + } conf->changed_parameters = (unsigned int) -1; @@ -955,7 +1091,9 @@ int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s) * TODO: should notify EAPOL SM about changes in opensc_engine_path, * pkcs11_engine_path, pkcs11_module_path, openssl_ciphers. */ - if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) { + if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) || + wpa_s->key_mgmt == WPA_KEY_MGMT_OWE || + wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) { /* * Clear forced success to clear EAP state for next * authentication. @@ -1056,6 +1194,18 @@ static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s, } +static int matching_ciphers(struct wpa_ssid *ssid, struct wpa_ie_data *ie, + int freq) +{ + if (!ie->has_group) + ie->group_cipher = wpa_default_rsn_cipher(freq); + if (!ie->has_pairwise) + ie->pairwise_cipher = wpa_default_rsn_cipher(freq); + return (ie->group_cipher & ssid->group_cipher) && + (ie->pairwise_cipher & ssid->pairwise_cipher); +} + + /** * wpa_supplicant_set_suites - Set authentication and encryption parameters * @wpa_s: Pointer to wpa_supplicant data @@ -1087,8 +1237,7 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) && wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 && - (ie.group_cipher & ssid->group_cipher) && - (ie.pairwise_cipher & ssid->pairwise_cipher) && + matching_ciphers(ssid, &ie, bss->freq) && (ie.key_mgmt & ssid->key_mgmt)) { wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0"); proto = WPA_PROTO_RSN; @@ -1100,14 +1249,20 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0"); proto = WPA_PROTO_WPA; #ifdef CONFIG_HS20 - } else if (bss_osen && (ssid->proto & WPA_PROTO_OSEN)) { + } else if (bss_osen && (ssid->proto & WPA_PROTO_OSEN) && + wpa_parse_wpa_ie(bss_osen, 2 + bss_osen[1], &ie) == 0 && + (ie.group_cipher & ssid->group_cipher) && + (ie.pairwise_cipher & ssid->pairwise_cipher) && + (ie.key_mgmt & ssid->key_mgmt)) { wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using OSEN"); - /* TODO: parse OSEN element */ - os_memset(&ie, 0, sizeof(ie)); - ie.group_cipher = WPA_CIPHER_CCMP; - ie.pairwise_cipher = WPA_CIPHER_CCMP; - ie.key_mgmt = WPA_KEY_MGMT_OSEN; proto = WPA_PROTO_OSEN; + } else if (bss_rsn && (ssid->proto & WPA_PROTO_OSEN) && + wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 && + (ie.group_cipher & ssid->group_cipher) && + (ie.pairwise_cipher & ssid->pairwise_cipher) && + (ie.key_mgmt & ssid->key_mgmt)) { + wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using OSEN (within RSN)"); + proto = WPA_PROTO_RSN; #endif /* CONFIG_HS20 */ } else if (bss) { wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN"); @@ -1159,10 +1314,35 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, ie.pairwise_cipher = ssid->pairwise_cipher; ie.key_mgmt = ssid->key_mgmt; #ifdef CONFIG_IEEE80211W - ie.mgmt_group_cipher = - ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION ? - WPA_CIPHER_AES_128_CMAC : 0; + ie.mgmt_group_cipher = 0; + if (ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION) { + if (ssid->group_mgmt_cipher & + WPA_CIPHER_BIP_GMAC_256) + ie.mgmt_group_cipher = + WPA_CIPHER_BIP_GMAC_256; + else if (ssid->group_mgmt_cipher & + WPA_CIPHER_BIP_CMAC_256) + ie.mgmt_group_cipher = + WPA_CIPHER_BIP_CMAC_256; + else if (ssid->group_mgmt_cipher & + WPA_CIPHER_BIP_GMAC_128) + ie.mgmt_group_cipher = + WPA_CIPHER_BIP_GMAC_128; + else + ie.mgmt_group_cipher = + WPA_CIPHER_AES_128_CMAC; + } #endif /* CONFIG_IEEE80211W */ +#ifdef CONFIG_OWE + if ((ssid->key_mgmt & WPA_KEY_MGMT_OWE) && + !ssid->owe_only && + !bss_wpa && !bss_rsn && !bss_osen) { + wpa_supplicant_set_non_wpa_policy(wpa_s, ssid); + wpa_s->wpa_proto = 0; + *wpa_ie_len = 0; + return 0; + } +#endif /* CONFIG_OWE */ wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites " "based on configuration"); } else @@ -1197,6 +1377,9 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, wpa_s->pairwise_cipher = WPA_CIPHER_NONE; #else /* CONFIG_NO_WPA */ sel = ie.group_cipher & ssid->group_cipher; + wpa_dbg(wpa_s, MSG_DEBUG, + "WPA: AP group 0x%x network profile group 0x%x; available group 0x%x", + ie.group_cipher, ssid->group_cipher, sel); wpa_s->group_cipher = wpa_pick_group_cipher(sel); if (wpa_s->group_cipher < 0) { wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group " @@ -1207,6 +1390,9 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, wpa_cipher_txt(wpa_s->group_cipher)); sel = ie.pairwise_cipher & ssid->pairwise_cipher; + wpa_dbg(wpa_s, MSG_DEBUG, + "WPA: AP pairwise 0x%x network profile pairwise 0x%x; available pairwise 0x%x", + ie.pairwise_cipher, ssid->pairwise_cipher, sel); wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1); if (wpa_s->pairwise_cipher < 0) { wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise " @@ -1218,11 +1404,29 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, #endif /* CONFIG_NO_WPA */ sel = ie.key_mgmt & ssid->key_mgmt; + wpa_dbg(wpa_s, MSG_DEBUG, + "WPA: AP key_mgmt 0x%x network profile key_mgmt 0x%x; available key_mgmt 0x%x", + ie.key_mgmt, ssid->key_mgmt, sel); #ifdef CONFIG_SAE if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE)) sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE); #endif /* CONFIG_SAE */ if (0) { +#ifdef CONFIG_IEEE80211R +#ifdef CONFIG_SHA384 + } else if (sel & WPA_KEY_MGMT_FT_IEEE8021X_SHA384) { + wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X_SHA384; + wpa_dbg(wpa_s, MSG_DEBUG, + "WPA: using KEY_MGMT FT/802.1X-SHA384"); + if (pmksa_cache_get_current(wpa_s->wpa)) { + /* PMKSA caching with FT is not fully functional, so + * disable the case for now. */ + wpa_dbg(wpa_s, MSG_DEBUG, + "WPA: Disable PMKSA caching for FT/802.1X connection"); + pmksa_cache_clear_current(wpa_s->wpa); + } +#endif /* CONFIG_SHA384 */ +#endif /* CONFIG_IEEE80211R */ #ifdef CONFIG_SUITEB192 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) { wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B_192; @@ -1235,22 +1439,52 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X with Suite B"); #endif /* CONFIG_SUITEB */ +#ifdef CONFIG_FILS +#ifdef CONFIG_IEEE80211R + } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA384) { + wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA384; + wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA384"); + } else if (sel & WPA_KEY_MGMT_FT_FILS_SHA256) { + wpa_s->key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA256; + wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT-FILS-SHA256"); +#endif /* CONFIG_IEEE80211R */ + } else if (sel & WPA_KEY_MGMT_FILS_SHA384) { + wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA384; + wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA384"); + } else if (sel & WPA_KEY_MGMT_FILS_SHA256) { + wpa_s->key_mgmt = WPA_KEY_MGMT_FILS_SHA256; + wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FILS-SHA256"); +#endif /* CONFIG_FILS */ #ifdef CONFIG_IEEE80211R } else if (sel & WPA_KEY_MGMT_FT_IEEE8021X) { wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X; wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X"); - } else if (sel & WPA_KEY_MGMT_FT_PSK) { - wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK; - wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK"); + if (pmksa_cache_get_current(wpa_s->wpa)) { + /* PMKSA caching with FT is not fully functional, so + * disable the case for now. */ + wpa_dbg(wpa_s, MSG_DEBUG, + "WPA: Disable PMKSA caching for FT/802.1X connection"); + pmksa_cache_clear_current(wpa_s->wpa); + } #endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_DPP + } else if (sel & WPA_KEY_MGMT_DPP) { + wpa_s->key_mgmt = WPA_KEY_MGMT_DPP; + wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT DPP"); +#endif /* CONFIG_DPP */ #ifdef CONFIG_SAE - } else if (sel & WPA_KEY_MGMT_SAE) { - wpa_s->key_mgmt = WPA_KEY_MGMT_SAE; - wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE"); } else if (sel & WPA_KEY_MGMT_FT_SAE) { wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE; wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE"); + } else if (sel & WPA_KEY_MGMT_SAE) { + wpa_s->key_mgmt = WPA_KEY_MGMT_SAE; + wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE"); #endif /* CONFIG_SAE */ +#ifdef CONFIG_IEEE80211R + } else if (sel & WPA_KEY_MGMT_FT_PSK) { + wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK; + wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK"); +#endif /* CONFIG_IEEE80211R */ #ifdef CONFIG_IEEE80211W } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) { wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256; @@ -1275,6 +1509,11 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, wpa_s->key_mgmt = WPA_KEY_MGMT_OSEN; wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using KEY_MGMT OSEN"); #endif /* CONFIG_HS20 */ +#ifdef CONFIG_OWE + } else if (sel & WPA_KEY_MGMT_OWE) { + wpa_s->key_mgmt = WPA_KEY_MGMT_OWE; + wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT OWE"); +#endif /* CONFIG_OWE */ } else { wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select " "authenticated key management type"); @@ -1288,9 +1527,14 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, #ifdef CONFIG_IEEE80211W sel = ie.mgmt_group_cipher; + if (ssid->group_mgmt_cipher) + sel &= ssid->group_mgmt_cipher; if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION || !(ie.capabilities & WPA_CAPABILITY_MFPC)) sel = 0; + wpa_dbg(wpa_s, MSG_DEBUG, + "WPA: AP mgmt_group_cipher 0x%x network profile mgmt_group_cipher 0x%x; available mgmt_group_cipher 0x%x", + ie.mgmt_group_cipher, ssid->group_mgmt_cipher, sel); if (sel & WPA_CIPHER_AES_128_CMAC) { wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC; wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher " @@ -1316,23 +1560,44 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP, wpas_get_ssid_pmf(wpa_s, ssid)); #endif /* CONFIG_IEEE80211W */ +#ifdef CONFIG_OCV + wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCV, ssid->ocv); +#endif /* CONFIG_OCV */ if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) { wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to generate WPA IE"); return -1; } - if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) { + if (0) { +#ifdef CONFIG_DPP + } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) { + /* Use PMK from DPP network introduction (PMKSA entry) */ + wpa_sm_set_pmk_from_pmksa(wpa_s->wpa); +#endif /* CONFIG_DPP */ + } else if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) { int psk_set = 0; + int sae_only; + + sae_only = (ssid->key_mgmt & (WPA_KEY_MGMT_PSK | + WPA_KEY_MGMT_FT_PSK | + WPA_KEY_MGMT_PSK_SHA256)) == 0; - if (ssid->psk_set) { + if (ssid->psk_set && !sae_only) { + wpa_hexdump_key(MSG_MSGDUMP, "PSK (set in config)", + ssid->psk, PMK_LEN); wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN, NULL, NULL); psk_set = 1; } + + if (wpa_key_mgmt_sae(ssid->key_mgmt) && + (ssid->sae_password || ssid->passphrase)) + psk_set = 1; + #ifndef CONFIG_NO_PBKDF2 if (bss && ssid->bssid_set && ssid->ssid_len == 0 && - ssid->passphrase) { + ssid->passphrase && !sae_only) { u8 psk[PMK_LEN]; pbkdf2_sha1(ssid->passphrase, bss->ssid, bss->ssid_len, 4096, psk, PMK_LEN); @@ -1344,7 +1609,7 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, } #endif /* CONFIG_NO_PBKDF2 */ #ifdef CONFIG_EXT_PASSWORD - if (ssid->ext_psk) { + if (ssid->ext_psk && !sae_only) { struct wpabuf *pw = ext_password_get(wpa_s->ext_pw, ssid->ext_psk); char pw_str[64 + 1]; @@ -1390,6 +1655,9 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, ext_password_free(pw); return -1; } + wpa_hexdump_key(MSG_MSGDUMP, + "PSK (from external PSK)", + psk, PMK_LEN); wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL, NULL); psk_set = 1; @@ -1410,8 +1678,15 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, if (!psk_set) { wpa_msg(wpa_s, MSG_INFO, "No PSK available for association"); + wpas_auth_failed(wpa_s, "NO_PSK_AVAILABLE"); return -1; } +#ifdef CONFIG_OWE + } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_OWE) { + /* OWE Diffie-Hellman exchange in (Re)Association + * Request/Response frames set the PMK, so do not override it + * here. */ +#endif /* CONFIG_OWE */ } else wpa_sm_set_pmk_from_pmksa(wpa_s->wpa); @@ -1427,6 +1702,10 @@ static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx) case 0: /* Bits 0-7 */ break; case 1: /* Bits 8-15 */ + if (wpa_s->conf->coloc_intf_reporting) { + /* Bit 13 - Collocated Interference Reporting */ + *pos |= 0x20; + } break; case 2: /* Bits 16-23 */ #ifdef CONFIG_WNM @@ -1445,7 +1724,7 @@ static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx) break; case 4: /* Bits 32-39 */ #ifdef CONFIG_INTERWORKING - if (wpa_s->drv_flags / WPA_DRIVER_FLAGS_QOS_MAPPING) + if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_QOS_MAPPING) *pos |= 0x01; /* Bit 32 - QoS Map */ #endif /* CONFIG_INTERWORKING */ break; @@ -1468,6 +1747,12 @@ static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx) if (wpa_s->conf->ftm_initiator) *pos |= 0x80; /* Bit 71 - FTM initiator */ break; + case 9: /* Bits 72-79 */ +#ifdef CONFIG_FILS + if (!wpa_s->disable_fils) + *pos |= 0x01; +#endif /* CONFIG_FILS */ + break; } } @@ -1475,11 +1760,8 @@ static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx) int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen) { u8 *pos = buf; - u8 len = 6, i; + u8 len = 10, i; - if (len < 9 && - (wpa_s->conf->ftm_initiator || wpa_s->conf->ftm_responder)) - len = 9; if (len < wpa_s->extended_capa_len) len = wpa_s->extended_capa_len; if (buflen < (size_t) len + 2) { @@ -1667,6 +1949,9 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s, wmm_ac_clear_saved_tspecs(wpa_s); wpa_s->reassoc_same_bss = 0; wpa_s->reassoc_same_ess = 0; +#ifdef CONFIG_TESTING_OPTIONS + wpa_s->testing_resend_assoc = 0; +#endif /* CONFIG_TESTING_OPTIONS */ if (wpa_s->last_ssid == ssid) { wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS"); @@ -1674,12 +1959,16 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s, if (wpa_s->current_bss && wpa_s->current_bss == bss) { wmm_ac_save_tspecs(wpa_s); wpa_s->reassoc_same_bss = 1; + } else if (wpa_s->current_bss && wpa_s->current_bss != bss) { + os_get_reltime(&wpa_s->roam_start); } - } else if (rand_style > 0) { + } + + if (rand_style > 0 && !wpa_s->reassoc_same_ess) { if (wpas_update_random_addr(wpa_s, rand_style) < 0) return; wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid); - } else if (wpa_s->mac_addr_changed) { + } else if (rand_style == 0 && wpa_s->mac_addr_changed) { if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) { wpa_msg(wpa_s, MSG_INFO, "Could not restore permanent MAC address"); @@ -1698,6 +1987,13 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s, #ifdef CONFIG_IBSS_RSN ibss_rsn_deinit(wpa_s->ibss_rsn); wpa_s->ibss_rsn = NULL; +#else /* CONFIG_IBSS_RSN */ + if (ssid->mode == WPAS_MODE_IBSS && + !(ssid->key_mgmt & (WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPA_NONE))) { + wpa_msg(wpa_s, MSG_INFO, + "IBSS RSN not supported in the build"); + return; + } #endif /* CONFIG_IBSS_RSN */ if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO || @@ -1739,6 +2035,7 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s, wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_STARTED "ssid=\"%s\" id=%d", wpa_ssid_txt(ssid->ssid, ssid->ssid_len), ssid->id); + wpas_notify_mesh_group_started(wpa_s, ssid); #else /* CONFIG_MESH */ wpa_msg(wpa_s, MSG_ERROR, "mesh mode support not included in the build"); @@ -1746,6 +2043,20 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s, return; } + /* + * Set WPA state machine configuration to match the selected network now + * so that the information is available before wpas_start_assoc_cb() + * gets called. This is needed at least for RSN pre-authentication where + * candidate APs are added to a list based on scan result processing + * before completion of the first association. + */ + wpa_supplicant_rsn_supp_set_config(wpa_s, ssid); + +#ifdef CONFIG_DPP + if (wpas_dpp_check_connect(wpa_s, ssid, bss) != 0) + return; +#endif /* CONFIG_DPP */ + #ifdef CONFIG_TDLS if (bss) wpa_tdls_ap_ies(wpa_s->wpa, (const u8 *) (bss + 1), @@ -1768,6 +2079,13 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s, return; } +#ifdef CONFIG_SME + if (ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) { + /* Clear possibly set auth_alg, if any, from last attempt. */ + wpa_s->sme.auth_alg = WPA_AUTH_ALG_OPEN; + } +#endif /* CONFIG_SME */ + wpas_abort_ongoing_scan(wpa_s); cwork = os_zalloc(sizeof(*cwork)); @@ -1799,11 +2117,6 @@ static int drv_supports_vht(struct wpa_supplicant *wpa_s, u8 channel; int i; -#ifdef CONFIG_HT_OVERRIDES - if (ssid->disable_ht) - return 0; -#endif /* CONFIG_HT_OVERRIDES */ - hw_mode = ieee80211_freq_to_chan(ssid->frequency, &channel); if (hw_mode == NUM_HOSTAPD_MODES) return 0; @@ -1916,9 +2229,14 @@ void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s, if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR)) return; + freq->channel = pri_chan->chan; + #ifdef CONFIG_HT_OVERRIDES - if (ssid->disable_ht40) - return; + if (ssid->disable_ht40) { + if (ssid->disable_vht) + return; + goto skip_ht40; + } #endif /* CONFIG_HT_OVERRIDES */ /* Check/setup HT40+/HT40- */ @@ -1943,8 +2261,6 @@ void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s, if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR)) return; - freq->channel = pri_chan->chan; - if (ht40 == -1) { if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS)) return; @@ -1988,6 +2304,9 @@ void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s, wpa_scan_results_free(scan_res); } +#ifdef CONFIG_HT_OVERRIDES +skip_ht40: +#endif /* CONFIG_HT_OVERRIDES */ wpa_printf(MSG_DEBUG, "IBSS/mesh: setup freq channel %d, sec_channel_offset %d", freq->channel, freq->sec_channel_offset); @@ -2002,6 +2321,13 @@ void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s, vht_freq = *freq; +#ifdef CONFIG_VHT_OVERRIDES + if (ssid->disable_vht) { + freq->vht_enabled = 0; + return; + } +#endif /* CONFIG_VHT_OVERRIDES */ + vht_freq.vht_enabled = vht_supported(mode); if (!vht_freq.vht_enabled) return; @@ -2070,6 +2396,13 @@ void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s, vht_caps |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ; seg0 = 114; } + } else if (ssid->max_oper_chwidth == VHT_CHANWIDTH_USE_HT) { + chwidth = VHT_CHANWIDTH_USE_HT; + seg0 = vht80[j] + 2; +#ifdef CONFIG_HT_OVERRIDES + if (ssid->disable_ht40) + seg0 = 0; +#endif /* CONFIG_HT_OVERRIDES */ } if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq, @@ -2086,147 +2419,177 @@ void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s, } -static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit) +#ifdef CONFIG_FILS +static size_t wpas_add_fils_hlp_req(struct wpa_supplicant *wpa_s, u8 *ie_buf, + size_t ie_buf_len) { - struct wpa_connect_work *cwork = work->ctx; - struct wpa_bss *bss = cwork->bss; - struct wpa_ssid *ssid = cwork->ssid; - struct wpa_supplicant *wpa_s = work->wpa_s; - u8 wpa_ie[200]; - size_t wpa_ie_len; - int use_crypt, ret, i, bssid_changed; - int algs = WPA_AUTH_ALG_OPEN; - unsigned int cipher_pairwise, cipher_group; - struct wpa_driver_associate_params params; - int wep_keys_set = 0; - int assoc_failed = 0; - struct wpa_ssid *old_ssid; - u8 prev_bssid[ETH_ALEN]; -#ifdef CONFIG_HT_OVERRIDES - struct ieee80211_ht_capabilities htcaps; - struct ieee80211_ht_capabilities htcaps_mask; -#endif /* CONFIG_HT_OVERRIDES */ -#ifdef CONFIG_VHT_OVERRIDES - struct ieee80211_vht_capabilities vhtcaps; - struct ieee80211_vht_capabilities vhtcaps_mask; -#endif /* CONFIG_VHT_OVERRIDES */ -#ifdef CONFIG_MBO - const u8 *mbo = NULL; -#endif /* CONFIG_MBO */ + struct fils_hlp_req *req; + size_t rem_len, hdr_len, hlp_len, len, ie_len = 0; + const u8 *pos; + u8 *buf = ie_buf; - if (deinit) { - if (work->started) { - wpa_s->connect_work = NULL; + dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req, + list) { + rem_len = ie_buf_len - ie_len; + pos = wpabuf_head(req->pkt); + hdr_len = 1 + 2 * ETH_ALEN + 6; + hlp_len = wpabuf_len(req->pkt); - /* cancel possible auth. timeout */ - eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, - NULL); + if (rem_len < 2 + hdr_len + hlp_len) { + wpa_printf(MSG_ERROR, + "FILS: Cannot fit HLP - rem_len=%lu to_fill=%lu", + (unsigned long) rem_len, + (unsigned long) (2 + hdr_len + hlp_len)); + break; + } + + len = (hdr_len + hlp_len) > 255 ? 255 : hdr_len + hlp_len; + /* Element ID */ + *buf++ = WLAN_EID_EXTENSION; + /* Length */ + *buf++ = len; + /* Element ID Extension */ + *buf++ = WLAN_EID_EXT_FILS_HLP_CONTAINER; + /* Destination MAC address */ + os_memcpy(buf, req->dst, ETH_ALEN); + buf += ETH_ALEN; + /* Source MAC address */ + os_memcpy(buf, wpa_s->own_addr, ETH_ALEN); + buf += ETH_ALEN; + /* LLC/SNAP Header */ + os_memcpy(buf, "\xaa\xaa\x03\x00\x00\x00", 6); + buf += 6; + /* HLP Packet */ + os_memcpy(buf, pos, len - hdr_len); + buf += len - hdr_len; + pos += len - hdr_len; + + hlp_len -= len - hdr_len; + ie_len += 2 + len; + rem_len -= 2 + len; + + while (hlp_len) { + len = (hlp_len > 255) ? 255 : hlp_len; + if (rem_len < 2 + len) + break; + *buf++ = WLAN_EID_FRAGMENT; + *buf++ = len; + os_memcpy(buf, pos, len); + buf += len; + pos += len; + + hlp_len -= len; + ie_len += 2 + len; + rem_len -= 2 + len; } - wpas_connect_work_free(cwork); - return; } - wpa_s->connect_work = work; + return ie_len; +} - if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid) || - wpas_network_disabled(wpa_s, ssid)) { - wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt"); - wpas_connect_work_done(wpa_s); - return; - } - os_memcpy(prev_bssid, wpa_s->bssid, ETH_ALEN); - os_memset(¶ms, 0, sizeof(params)); - wpa_s->reassociate = 0; - wpa_s->eap_expected_failure = 0; - if (bss && - (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) { -#ifdef CONFIG_IEEE80211R - const u8 *ie, *md = NULL; -#endif /* CONFIG_IEEE80211R */ - wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR - " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid), - wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq); - bssid_changed = !is_zero_ether_addr(wpa_s->bssid); - os_memset(wpa_s->bssid, 0, ETH_ALEN); - os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN); - if (bssid_changed) - wpas_notify_bssid_changed(wpa_s); -#ifdef CONFIG_IEEE80211R - ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN); - if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN) - md = ie + 2; - wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0); - if (md) { - /* Prepare for the next transition */ - wpa_ft_prepare_auth_request(wpa_s->wpa, ie); - } -#endif /* CONFIG_IEEE80211R */ -#ifdef CONFIG_WPS - } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) && - wpa_s->conf->ap_scan == 2 && - (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) { - /* Use ap_scan==1 style network selection to find the network - */ - wpas_connect_work_done(wpa_s); - wpa_s->scan_req = MANUAL_SCAN_REQ; - wpa_s->reassociate = 1; - wpa_supplicant_req_scan(wpa_s, 0, 0); - return; -#endif /* CONFIG_WPS */ - } else { - wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'", - wpa_ssid_txt(ssid->ssid, ssid->ssid_len)); - if (bss) - os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN); - else - os_memset(wpa_s->pending_bssid, 0, ETH_ALEN); - } - if (!wpa_s->pno) - wpa_supplicant_cancel_sched_scan(wpa_s); +int wpa_is_fils_supported(struct wpa_supplicant *wpa_s) +{ + return (((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) && + (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS)) || + (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) && + (wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD))); +} - wpa_supplicant_cancel_scan(wpa_s); - /* Starting new association, so clear the possibly used WPA IE from the - * previous association. */ - wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0); +int wpa_is_fils_sk_pfs_supported(struct wpa_supplicant *wpa_s) +{ +#ifdef CONFIG_FILS_SK_PFS + return (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) && + (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_FILS); +#else /* CONFIG_FILS_SK_PFS */ + return 0; +#endif /* CONFIG_FILS_SK_PFS */ +} -#ifdef IEEE8021X_EAPOL - if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) { - if (ssid->leap) { - if (ssid->non_leap == 0) - algs = WPA_AUTH_ALG_LEAP; - else - algs |= WPA_AUTH_ALG_LEAP; - } +#endif /* CONFIG_FILS */ + + +static u8 * wpas_populate_assoc_ies( + struct wpa_supplicant *wpa_s, + struct wpa_bss *bss, struct wpa_ssid *ssid, + struct wpa_driver_associate_params *params, + enum wpa_drv_update_connect_params_mask *mask) +{ + u8 *wpa_ie; + size_t max_wpa_ie_len = 500; + size_t wpa_ie_len; + int algs = WPA_AUTH_ALG_OPEN; +#ifdef CONFIG_MBO + const u8 *mbo_ie; +#endif +#ifdef CONFIG_SAE + int sae_pmksa_cached = 0; +#endif /* CONFIG_SAE */ +#ifdef CONFIG_FILS + const u8 *realm, *username, *rrk; + size_t realm_len, username_len, rrk_len; + u16 next_seq_num; + struct fils_hlp_req *req; + + dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req, + list) { + max_wpa_ie_len += 3 + 2 * ETH_ALEN + 6 + wpabuf_len(req->pkt) + + 2 + 2 * wpabuf_len(req->pkt) / 255; } -#endif /* IEEE8021X_EAPOL */ - wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs); - if (ssid->auth_alg) { - algs = ssid->auth_alg; - wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: " - "0x%x", algs); +#endif /* CONFIG_FILS */ + + wpa_ie = os_malloc(max_wpa_ie_len); + if (!wpa_ie) { + wpa_printf(MSG_ERROR, + "Failed to allocate connect IE buffer for %lu bytes", + (unsigned long) max_wpa_ie_len); + return NULL; } if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) || wpa_bss_get_ie(bss, WLAN_EID_RSN)) && wpa_key_mgmt_wpa(ssid->key_mgmt)) { int try_opportunistic; + const u8 *cache_id = NULL; + try_opportunistic = (ssid->proactive_key_caching < 0 ? wpa_s->conf->okc : ssid->proactive_key_caching) && (ssid->proto & WPA_PROTO_RSN); +#ifdef CONFIG_FILS + if (wpa_key_mgmt_fils(ssid->key_mgmt)) + cache_id = wpa_bss_get_fils_cache_id(bss); +#endif /* CONFIG_FILS */ if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid, - ssid, try_opportunistic) == 0) + ssid, try_opportunistic, + cache_id, 0) == 0) { eapol_sm_notify_pmkid_attempt(wpa_s->eapol); - wpa_ie_len = sizeof(wpa_ie); +#ifdef CONFIG_SAE + sae_pmksa_cached = 1; +#endif /* CONFIG_SAE */ + } + wpa_ie_len = max_wpa_ie_len; if (wpa_supplicant_set_suites(wpa_s, bss, ssid, wpa_ie, &wpa_ie_len)) { wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA " "key management and encryption suites"); - wpas_connect_work_done(wpa_s); - return; + os_free(wpa_ie); + return NULL; } +#ifdef CONFIG_HS20 + } else if (bss && wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE) && + (ssid->key_mgmt & WPA_KEY_MGMT_OSEN)) { + /* No PMKSA caching, but otherwise similar to RSN/WPA */ + wpa_ie_len = max_wpa_ie_len; + if (wpa_supplicant_set_suites(wpa_s, bss, ssid, + wpa_ie, &wpa_ie_len)) { + wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA " + "key management and encryption suites"); + os_free(wpa_ie); + return NULL; + } +#endif /* CONFIG_HS20 */ } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss && wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) { /* @@ -2238,20 +2601,20 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit) wpa_ie_len = 0; wpa_s->wpa_proto = 0; } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) { - wpa_ie_len = sizeof(wpa_ie); + wpa_ie_len = max_wpa_ie_len; if (wpa_supplicant_set_suites(wpa_s, NULL, ssid, wpa_ie, &wpa_ie_len)) { wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA " "key management and encryption suites (no " "scan results)"); - wpas_connect_work_done(wpa_s); - return; + os_free(wpa_ie); + return NULL; } #ifdef CONFIG_WPS } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) { struct wpabuf *wps_ie; wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid)); - if (wps_ie && wpabuf_len(wps_ie) <= sizeof(wpa_ie)) { + if (wps_ie && wpabuf_len(wps_ie) <= max_wpa_ie_len) { wpa_ie_len = wpabuf_len(wps_ie); os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len); } else @@ -2259,9 +2622,9 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit) wpabuf_free(wps_ie); wpa_supplicant_set_non_wpa_policy(wpa_s, ssid); if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY)) - params.wps = WPS_MODE_PRIVACY; + params->wps = WPS_MODE_PRIVACY; else - params.wps = WPS_MODE_OPEN; + params->wps = WPS_MODE_OPEN; wpa_s->wpa_proto = 0; #endif /* CONFIG_WPS */ } else { @@ -2270,13 +2633,69 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit) wpa_s->wpa_proto = 0; } +#ifdef IEEE8021X_EAPOL + if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) { + if (ssid->leap) { + if (ssid->non_leap == 0) + algs = WPA_AUTH_ALG_LEAP; + else + algs |= WPA_AUTH_ALG_LEAP; + } + } + +#ifdef CONFIG_FILS + /* Clear FILS association */ + wpa_sm_set_reset_fils_completed(wpa_s->wpa, 0); + + if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) && + ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) && + eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap, &username, + &username_len, &realm, &realm_len, + &next_seq_num, &rrk, &rrk_len) == 0 && + (!wpa_s->last_con_fail_realm || + wpa_s->last_con_fail_realm_len != realm_len || + os_memcmp(wpa_s->last_con_fail_realm, realm, realm_len) != 0)) { + algs = WPA_AUTH_ALG_FILS; + params->fils_erp_username = username; + params->fils_erp_username_len = username_len; + params->fils_erp_realm = realm; + params->fils_erp_realm_len = realm_len; + params->fils_erp_next_seq_num = next_seq_num; + params->fils_erp_rrk = rrk; + params->fils_erp_rrk_len = rrk_len; + + if (mask) + *mask |= WPA_DRV_UPDATE_FILS_ERP_INFO; + } +#endif /* CONFIG_FILS */ +#endif /* IEEE8021X_EAPOL */ +#ifdef CONFIG_SAE + if (wpa_s->key_mgmt & (WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE)) + algs = WPA_AUTH_ALG_SAE; +#endif /* CONFIG_SAE */ + + wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs); + if (ssid->auth_alg) { + algs = ssid->auth_alg; + wpa_dbg(wpa_s, MSG_DEBUG, + "Overriding auth_alg selection: 0x%x", algs); + } + +#ifdef CONFIG_SAE + if (sae_pmksa_cached && algs == WPA_AUTH_ALG_SAE) { + wpa_dbg(wpa_s, MSG_DEBUG, + "SAE: Use WPA_AUTH_ALG_OPEN for PMKSA caching attempt"); + algs = WPA_AUTH_ALG_OPEN; + } +#endif /* CONFIG_SAE */ + #ifdef CONFIG_P2P if (wpa_s->global->p2p) { u8 *pos; size_t len; int res; pos = wpa_ie + wpa_ie_len; - len = sizeof(wpa_ie) - wpa_ie_len; + len = max_wpa_ie_len - wpa_ie_len; res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len, ssid->p2p_group); if (res >= 0) @@ -2301,21 +2720,12 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit) os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info)); #endif /* CONFIG_P2P */ -#ifdef CONFIG_MBO if (bss) { - mbo = wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE); - if (mbo) { - int len; - - len = wpas_mbo_supp_op_class_ie(wpa_s, bss->freq, - wpa_ie + wpa_ie_len, - sizeof(wpa_ie) - - wpa_ie_len); - if (len > 0) - wpa_ie_len += len; - } + wpa_ie_len += wpas_supp_op_class_ie(wpa_s, ssid, bss->freq, + wpa_ie + wpa_ie_len, + max_wpa_ie_len - + wpa_ie_len); } -#endif /* CONFIG_MBO */ /* * Workaround: Add Extended Capabilities element only if the AP @@ -2335,7 +2745,8 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit) int ext_capab_len; ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab, sizeof(ext_capab)); - if (ext_capab_len > 0) { + if (ext_capab_len > 0 && + wpa_ie_len + ext_capab_len <= max_wpa_ie_len) { u8 *pos = wpa_ie; if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN) pos += 2 + pos[1]; @@ -2350,13 +2761,15 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit) if (is_hs20_network(wpa_s, ssid, bss)) { struct wpabuf *hs20; - hs20 = wpabuf_alloc(20); + hs20 = wpabuf_alloc(20 + MAX_ROAMING_CONS_OI_LEN); if (hs20) { int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid); size_t len; - wpas_hs20_add_indication(hs20, pps_mo_id); - len = sizeof(wpa_ie) - wpa_ie_len; + wpas_hs20_add_indication(hs20, pps_mo_id, + get_hs20_version(bss)); + wpas_hs20_add_roam_cons_sel(hs20, ssid); + len = max_wpa_ie_len - wpa_ie_len; if (wpabuf_len(hs20) <= len) { os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(hs20), wpabuf_len(hs20)); @@ -2373,7 +2786,7 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit) struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]; size_t len; - len = sizeof(wpa_ie) - wpa_ie_len; + len = max_wpa_ie_len - wpa_ie_len; if (wpabuf_len(buf) <= len) { os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(buf), wpabuf_len(buf)); @@ -2385,7 +2798,7 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit) if (wpa_s->fst_ies) { int fst_ies_len = wpabuf_len(wpa_s->fst_ies); - if (wpa_ie_len + fst_ies_len <= sizeof(wpa_ie)) { + if (wpa_ie_len + fst_ies_len <= max_wpa_ie_len) { os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(wpa_s->fst_ies), fst_ies_len); wpa_ie_len += fst_ies_len; @@ -2394,20 +2807,314 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit) #endif /* CONFIG_FST */ #ifdef CONFIG_MBO - if (mbo) { + mbo_ie = bss ? wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE) : NULL; + if (mbo_ie) { int len; len = wpas_mbo_ie(wpa_s, wpa_ie + wpa_ie_len, - sizeof(wpa_ie) - wpa_ie_len); + max_wpa_ie_len - wpa_ie_len, + !!mbo_attr_from_mbo_ie(mbo_ie, + OCE_ATTR_ID_CAPA_IND)); if (len >= 0) wpa_ie_len += len; } #endif /* CONFIG_MBO */ +#ifdef CONFIG_FILS + if (algs == WPA_AUTH_ALG_FILS) { + size_t len; + + len = wpas_add_fils_hlp_req(wpa_s, wpa_ie + wpa_ie_len, + max_wpa_ie_len - wpa_ie_len); + wpa_ie_len += len; + } +#endif /* CONFIG_FILS */ + +#ifdef CONFIG_OWE +#ifdef CONFIG_TESTING_OPTIONS + if (get_ie_ext(wpa_ie, wpa_ie_len, WLAN_EID_EXT_OWE_DH_PARAM)) { + wpa_printf(MSG_INFO, "TESTING: Override OWE DH element"); + } else +#endif /* CONFIG_TESTING_OPTIONS */ + if (algs == WPA_AUTH_ALG_OPEN && + ssid->key_mgmt == WPA_KEY_MGMT_OWE) { + struct wpabuf *owe_ie; + u16 group; + + if (ssid->owe_group) { + group = ssid->owe_group; + } else if (wpa_s->assoc_status_code == + WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) { + if (wpa_s->last_owe_group == 19) + group = 20; + else if (wpa_s->last_owe_group == 20) + group = 21; + else + group = OWE_DH_GROUP; + } else { + group = OWE_DH_GROUP; + } + + wpa_s->last_owe_group = group; + wpa_printf(MSG_DEBUG, "OWE: Try to use group %u", group); + owe_ie = owe_build_assoc_req(wpa_s->wpa, group); + if (owe_ie && + wpabuf_len(owe_ie) <= max_wpa_ie_len - wpa_ie_len) { + os_memcpy(wpa_ie + wpa_ie_len, + wpabuf_head(owe_ie), wpabuf_len(owe_ie)); + wpa_ie_len += wpabuf_len(owe_ie); + } + wpabuf_free(owe_ie); + } +#endif /* CONFIG_OWE */ + +#ifdef CONFIG_DPP2 + if (wpa_sm_get_key_mgmt(wpa_s->wpa) == WPA_KEY_MGMT_DPP && + ssid->dpp_netaccesskey) { + dpp_pfs_free(wpa_s->dpp_pfs); + wpa_s->dpp_pfs = dpp_pfs_init(ssid->dpp_netaccesskey, + ssid->dpp_netaccesskey_len); + if (!wpa_s->dpp_pfs) { + wpa_printf(MSG_DEBUG, "DPP: Could not initialize PFS"); + /* Try to continue without PFS */ + goto pfs_fail; + } + if (wpabuf_len(wpa_s->dpp_pfs->ie) <= + max_wpa_ie_len - wpa_ie_len) { + os_memcpy(wpa_ie + wpa_ie_len, + wpabuf_head(wpa_s->dpp_pfs->ie), + wpabuf_len(wpa_s->dpp_pfs->ie)); + wpa_ie_len += wpabuf_len(wpa_s->dpp_pfs->ie); + } + } +pfs_fail: +#endif /* CONFIG_DPP2 */ + +#ifdef CONFIG_IEEE80211R + /* + * Add MDIE under these conditions: the network profile allows FT, + * the AP supports FT, and the mobility domain ID matches. + */ + if (bss && wpa_key_mgmt_ft(wpa_sm_get_key_mgmt(wpa_s->wpa))) { + const u8 *mdie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN); + + if (mdie && mdie[1] >= MOBILITY_DOMAIN_ID_LEN) { + size_t len = 0; + const u8 *md = mdie + 2; + const u8 *wpa_md = wpa_sm_get_ft_md(wpa_s->wpa); + + if (os_memcmp(md, wpa_md, + MOBILITY_DOMAIN_ID_LEN) == 0) { + /* Add mobility domain IE */ + len = wpa_ft_add_mdie( + wpa_s->wpa, wpa_ie + wpa_ie_len, + max_wpa_ie_len - wpa_ie_len, mdie); + wpa_ie_len += len; + } +#ifdef CONFIG_SME + if (len > 0 && wpa_s->sme.ft_used && + wpa_sm_has_ptk(wpa_s->wpa)) { + wpa_dbg(wpa_s, MSG_DEBUG, + "SME: Trying to use FT over-the-air"); + algs |= WPA_AUTH_ALG_FT; + } +#endif /* CONFIG_SME */ + } + } +#endif /* CONFIG_IEEE80211R */ + + if (ssid->multi_ap_backhaul_sta) { + size_t multi_ap_ie_len; + + multi_ap_ie_len = add_multi_ap_ie(wpa_ie + wpa_ie_len, + max_wpa_ie_len - wpa_ie_len, + MULTI_AP_BACKHAUL_STA); + if (multi_ap_ie_len == 0) { + wpa_printf(MSG_ERROR, + "Multi-AP: Failed to build Multi-AP IE"); + os_free(wpa_ie); + return NULL; + } + wpa_ie_len += multi_ap_ie_len; + } + + params->wpa_ie = wpa_ie; + params->wpa_ie_len = wpa_ie_len; + params->auth_alg = algs; + if (mask) + *mask |= WPA_DRV_UPDATE_ASSOC_IES | WPA_DRV_UPDATE_AUTH_TYPE; + + return wpa_ie; +} + + +#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL) +static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s) +{ + struct wpa_driver_associate_params params; + enum wpa_drv_update_connect_params_mask mask = 0; + u8 *wpa_ie; + + if (wpa_s->auth_alg != WPA_AUTH_ALG_OPEN) + return; /* nothing to do */ + + os_memset(¶ms, 0, sizeof(params)); + wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss, + wpa_s->current_ssid, ¶ms, &mask); + if (!wpa_ie) + return; + + if (params.auth_alg != WPA_AUTH_ALG_FILS) { + os_free(wpa_ie); + return; + } + + wpa_s->auth_alg = params.auth_alg; + wpa_drv_update_connect_params(wpa_s, ¶ms, mask); + os_free(wpa_ie); +} +#endif /* CONFIG_FILS && IEEE8021X_EAPOL */ + + +#ifdef CONFIG_MBO +void wpas_update_mbo_connect_params(struct wpa_supplicant *wpa_s) +{ + struct wpa_driver_associate_params params; + u8 *wpa_ie; + + /* + * Update MBO connect params only in case of change of MBO attributes + * when connected, if the AP support MBO. + */ + + if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid || + !wpa_s->current_bss || + !wpa_bss_get_vendor_ie(wpa_s->current_bss, MBO_IE_VENDOR_TYPE)) + return; + + os_memset(¶ms, 0, sizeof(params)); + wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss, + wpa_s->current_ssid, ¶ms, NULL); + if (!wpa_ie) + return; + + wpa_drv_update_connect_params(wpa_s, ¶ms, WPA_DRV_UPDATE_ASSOC_IES); + os_free(wpa_ie); +} +#endif /* CONFIG_MBO */ + + +static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit) +{ + struct wpa_connect_work *cwork = work->ctx; + struct wpa_bss *bss = cwork->bss; + struct wpa_ssid *ssid = cwork->ssid; + struct wpa_supplicant *wpa_s = work->wpa_s; + u8 *wpa_ie; + int use_crypt, ret, i, bssid_changed; + unsigned int cipher_pairwise, cipher_group, cipher_group_mgmt; + struct wpa_driver_associate_params params; + int wep_keys_set = 0; + int assoc_failed = 0; + struct wpa_ssid *old_ssid; + u8 prev_bssid[ETH_ALEN]; +#ifdef CONFIG_HT_OVERRIDES + struct ieee80211_ht_capabilities htcaps; + struct ieee80211_ht_capabilities htcaps_mask; +#endif /* CONFIG_HT_OVERRIDES */ +#ifdef CONFIG_VHT_OVERRIDES + struct ieee80211_vht_capabilities vhtcaps; + struct ieee80211_vht_capabilities vhtcaps_mask; +#endif /* CONFIG_VHT_OVERRIDES */ + + if (deinit) { + if (work->started) { + wpa_s->connect_work = NULL; + + /* cancel possible auth. timeout */ + eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, + NULL); + } + wpas_connect_work_free(cwork); + return; + } + + wpa_s->connect_work = work; + + if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid) || + wpas_network_disabled(wpa_s, ssid)) { + wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt"); + wpas_connect_work_done(wpa_s); + return; + } + + os_memcpy(prev_bssid, wpa_s->bssid, ETH_ALEN); + os_memset(¶ms, 0, sizeof(params)); + wpa_s->reassociate = 0; + wpa_s->eap_expected_failure = 0; + if (bss && + (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) { +#ifdef CONFIG_IEEE80211R + const u8 *ie, *md = NULL; +#endif /* CONFIG_IEEE80211R */ + wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR + " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid), + wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq); + bssid_changed = !is_zero_ether_addr(wpa_s->bssid); + os_memset(wpa_s->bssid, 0, ETH_ALEN); + os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN); + if (bssid_changed) + wpas_notify_bssid_changed(wpa_s); +#ifdef CONFIG_IEEE80211R + ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN); + if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN) + md = ie + 2; + wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0); + if (md) { + /* Prepare for the next transition */ + wpa_ft_prepare_auth_request(wpa_s->wpa, ie); + } +#endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_WPS + } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) && + wpa_s->conf->ap_scan == 2 && + (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) { + /* Use ap_scan==1 style network selection to find the network + */ + wpas_connect_work_done(wpa_s); + wpa_s->scan_req = MANUAL_SCAN_REQ; + wpa_s->reassociate = 1; + wpa_supplicant_req_scan(wpa_s, 0, 0); + return; +#endif /* CONFIG_WPS */ + } else { + wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'", + wpa_ssid_txt(ssid->ssid, ssid->ssid_len)); + if (bss) + os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN); + else + os_memset(wpa_s->pending_bssid, 0, ETH_ALEN); + } + if (!wpa_s->pno) + wpa_supplicant_cancel_sched_scan(wpa_s); + + wpa_supplicant_cancel_scan(wpa_s); + + /* Starting new association, so clear the possibly used WPA IE from the + * previous association. */ + wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0); + + wpa_ie = wpas_populate_assoc_ies(wpa_s, bss, ssid, ¶ms, NULL); + if (!wpa_ie) { + wpas_connect_work_done(wpa_s); + return; + } + wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL); use_crypt = 1; cipher_pairwise = wpa_s->pairwise_cipher; cipher_group = wpa_s->group_cipher; + cipher_group_mgmt = wpa_s->mgmt_group_cipher; if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE || wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) { if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) @@ -2445,12 +3152,14 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit) if (bss) { params.ssid = bss->ssid; params.ssid_len = bss->ssid_len; - if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) { + if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set || + wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) { wpa_printf(MSG_DEBUG, "Limit connection to BSSID " MACSTR " freq=%u MHz based on scan results " - "(bssid_set=%d)", + "(bssid_set=%d wps=%d)", MAC2STR(bss->bssid), bss->freq, - ssid->bssid_set); + ssid->bssid_set, + wpa_s->key_mgmt == WPA_KEY_MGMT_WPS); params.bssid = bss->bssid; params.freq.freq = bss->freq; } @@ -2458,6 +3167,9 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit) params.freq_hint = bss->freq; params.pbss = bss_is_pbss(bss); } else { + if (ssid->bssid_hint_set) + params.bssid_hint = ssid->bssid_hint; + params.ssid = ssid->ssid; params.ssid_len = ssid->ssid_len; params.pbss = (ssid->pbss != 2) ? ssid->pbss : 0; @@ -2482,13 +3194,12 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit) params.beacon_int = wpa_s->conf->beacon_int; } - params.wpa_ie = wpa_ie; - params.wpa_ie_len = wpa_ie_len; params.pairwise_suite = cipher_pairwise; params.group_suite = cipher_group; + params.mgmt_group_suite = cipher_group_mgmt; params.key_mgmt_suite = wpa_s->key_mgmt; params.wpa_proto = wpa_s->wpa_proto; - params.auth_alg = algs; + wpa_s->auth_alg = params.auth_alg; params.mode = ssid->mode; params.bg_scan_period = ssid->bg_scan_period; for (i = 0; i < NUM_WEP_KEYS; i++) { @@ -2498,7 +3209,7 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit) } params.wep_tx_keyidx = ssid->wep_tx_keyidx; - if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) && + if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) && (params.key_mgmt_suite == WPA_KEY_MGMT_PSK || params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) { params.passphrase = ssid->passphrase; @@ -2506,6 +3217,13 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit) params.psk = ssid->psk; } + if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X) && + (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X || + params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 || + params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B || + params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)) + params.req_key_mgmt_offload = 1; + if (wpa_s->conf->key_mgmt_offload) { if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X || params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 || @@ -2538,6 +3256,11 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit) "MFP: require MFP"); params.mgmt_frame_protection = MGMT_FRAME_PROTECTION_REQUIRED; +#ifdef CONFIG_OWE + } else if (!rsn && (ssid->key_mgmt & WPA_KEY_MGMT_OWE) && + !ssid->owe_only) { + params.mgmt_frame_protection = NO_MGMT_FRAME_PROTECTION; +#endif /* CONFIG_OWE */ } } #endif /* CONFIG_IEEE80211W */ @@ -2580,6 +3303,7 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit) if (wpas_p2p_handle_frequency_conflicts( wpa_s, params.freq.freq, ssid) < 0) { wpas_connect_work_done(wpa_s); + os_free(wpa_ie); return; } } @@ -2591,6 +3315,7 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit) params.prev_bssid = prev_bssid; ret = wpa_drv_associate(wpa_s, ¶ms); + os_free(wpa_ie); if (ret < 0) { wpa_msg(wpa_s, MSG_INFO, "Association request to the driver " "failed"); @@ -2726,14 +3451,22 @@ void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s, zero_addr = 1; } + if (wpa_s->enabled_4addr_mode && wpa_drv_set_4addr_mode(wpa_s, 0) == 0) + wpa_s->enabled_4addr_mode = 0; + #ifdef CONFIG_TDLS wpa_tdls_teardown_peers(wpa_s->wpa); #endif /* CONFIG_TDLS */ #ifdef CONFIG_MESH if (wpa_s->ifmsh) { + struct mesh_conf *mconf; + + mconf = wpa_s->ifmsh->mconf; wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s", wpa_s->ifname); + wpas_notify_mesh_group_removed(wpa_s, mconf->meshid, + mconf->meshid_len, reason_code); wpa_supplicant_leave_mesh(wpa_s); } #endif /* CONFIG_MESH */ @@ -2758,6 +3491,7 @@ static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s, return; ssid->disabled = 0; + ssid->owe_transition_bss_select_count = 0; wpas_clear_temp_disabled(wpa_s, ssid, 1); wpas_notify_network_enabled_changed(wpa_s, ssid); @@ -2923,13 +3657,19 @@ void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s, wpas_notify_network_enabled_changed( wpa_s, other_ssid); } - if (wpa_s->current_ssid) + if (wpa_s->current_ssid) { + if (wpa_s->wpa_state >= WPA_AUTHENTICATING) + wpa_s->own_disconnect_req = 1; wpa_supplicant_deauthenticate( wpa_s, WLAN_REASON_DEAUTH_LEAVING); + } } else if (ssid->disabled != 2) { - if (ssid == wpa_s->current_ssid) + if (ssid == wpa_s->current_ssid) { + if (wpa_s->wpa_state >= WPA_AUTHENTICATING) + wpa_s->own_disconnect_req = 1; wpa_supplicant_deauthenticate( wpa_s, WLAN_REASON_DEAUTH_LEAVING); + } was_disabled = ssid->disabled; @@ -3015,6 +3755,9 @@ void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s, wpa_s->disconnected = 0; wpa_s->reassociate = 1; + wpa_s->last_owe_group = 0; + if (ssid) + ssid->owe_transition_bss_select_count = 0; if (wpa_s->connect_without_scan || wpa_supplicant_fast_associate(wpa_s) != 1) { @@ -3232,6 +3975,41 @@ int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level, } +#ifdef CONFIG_OWE +static int owe_trans_ssid_match(struct wpa_supplicant *wpa_s, const u8 *bssid, + const u8 *entry_ssid, size_t entry_ssid_len) +{ + const u8 *owe, *pos, *end; + u8 ssid_len; + struct wpa_bss *bss; + + /* Check network profile SSID aganst the SSID in the + * OWE Transition Mode element. */ + + bss = wpa_bss_get_bssid_latest(wpa_s, bssid); + if (!bss) + return 0; + + owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE); + if (!owe) + return 0; + + pos = owe + 6; + end = owe + 2 + owe[1]; + + if (end - pos < ETH_ALEN + 1) + return 0; + pos += ETH_ALEN; + ssid_len = *pos++; + if (end - pos < ssid_len || ssid_len > SSID_MAX_LEN) + return 0; + + return entry_ssid_len == ssid_len && + os_memcmp(pos, entry_ssid, ssid_len) == 0; +} +#endif /* CONFIG_OWE */ + + /** * wpa_supplicant_get_ssid - Get a pointer to the current network structure * @wpa_s: Pointer to wpa_supplicant data @@ -3267,7 +4045,9 @@ struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s) while (entry) { if (!wpas_network_disabled(wpa_s, entry) && ((ssid_len == entry->ssid_len && - os_memcmp(ssid, entry->ssid, ssid_len) == 0) || wired) && + (!entry->ssid || + os_memcmp(ssid, entry->ssid, ssid_len) == 0)) || + wired) && (!entry->bssid_set || os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)) return entry; @@ -3280,6 +4060,15 @@ struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s) return entry; #endif /* CONFIG_WPS */ +#ifdef CONFIG_OWE + if (!wpas_network_disabled(wpa_s, entry) && + owe_trans_ssid_match(wpa_s, bssid, entry->ssid, + entry->ssid_len) && + (!entry->bssid_set || + os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)) + return entry; +#endif /* CONFIG_OWE */ + if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set && entry->ssid_len == 0 && os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0) @@ -3387,16 +4176,6 @@ void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr, } #endif /* CONFIG_TESTING_OPTIONS */ -#ifdef CONFIG_PEERKEY - if (wpa_s->wpa_state > WPA_ASSOCIATED && wpa_s->current_ssid && - wpa_s->current_ssid->peerkey && - !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) && - wpa_sm_rx_eapol_peerkey(wpa_s->wpa, src_addr, buf, len) == 1) { - wpa_dbg(wpa_s, MSG_DEBUG, "RSN: Processed PeerKey EAPOL-Key"); - return; - } -#endif /* CONFIG_PEERKEY */ - if (wpa_s->wpa_state < WPA_ASSOCIATED || (wpa_s->last_eapol_matches_bssid && #ifdef CONFIG_AP @@ -3446,7 +4225,7 @@ void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr, } if (wpa_s->eapol_received == 0 && - (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) || + (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) || !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) || wpa_s->wpa_state != WPA_COMPLETED) && (wpa_s->current_ssid == NULL || @@ -3507,10 +4286,12 @@ void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr, os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN); if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) && + wpa_s->key_mgmt != WPA_KEY_MGMT_OWE && + wpa_s->key_mgmt != WPA_KEY_MGMT_DPP && eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0) return; wpa_drv_poll(wpa_s); - if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE)) + if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK)) wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len); else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) { /* @@ -3536,6 +4317,11 @@ int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s) wpa_supplicant_rx_eapol, wpa_s, 0); if (wpa_s->l2 == NULL) return -1; + + if (l2_packet_set_packet_filter(wpa_s->l2, + L2_PACKET_FILTER_PKTTYPE)) + wpa_dbg(wpa_s, MSG_DEBUG, + "Failed to attach pkt_type filter"); } else { const u8 *addr = wpa_drv_get_mac_addr(wpa_s); if (addr) @@ -3675,6 +4461,7 @@ wpa_supplicant_alloc(struct wpa_supplicant *parent) wpa_s->sched_scanning = 0; dl_list_init(&wpa_s->bss_tmp_disallowed); + dl_list_init(&wpa_s->fils_hlp_req); return wpa_s; } @@ -3702,8 +4489,11 @@ static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s, wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs); for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) { + long v; + errno = 0; - long v = strtol(tmp, &end, 16); + v = strtol(tmp, &end, 16); + if (errno == 0) { wpa_msg(wpa_s, MSG_DEBUG, "htcap value[%i]: %ld end: %p tmp: %p", @@ -3743,11 +4533,11 @@ static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s, { le16 msk; - wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled); - if (disabled == -1) return 0; + wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled); + msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE); htcaps_mask->ht_capabilities_info |= msk; if (disabled) @@ -3764,11 +4554,11 @@ static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s, struct ieee80211_ht_capabilities *htcaps_mask, int factor) { - wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor); - if (factor == -1) return 0; + wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor); + if (factor < 0 || factor > 3) { wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. " "Must be 0-3 or -1", factor); @@ -3788,11 +4578,11 @@ static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s, struct ieee80211_ht_capabilities *htcaps_mask, int density) { - wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density); - if (density == -1) return 0; + wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density); + if (density < 0 || density > 7) { wpa_msg(wpa_s, MSG_ERROR, "ampdu_density: %d out of range. Must be 0-7 or -1.", @@ -3813,18 +4603,11 @@ static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s, struct ieee80211_ht_capabilities *htcaps_mask, int disabled) { - /* Masking these out disables HT40 */ - le16 msk = host_to_le16(HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET | - HT_CAP_INFO_SHORT_GI40MHZ); - - wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled); - if (disabled) - htcaps->ht_capabilities_info &= ~msk; - else - htcaps->ht_capabilities_info |= msk; + wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled); - htcaps_mask->ht_capabilities_info |= msk; + set_disable_ht40(htcaps, disabled); + set_disable_ht40(htcaps_mask, 0); return 0; } @@ -3839,7 +4622,8 @@ static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s, le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ | HT_CAP_INFO_SHORT_GI40MHZ); - wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled); + if (disabled) + wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled); if (disabled) htcaps->ht_capabilities_info &= ~msk; @@ -3860,7 +4644,8 @@ static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s, /* Masking these out disables LDPC */ le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP); - wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled); + if (disabled) + wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled); if (disabled) htcaps->ht_capabilities_info &= ~msk; @@ -3873,6 +4658,58 @@ static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s, } +static int wpa_set_tx_stbc(struct wpa_supplicant *wpa_s, + struct ieee80211_ht_capabilities *htcaps, + struct ieee80211_ht_capabilities *htcaps_mask, + int tx_stbc) +{ + le16 msk = host_to_le16(HT_CAP_INFO_TX_STBC); + + if (tx_stbc == -1) + return 0; + + wpa_msg(wpa_s, MSG_DEBUG, "set_tx_stbc: %d", tx_stbc); + + if (tx_stbc < 0 || tx_stbc > 1) { + wpa_msg(wpa_s, MSG_ERROR, + "tx_stbc: %d out of range. Must be 0-1 or -1", tx_stbc); + return -EINVAL; + } + + htcaps_mask->ht_capabilities_info |= msk; + htcaps->ht_capabilities_info &= ~msk; + htcaps->ht_capabilities_info |= (tx_stbc << 7) & msk; + + return 0; +} + + +static int wpa_set_rx_stbc(struct wpa_supplicant *wpa_s, + struct ieee80211_ht_capabilities *htcaps, + struct ieee80211_ht_capabilities *htcaps_mask, + int rx_stbc) +{ + le16 msk = host_to_le16(HT_CAP_INFO_RX_STBC_MASK); + + if (rx_stbc == -1) + return 0; + + wpa_msg(wpa_s, MSG_DEBUG, "set_rx_stbc: %d", rx_stbc); + + if (rx_stbc < 0 || rx_stbc > 3) { + wpa_msg(wpa_s, MSG_ERROR, + "rx_stbc: %d out of range. Must be 0-3 or -1", rx_stbc); + return -EINVAL; + } + + htcaps_mask->ht_capabilities_info |= msk; + htcaps->ht_capabilities_info &= ~msk; + htcaps->ht_capabilities_info |= (rx_stbc << 8) & msk; + + return 0; +} + + void wpa_supplicant_apply_ht_overrides( struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, struct wpa_driver_associate_params *params) @@ -3897,6 +4734,8 @@ void wpa_supplicant_apply_ht_overrides( wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40); wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi); wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc); + wpa_set_rx_stbc(wpa_s, htcaps, htcaps_mask, ssid->rx_stbc); + wpa_set_tx_stbc(wpa_s, htcaps, htcaps_mask, ssid->tx_stbc); if (ssid->ht40_intolerant) { le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT); @@ -3931,6 +4770,16 @@ void wpa_supplicant_apply_vht_overrides( vhtcaps_mask->vht_capabilities_info = host_to_le32(ssid->vht_capa_mask); #ifdef CONFIG_HT_OVERRIDES + if (ssid->disable_sgi) { + vhtcaps_mask->vht_capabilities_info |= (VHT_CAP_SHORT_GI_80 | + VHT_CAP_SHORT_GI_160); + vhtcaps->vht_capabilities_info &= ~(VHT_CAP_SHORT_GI_80 | + VHT_CAP_SHORT_GI_160); + wpa_msg(wpa_s, MSG_DEBUG, + "disable-sgi override specified, vht-caps: 0x%x", + vhtcaps->vht_capabilities_info); + } + /* if max ampdu is <= 3, we have to make the HT cap the same */ if (ssid->vht_capa_mask & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) { int max_ampdu; @@ -4100,10 +4949,14 @@ static int wpas_fst_send_action_cb(void *ctx, const u8 *da, struct wpabuf *data) { struct wpa_supplicant *wpa_s = ctx; - WPA_ASSERT(os_memcmp(wpa_s->bssid, da, ETH_ALEN) == 0); + if (os_memcmp(wpa_s->bssid, da, ETH_ALEN) != 0) { + wpa_printf(MSG_INFO, "FST:%s:bssid=" MACSTR " != da=" MACSTR, + __func__, MAC2STR(wpa_s->bssid), MAC2STR(da)); + return -1; + } return wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid, - wpa_s->own_addr, wpa_s->bssid, - wpabuf_head(data), wpabuf_len(data), + wpa_s->own_addr, wpa_s->bssid, + wpabuf_head(data), wpabuf_len(data), 0); } @@ -4291,7 +5144,7 @@ static void radio_work_free(struct wpa_radio_work *work) if (work->started) { work->wpa_s->radio->num_active_works--; wpa_dbg(work->wpa_s, MSG_DEBUG, - "radio_work_free('%s'@%p: num_active_works --> %u", + "radio_work_free('%s'@%p): num_active_works --> %u", work->type, work, work->wpa_s->radio->num_active_works); } @@ -4301,6 +5154,20 @@ static void radio_work_free(struct wpa_radio_work *work) } +static int radio_work_is_connect(struct wpa_radio_work *work) +{ + return os_strcmp(work->type, "sme-connect") == 0 || + os_strcmp(work->type, "connect") == 0; +} + + +static int radio_work_is_scan(struct wpa_radio_work *work) +{ + return os_strcmp(work->type, "scan") == 0 || + os_strcmp(work->type, "p2p-scan") == 0; +} + + static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio) { struct wpa_radio_work *active_work = NULL; @@ -4330,8 +5197,7 @@ static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio) return NULL; } - if (os_strcmp(active_work->type, "sme-connect") == 0 || - os_strcmp(active_work->type, "connect") == 0) { + if (radio_work_is_connect(active_work)) { /* * If the active work is either connect or sme-connect, * do not parallelize them with other radio works. @@ -4350,10 +5216,20 @@ static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio) * If connect or sme-connect are enqueued, parallelize only * those operations ahead of them in the queue. */ - if (os_strcmp(tmp->type, "connect") == 0 || - os_strcmp(tmp->type, "sme-connect") == 0) + if (radio_work_is_connect(tmp)) break; + /* Serialize parallel scan and p2p_scan operations on the same + * interface since the driver_nl80211 mechanism for tracking + * scan cookies does not yet have support for this. */ + if (active_work->wpa_s == tmp->wpa_s && + radio_work_is_scan(active_work) && + radio_work_is_scan(tmp)) { + wpa_dbg(active_work->wpa_s, MSG_DEBUG, + "Do not start work '%s' when another work '%s' is already scheduled", + tmp->type, active_work->type); + continue; + } /* * Check that the radio works are distinct and * on different bands. @@ -4475,6 +5351,22 @@ void radio_remove_works(struct wpa_supplicant *wpa_s, } +void radio_remove_pending_work(struct wpa_supplicant *wpa_s, void *ctx) +{ + struct wpa_radio_work *work; + struct wpa_radio *radio = wpa_s->radio; + + dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) { + if (work->ctx != ctx) + continue; + wpa_dbg(wpa_s, MSG_DEBUG, "Free pending radio work '%s'@%p%s", + work->type, work, work->started ? " (started)" : ""); + radio_work_free(work); + break; + } +} + + static void radio_remove_interface(struct wpa_supplicant *wpa_s) { struct wpa_radio *radio = wpa_s->radio; @@ -4627,7 +5519,7 @@ radio_work_pending(struct wpa_supplicant *wpa_s, const char *type) static int wpas_init_driver(struct wpa_supplicant *wpa_s, - struct wpa_interface *iface) + const struct wpa_interface *iface) { const char *ifname, *driver, *rn; @@ -4675,11 +5567,47 @@ next_driver: } +#ifdef CONFIG_GAS_SERVER + +static void wpas_gas_server_tx_status(struct wpa_supplicant *wpa_s, + unsigned int freq, const u8 *dst, + const u8 *src, const u8 *bssid, + const u8 *data, size_t data_len, + enum offchannel_send_action_result result) +{ + wpa_printf(MSG_DEBUG, "GAS: TX status: freq=%u dst=" MACSTR + " result=%s", + freq, MAC2STR(dst), + result == OFFCHANNEL_SEND_ACTION_SUCCESS ? "SUCCESS" : + (result == OFFCHANNEL_SEND_ACTION_NO_ACK ? "no-ACK" : + "FAILED")); + gas_server_tx_status(wpa_s->gas_server, dst, data, data_len, + result == OFFCHANNEL_SEND_ACTION_SUCCESS); +} + + +static void wpas_gas_server_tx(void *ctx, int freq, const u8 *da, + struct wpabuf *buf, unsigned int wait_time) +{ + struct wpa_supplicant *wpa_s = ctx; + const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + + if (wait_time > wpa_s->max_remain_on_chan) + wait_time = wpa_s->max_remain_on_chan; + + offchannel_send_action(wpa_s, freq, da, wpa_s->own_addr, broadcast, + wpabuf_head(buf), wpabuf_len(buf), + wait_time, wpas_gas_server_tx_status, 0); +} + +#endif /* CONFIG_GAS_SERVER */ + static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s, - struct wpa_interface *iface) + const struct wpa_interface *iface) { struct wpa_driver_capa capa; int capa_res; + u8 dfs_domain; wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver " "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname, @@ -4709,7 +5637,13 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s, return -1; } wpa_s->confanother = os_rel2abs_path(iface->confanother); - wpa_config_read(wpa_s->confanother, wpa_s->conf); + if (wpa_s->confanother && + !wpa_config_read(wpa_s->confanother, wpa_s->conf)) { + wpa_printf(MSG_ERROR, + "Failed to read or parse configuration '%s'.", + wpa_s->confanother); + return -1; + } /* * Override ctrl_interface and driver_param if set on command @@ -4807,7 +5741,8 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s, wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s, &wpa_s->hw.num_modes, - &wpa_s->hw.flags); + &wpa_s->hw.flags, + &dfs_domain); if (wpa_s->hw.modes) { u16 i; @@ -4858,6 +5793,12 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s, capa.mac_addr_rand_sched_scan_supported) wpa_s->mac_addr_rand_supported |= (MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO); + + wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION); + if (wpa_s->extended_capa && + wpa_s->extended_capa_len >= 3 && + wpa_s->extended_capa[2] & 0x40) + wpa_s->multi_bss_support = 1; } if (wpa_s->max_remain_on_chan == 0) wpa_s->max_remain_on_chan = 1000; @@ -4869,8 +5810,6 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s, */ if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) wpa_s->p2p_mgmt = iface->p2p_mgmt; - else - iface->p2p_mgmt = 1; if (wpa_s->num_multichan_concurrent == 0) wpa_s->num_multichan_concurrent = 1; @@ -4879,10 +5818,7 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s, return -1; #ifdef CONFIG_TDLS - if ((!iface->p2p_mgmt || - !(wpa_s->drv_flags & - WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) && - wpa_tdls_init(wpa_s->wpa)) + if (!iface->p2p_mgmt && wpa_tdls_init(wpa_s->wpa)) return -1; #endif /* CONFIG_TDLS */ @@ -4917,6 +5853,19 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s, if (wpas_wps_init(wpa_s)) return -1; +#ifdef CONFIG_GAS_SERVER + wpa_s->gas_server = gas_server_init(wpa_s, wpas_gas_server_tx); + if (!wpa_s->gas_server) { + wpa_printf(MSG_ERROR, "Failed to initialize GAS server"); + return -1; + } +#endif /* CONFIG_GAS_SERVER */ + +#ifdef CONFIG_DPP + if (wpas_dpp_init(wpa_s) < 0) + return -1; +#endif /* CONFIG_DPP */ + if (wpa_supplicant_init_eapol(wpa_s) < 0) return -1; wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol); @@ -4941,7 +5890,9 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s, return -1; } - if (iface->p2p_mgmt && wpas_p2p_init(wpa_s->global, wpa_s) < 0) { + if ((!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) || + wpa_s->p2p_mgmt) && + wpas_p2p_init(wpa_s->global, wpa_s) < 0) { wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P"); return -1; } @@ -4949,6 +5900,12 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s, if (wpa_bss_init(wpa_s) < 0) return -1; +#ifdef CONFIG_PMKSA_CACHE_EXTERNAL +#ifdef CONFIG_MESH + dl_list_init(&wpa_s->mesh_external_pmksa_cache); +#endif /* CONFIG_MESH */ +#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */ + /* * Set Wake-on-WLAN triggers, if configured. * Note: We don't restore/remove the triggers on shutdown (it doesn't @@ -4960,8 +5917,8 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s, #ifdef CONFIG_EAP_PROXY { size_t len; - wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, wpa_s->imsi, - &len); + wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, -1, + wpa_s->imsi, &len); if (wpa_s->mnc_len > 0) { wpa_s->imsi[len] = '\0'; wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)", @@ -4986,6 +5943,17 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s, hs20_init(wpa_s); #endif /* CONFIG_HS20 */ #ifdef CONFIG_MBO + if (wpa_s->conf->oce) { + if ((wpa_s->conf->oce & OCE_STA) && + (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA)) + wpa_s->enable_oce = OCE_STA; + if ((wpa_s->conf->oce & OCE_STA_CFON) && + (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OCE_STA_CFON)) { + /* TODO: Need to add STA-CFON support */ + wpa_printf(MSG_ERROR, + "OCE STA-CFON feature is not yet supported"); + } + } wpas_mbo_update_non_pref_chan(wpa_s, wpa_s->conf->non_pref_chan); #endif /* CONFIG_MBO */ @@ -5250,6 +6218,7 @@ int wpa_supplicant_remove_iface(struct wpa_global *global, #ifdef CONFIG_MESH unsigned int mesh_if_created = wpa_s->mesh_if_created; char *ifname = NULL; + struct wpa_supplicant *parent = wpa_s->parent; #endif /* CONFIG_MESH */ /* Remove interface from the global list of interfaces */ @@ -5285,7 +6254,7 @@ int wpa_supplicant_remove_iface(struct wpa_global *global, #ifdef CONFIG_MESH if (mesh_if_created) { - wpa_drv_if_remove(global->ifaces, WPA_IF_MESH, ifname); + wpa_drv_if_remove(parent, WPA_IF_MESH, ifname); os_free(ifname); } #endif /* CONFIG_MESH */ @@ -5390,13 +6359,6 @@ struct wpa_global * wpa_supplicant_init(struct wpa_params *params) if (params == NULL) return NULL; -#ifdef CONFIG_DRIVER_NDIS - { - void driver_ndis_init_ops(void); - driver_ndis_init_ops(); - } -#endif /* CONFIG_DRIVER_NDIS */ - #ifndef CONFIG_NO_WPA_MSG wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb); #endif /* CONFIG_NO_WPA_MSG */ @@ -5649,6 +6611,16 @@ void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s) if (wpa_s->conf->changed_parameters & CFG_CHANGED_SCHED_SCAN_PLANS) wpas_sched_scan_plans_set(wpa_s, wpa_s->conf->sched_scan_plans); + if (wpa_s->conf->changed_parameters & CFG_CHANGED_WOWLAN_TRIGGERS) { + struct wpa_driver_capa capa; + int res = wpa_drv_get_capa(wpa_s, &capa); + + if (res == 0 && wpas_set_wowlan_triggers(wpa_s, &capa) < 0) + wpa_printf(MSG_ERROR, + "Failed to update wowlan_triggers to '%s'", + wpa_s->conf->wowlan_triggers); + } + #ifdef CONFIG_WPS wpas_wps_update_config(wpa_s); #endif /* CONFIG_WPS */ @@ -5803,11 +6775,43 @@ void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid) * TODO: if more than one possible AP is available in scan results, * could try the other ones before requesting a new scan. */ + + /* speed up the connection attempt with normal scan */ + wpa_s->normal_scans = 0; wpa_supplicant_req_scan(wpa_s, timeout / 1000, 1000 * (timeout % 1000)); } +#ifdef CONFIG_FILS +void fils_connection_failure(struct wpa_supplicant *wpa_s) +{ + struct wpa_ssid *ssid = wpa_s->current_ssid; + const u8 *realm, *username, *rrk; + size_t realm_len, username_len, rrk_len; + u16 next_seq_num; + + if (!ssid || !ssid->eap.erp || !wpa_key_mgmt_fils(ssid->key_mgmt) || + eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap, + &username, &username_len, + &realm, &realm_len, &next_seq_num, + &rrk, &rrk_len) != 0 || + !realm) + return; + + wpa_hexdump_ascii(MSG_DEBUG, + "FILS: Store last connection failure realm", + realm, realm_len); + os_free(wpa_s->last_con_fail_realm); + wpa_s->last_con_fail_realm = os_malloc(realm_len); + if (wpa_s->last_con_fail_realm) { + wpa_s->last_con_fail_realm_len = realm_len; + os_memcpy(wpa_s->last_con_fail_realm, realm, realm_len); + } +} +#endif /* CONFIG_FILS */ + + int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s) { return wpa_s->conf->ap_scan == 2 || @@ -5878,6 +6882,7 @@ int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s, case WPA_CTRL_REQ_SIM: str_clear_free(eap->external_sim_resp); eap->external_sim_resp = os_strdup(value); + eap->pending_req_sim = 0; break; case WPA_CTRL_REQ_PSK_PASSPHRASE: if (wpa_config_set(ssid, "psk", value, 0) < 0) @@ -5946,6 +6951,7 @@ int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid) if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set && (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk && + !(wpa_key_mgmt_sae(ssid->key_mgmt) && ssid->sae_password) && !ssid->mem_only_psk) return 1; @@ -6130,6 +7136,7 @@ void wpas_request_connection(struct wpa_supplicant *wpa_s) wpa_s->extra_blacklist_count = 0; wpa_s->disconnected = 0; wpa_s->reassociate = 1; + wpa_s->last_owe_group = 0; if (wpa_supplicant_fast_associate(wpa_s) != 1) wpa_supplicant_req_scan(wpa_s, 0, 0); @@ -6156,6 +7163,8 @@ void wpas_request_disconnection(struct wpa_supplicant *wpa_s) wpa_supplicant_cancel_scan(wpa_s); wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING); eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL); + radio_remove_works(wpa_s, "connect", 0); + radio_remove_works(wpa_s, "sme-connect", 0); } @@ -6256,489 +7265,6 @@ int get_shared_radio_freqs(struct wpa_supplicant *wpa_s, } -static void wpas_rrm_neighbor_rep_timeout_handler(void *data, void *user_ctx) -{ - struct rrm_data *rrm = data; - - if (!rrm->notify_neighbor_rep) { - wpa_printf(MSG_ERROR, - "RRM: Unexpected neighbor report timeout"); - return; - } - - wpa_printf(MSG_DEBUG, "RRM: Notifying neighbor report - NONE"); - rrm->notify_neighbor_rep(rrm->neighbor_rep_cb_ctx, NULL); - - rrm->notify_neighbor_rep = NULL; - rrm->neighbor_rep_cb_ctx = NULL; -} - - -/* - * wpas_rrm_reset - Clear and reset all RRM data in wpa_supplicant - * @wpa_s: Pointer to wpa_supplicant - */ -void wpas_rrm_reset(struct wpa_supplicant *wpa_s) -{ - wpa_s->rrm.rrm_used = 0; - - eloop_cancel_timeout(wpas_rrm_neighbor_rep_timeout_handler, &wpa_s->rrm, - NULL); - if (wpa_s->rrm.notify_neighbor_rep) - wpas_rrm_neighbor_rep_timeout_handler(&wpa_s->rrm, NULL); - wpa_s->rrm.next_neighbor_rep_token = 1; -} - - -/* - * wpas_rrm_process_neighbor_rep - Handle incoming neighbor report - * @wpa_s: Pointer to wpa_supplicant - * @report: Neighbor report buffer, prefixed by a 1-byte dialog token - * @report_len: Length of neighbor report buffer - */ -void wpas_rrm_process_neighbor_rep(struct wpa_supplicant *wpa_s, - const u8 *report, size_t report_len) -{ - struct wpabuf *neighbor_rep; - - wpa_hexdump(MSG_DEBUG, "RRM: New Neighbor Report", report, report_len); - if (report_len < 1) - return; - - if (report[0] != wpa_s->rrm.next_neighbor_rep_token - 1) { - wpa_printf(MSG_DEBUG, - "RRM: Discarding neighbor report with token %d (expected %d)", - report[0], wpa_s->rrm.next_neighbor_rep_token - 1); - return; - } - - eloop_cancel_timeout(wpas_rrm_neighbor_rep_timeout_handler, &wpa_s->rrm, - NULL); - - if (!wpa_s->rrm.notify_neighbor_rep) { - wpa_printf(MSG_ERROR, "RRM: Unexpected neighbor report"); - return; - } - - /* skipping the first byte, which is only an id (dialog token) */ - neighbor_rep = wpabuf_alloc(report_len - 1); - if (neighbor_rep == NULL) - return; - wpabuf_put_data(neighbor_rep, report + 1, report_len - 1); - wpa_printf(MSG_DEBUG, "RRM: Notifying neighbor report (token = %d)", - report[0]); - wpa_s->rrm.notify_neighbor_rep(wpa_s->rrm.neighbor_rep_cb_ctx, - neighbor_rep); - wpa_s->rrm.notify_neighbor_rep = NULL; - wpa_s->rrm.neighbor_rep_cb_ctx = NULL; -} - - -#if defined(__CYGWIN__) || defined(CONFIG_NATIVE_WINDOWS) -/* Workaround different, undefined for Windows, error codes used here */ -#define ENOTCONN -1 -#define EOPNOTSUPP -1 -#define ECANCELED -1 -#endif - -/* Measurement Request element + Location Subject + Maximum Age subelement */ -#define MEASURE_REQUEST_LCI_LEN (3 + 1 + 4) -/* Measurement Request element + Location Civic Request */ -#define MEASURE_REQUEST_CIVIC_LEN (3 + 5) - - -/** - * wpas_rrm_send_neighbor_rep_request - Request a neighbor report from our AP - * @wpa_s: Pointer to wpa_supplicant - * @ssid: if not null, this is sent in the request. Otherwise, no SSID IE - * is sent in the request. - * @lci: if set, neighbor request will include LCI request - * @civic: if set, neighbor request will include civic location request - * @cb: Callback function to be called once the requested report arrives, or - * timed out after RRM_NEIGHBOR_REPORT_TIMEOUT seconds. - * In the former case, 'neighbor_rep' is a newly allocated wpabuf, and it's - * the requester's responsibility to free it. - * In the latter case NULL will be sent in 'neighbor_rep'. - * @cb_ctx: Context value to send the callback function - * Returns: 0 in case of success, negative error code otherwise - * - * In case there is a previous request which has not been answered yet, the - * new request fails. The caller may retry after RRM_NEIGHBOR_REPORT_TIMEOUT. - * Request must contain a callback function. - */ -int wpas_rrm_send_neighbor_rep_request(struct wpa_supplicant *wpa_s, - const struct wpa_ssid_value *ssid, - int lci, int civic, - void (*cb)(void *ctx, - struct wpabuf *neighbor_rep), - void *cb_ctx) -{ - struct wpabuf *buf; - const u8 *rrm_ie; - - if (wpa_s->wpa_state != WPA_COMPLETED || wpa_s->current_ssid == NULL) { - wpa_printf(MSG_DEBUG, "RRM: No connection, no RRM."); - return -ENOTCONN; - } - - if (!wpa_s->rrm.rrm_used) { - wpa_printf(MSG_DEBUG, "RRM: No RRM in current connection."); - return -EOPNOTSUPP; - } - - rrm_ie = wpa_bss_get_ie(wpa_s->current_bss, - WLAN_EID_RRM_ENABLED_CAPABILITIES); - if (!rrm_ie || !(wpa_s->current_bss->caps & IEEE80211_CAP_RRM) || - !(rrm_ie[2] & WLAN_RRM_CAPS_NEIGHBOR_REPORT)) { - wpa_printf(MSG_DEBUG, - "RRM: No network support for Neighbor Report."); - return -EOPNOTSUPP; - } - - if (!cb) { - wpa_printf(MSG_DEBUG, - "RRM: Neighbor Report request must provide a callback."); - return -EINVAL; - } - - /* Refuse if there's a live request */ - if (wpa_s->rrm.notify_neighbor_rep) { - wpa_printf(MSG_DEBUG, - "RRM: Currently handling previous Neighbor Report."); - return -EBUSY; - } - - /* 3 = action category + action code + dialog token */ - buf = wpabuf_alloc(3 + (ssid ? 2 + ssid->ssid_len : 0) + - (lci ? 2 + MEASURE_REQUEST_LCI_LEN : 0) + - (civic ? 2 + MEASURE_REQUEST_CIVIC_LEN : 0)); - if (buf == NULL) { - wpa_printf(MSG_DEBUG, - "RRM: Failed to allocate Neighbor Report Request"); - return -ENOMEM; - } - - wpa_printf(MSG_DEBUG, "RRM: Neighbor report request (for %s), token=%d", - (ssid ? wpa_ssid_txt(ssid->ssid, ssid->ssid_len) : ""), - wpa_s->rrm.next_neighbor_rep_token); - - wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT); - wpabuf_put_u8(buf, WLAN_RRM_NEIGHBOR_REPORT_REQUEST); - wpabuf_put_u8(buf, wpa_s->rrm.next_neighbor_rep_token); - if (ssid) { - wpabuf_put_u8(buf, WLAN_EID_SSID); - wpabuf_put_u8(buf, ssid->ssid_len); - wpabuf_put_data(buf, ssid->ssid, ssid->ssid_len); - } - - if (lci) { - /* IEEE P802.11-REVmc/D5.0 9.4.2.21 */ - wpabuf_put_u8(buf, WLAN_EID_MEASURE_REQUEST); - wpabuf_put_u8(buf, MEASURE_REQUEST_LCI_LEN); - - /* - * Measurement token; nonzero number that is unique among the - * Measurement Request elements in a particular frame. - */ - wpabuf_put_u8(buf, 1); /* Measurement Token */ - - /* - * Parallel, Enable, Request, and Report bits are 0, Duration is - * reserved. - */ - wpabuf_put_u8(buf, 0); /* Measurement Request Mode */ - wpabuf_put_u8(buf, MEASURE_TYPE_LCI); /* Measurement Type */ - - /* IEEE P802.11-REVmc/D5.0 9.4.2.21.10 - LCI request */ - /* Location Subject */ - wpabuf_put_u8(buf, LOCATION_SUBJECT_REMOTE); - - /* Optional Subelements */ - /* - * IEEE P802.11-REVmc/D5.0 Figure 9-170 - * The Maximum Age subelement is required, otherwise the AP can - * send only data that was determined after receiving the - * request. Setting it here to unlimited age. - */ - wpabuf_put_u8(buf, LCI_REQ_SUBELEM_MAX_AGE); - wpabuf_put_u8(buf, 2); - wpabuf_put_le16(buf, 0xffff); - } - - if (civic) { - /* IEEE P802.11-REVmc/D5.0 9.4.2.21 */ - wpabuf_put_u8(buf, WLAN_EID_MEASURE_REQUEST); - wpabuf_put_u8(buf, MEASURE_REQUEST_CIVIC_LEN); - - /* - * Measurement token; nonzero number that is unique among the - * Measurement Request elements in a particular frame. - */ - wpabuf_put_u8(buf, 2); /* Measurement Token */ - - /* - * Parallel, Enable, Request, and Report bits are 0, Duration is - * reserved. - */ - wpabuf_put_u8(buf, 0); /* Measurement Request Mode */ - /* Measurement Type */ - wpabuf_put_u8(buf, MEASURE_TYPE_LOCATION_CIVIC); - - /* IEEE P802.11-REVmc/D5.0 9.4.2.21.14: - * Location Civic request */ - /* Location Subject */ - wpabuf_put_u8(buf, LOCATION_SUBJECT_REMOTE); - wpabuf_put_u8(buf, 0); /* Civic Location Type: IETF RFC 4776 */ - /* Location Service Interval Units: Seconds */ - wpabuf_put_u8(buf, 0); - /* Location Service Interval: 0 - Only one report is requested - */ - wpabuf_put_le16(buf, 0); - /* No optional subelements */ - } - - wpa_s->rrm.next_neighbor_rep_token++; - - if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid, - wpa_s->own_addr, wpa_s->bssid, - wpabuf_head(buf), wpabuf_len(buf), 0) < 0) { - wpa_printf(MSG_DEBUG, - "RRM: Failed to send Neighbor Report Request"); - wpabuf_free(buf); - return -ECANCELED; - } - - wpa_s->rrm.neighbor_rep_cb_ctx = cb_ctx; - wpa_s->rrm.notify_neighbor_rep = cb; - eloop_register_timeout(RRM_NEIGHBOR_REPORT_TIMEOUT, 0, - wpas_rrm_neighbor_rep_timeout_handler, - &wpa_s->rrm, NULL); - - wpabuf_free(buf); - return 0; -} - - -static struct wpabuf * wpas_rrm_build_lci_report(struct wpa_supplicant *wpa_s, - const u8 *request, size_t len, - struct wpabuf *report) -{ - u8 token, type, subject; - u16 max_age = 0; - struct os_reltime t, diff; - unsigned long diff_l; - u8 *ptoken; - const u8 *subelem; - - if (!wpa_s->lci || len < 3 + 4) - return report; - - token = *request++; - /* Measurement request mode isn't used */ - request++; - type = *request++; - subject = *request++; - - wpa_printf(MSG_DEBUG, - "Measurement request token %u type %u location subject %u", - token, type, subject); - - if (type != MEASURE_TYPE_LCI || subject != LOCATION_SUBJECT_REMOTE) { - wpa_printf(MSG_INFO, - "Not building LCI report - bad type or location subject"); - return report; - } - - /* Subelements are formatted exactly like elements */ - subelem = get_ie(request, len, LCI_REQ_SUBELEM_MAX_AGE); - if (subelem && subelem[1] == 2) - max_age = WPA_GET_LE16(subelem + 2); - - if (os_get_reltime(&t)) - return report; - - os_reltime_sub(&t, &wpa_s->lci_time, &diff); - /* LCI age is calculated in 10th of a second units. */ - diff_l = diff.sec * 10 + diff.usec / 100000; - - if (max_age != 0xffff && max_age < diff_l) - return report; - - if (wpabuf_resize(&report, 2 + wpabuf_len(wpa_s->lci))) - return report; - - wpabuf_put_u8(report, WLAN_EID_MEASURE_REPORT); - wpabuf_put_u8(report, wpabuf_len(wpa_s->lci)); - /* We'll override user's measurement token */ - ptoken = wpabuf_put(report, 0); - wpabuf_put_buf(report, wpa_s->lci); - *ptoken = token; - - return report; -} - - -void wpas_rrm_handle_radio_measurement_request(struct wpa_supplicant *wpa_s, - const u8 *src, - const u8 *frame, size_t len) -{ - struct wpabuf *buf, *report; - u8 token; - const u8 *ie, *end; - - if (wpa_s->wpa_state != WPA_COMPLETED) { - wpa_printf(MSG_INFO, - "RRM: Ignoring radio measurement request: Not associated"); - return; - } - - if (!wpa_s->rrm.rrm_used) { - wpa_printf(MSG_INFO, - "RRM: Ignoring radio measurement request: Not RRM network"); - return; - } - - if (len < 3) { - wpa_printf(MSG_INFO, - "RRM: Ignoring too short radio measurement request"); - return; - } - - end = frame + len; - - token = *frame++; - - /* Ignore number of repetitions because it's not used in LCI request */ - frame += 2; - - report = NULL; - while ((ie = get_ie(frame, end - frame, WLAN_EID_MEASURE_REQUEST)) && - ie[1] >= 3) { - u8 msmt_type; - - msmt_type = ie[4]; - wpa_printf(MSG_DEBUG, "RRM request %d", msmt_type); - - switch (msmt_type) { - case MEASURE_TYPE_LCI: - report = wpas_rrm_build_lci_report(wpa_s, ie + 2, ie[1], - report); - break; - default: - wpa_printf(MSG_INFO, - "RRM: Unsupported radio measurement request %d", - msmt_type); - break; - } - - frame = ie + ie[1] + 2; - } - - if (!report) - return; - - buf = wpabuf_alloc(3 + wpabuf_len(report)); - if (!buf) { - wpabuf_free(report); - return; - } - - wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT); - wpabuf_put_u8(buf, WLAN_RRM_RADIO_MEASUREMENT_REPORT); - wpabuf_put_u8(buf, token); - - wpabuf_put_buf(buf, report); - wpabuf_free(report); - - if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, src, - wpa_s->own_addr, wpa_s->bssid, - wpabuf_head(buf), wpabuf_len(buf), 0)) { - wpa_printf(MSG_ERROR, - "RRM: Radio measurement report failed: Sending Action frame failed"); - } - wpabuf_free(buf); -} - - -void wpas_rrm_handle_link_measurement_request(struct wpa_supplicant *wpa_s, - const u8 *src, - const u8 *frame, size_t len, - int rssi) -{ - struct wpabuf *buf; - const struct rrm_link_measurement_request *req; - struct rrm_link_measurement_report report; - - if (wpa_s->wpa_state != WPA_COMPLETED) { - wpa_printf(MSG_INFO, - "RRM: Ignoring link measurement request. Not associated"); - return; - } - - if (!wpa_s->rrm.rrm_used) { - wpa_printf(MSG_INFO, - "RRM: Ignoring link measurement request. Not RRM network"); - return; - } - - if (!(wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_TX_POWER_INSERTION)) { - wpa_printf(MSG_INFO, - "RRM: Measurement report failed. TX power insertion not supported"); - return; - } - - req = (const struct rrm_link_measurement_request *) frame; - if (len < sizeof(*req)) { - wpa_printf(MSG_INFO, - "RRM: Link measurement report failed. Request too short"); - return; - } - - os_memset(&report, 0, sizeof(report)); - report.tpc.eid = WLAN_EID_TPC_REPORT; - report.tpc.len = 2; - report.rsni = 255; /* 255 indicates that RSNI is not available */ - report.dialog_token = req->dialog_token; - - /* - * It's possible to estimate RCPI based on RSSI in dBm. This - * calculation will not reflect the correct value for high rates, - * but it's good enough for Action frames which are transmitted - * with up to 24 Mbps rates. - */ - if (!rssi) - report.rcpi = 255; /* not available */ - else if (rssi < -110) - report.rcpi = 0; - else if (rssi > 0) - report.rcpi = 220; - else - report.rcpi = (rssi + 110) * 2; - - /* action_category + action_code */ - buf = wpabuf_alloc(2 + sizeof(report)); - if (buf == NULL) { - wpa_printf(MSG_ERROR, - "RRM: Link measurement report failed. Buffer allocation failed"); - return; - } - - wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT); - wpabuf_put_u8(buf, WLAN_RRM_LINK_MEASUREMENT_REPORT); - wpabuf_put_data(buf, &report, sizeof(report)); - wpa_hexdump(MSG_DEBUG, "RRM: Link measurement report:", - wpabuf_head(buf), wpabuf_len(buf)); - - if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, src, - wpa_s->own_addr, wpa_s->bssid, - wpabuf_head(buf), wpabuf_len(buf), 0)) { - wpa_printf(MSG_ERROR, - "RRM: Link measurement report failed. Send action failed"); - } - wpabuf_free(buf); -} - - struct wpa_supplicant * wpas_vendor_elem(struct wpa_supplicant *wpa_s, enum wpa_vendor_elem_frame frame) { @@ -6852,19 +7378,55 @@ wpa_bss_tmp_disallowed * wpas_get_disallowed_bss(struct wpa_supplicant *wpa_s, } +static int wpa_set_driver_tmp_disallow_list(struct wpa_supplicant *wpa_s) +{ + struct wpa_bss_tmp_disallowed *tmp; + unsigned int num_bssid = 0; + u8 *bssids; + int ret; + + bssids = os_malloc(dl_list_len(&wpa_s->bss_tmp_disallowed) * ETH_ALEN); + if (!bssids) + return -1; + dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed, + struct wpa_bss_tmp_disallowed, list) { + os_memcpy(&bssids[num_bssid * ETH_ALEN], tmp->bssid, + ETH_ALEN); + num_bssid++; + } + ret = wpa_drv_set_bssid_blacklist(wpa_s, num_bssid, bssids); + os_free(bssids); + return ret; +} + + +static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx) +{ + struct wpa_supplicant *wpa_s = eloop_ctx; + struct wpa_bss_tmp_disallowed *tmp, *bss = timeout_ctx; + + /* Make sure the bss is not already freed */ + dl_list_for_each(tmp, &wpa_s->bss_tmp_disallowed, + struct wpa_bss_tmp_disallowed, list) { + if (bss == tmp) { + dl_list_del(&tmp->list); + os_free(tmp); + wpa_set_driver_tmp_disallow_list(wpa_s); + break; + } + } +} + + void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid, - unsigned int sec) + unsigned int sec, int rssi_threshold) { struct wpa_bss_tmp_disallowed *bss; - struct os_reltime until; - - os_get_reltime(&until); - until.sec += sec; bss = wpas_get_disallowed_bss(wpa_s, bssid); if (bss) { - bss->disallowed_until = until; - return; + eloop_cancel_timeout(wpa_bss_tmp_disallow_timeout, wpa_s, bss); + goto finish; } bss = os_malloc(sizeof(*bss)); @@ -6874,38 +7436,35 @@ void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid, return; } - bss->disallowed_until = until; os_memcpy(bss->bssid, bssid, ETH_ALEN); dl_list_add(&wpa_s->bss_tmp_disallowed, &bss->list); + wpa_set_driver_tmp_disallow_list(wpa_s); + +finish: + bss->rssi_threshold = rssi_threshold; + eloop_register_timeout(sec, 0, wpa_bss_tmp_disallow_timeout, + wpa_s, bss); } -int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s, const u8 *bssid) +int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s, + struct wpa_bss *bss) { - struct wpa_bss_tmp_disallowed *bss = NULL, *tmp, *prev; - struct os_reltime now, age; - - os_get_reltime(&now); + struct wpa_bss_tmp_disallowed *disallowed = NULL, *tmp, *prev; dl_list_for_each_safe(tmp, prev, &wpa_s->bss_tmp_disallowed, struct wpa_bss_tmp_disallowed, list) { - if (!os_reltime_before(&now, &tmp->disallowed_until)) { - /* This BSS is not disallowed anymore */ - dl_list_del(&tmp->list); - os_free(tmp); - continue; - } - if (os_memcmp(bssid, tmp->bssid, ETH_ALEN) == 0) { - bss = tmp; + if (os_memcmp(bss->bssid, tmp->bssid, ETH_ALEN) == 0) { + disallowed = tmp; break; } } - if (!bss) + if (!disallowed) + return 0; + + if (disallowed->rssi_threshold != 0 && + bss->level > disallowed->rssi_threshold) return 0; - os_reltime_sub(&bss->disallowed_until, &now, &age); - wpa_printf(MSG_DEBUG, - "BSS " MACSTR " disabled for %ld.%0ld seconds", - MAC2STR(bss->bssid), age.sec, age.usec); return 1; } diff --git a/freebsd/contrib/wpa/wpa_supplicant/wpa_supplicant_i.h b/freebsd/contrib/wpa/wpa_supplicant/wpa_supplicant_i.h index ef9273d0..16e4db62 100644 --- a/freebsd/contrib/wpa/wpa_supplicant/wpa_supplicant_i.h +++ b/freebsd/contrib/wpa/wpa_supplicant/wpa_supplicant_i.h @@ -9,6 +9,7 @@ #ifndef WPA_SUPPLICANT_I_H #define WPA_SUPPLICANT_I_H +#include "utils/bitfield.h" #include "utils/list.h" #include "common/defs.h" #include "common/sae.h" @@ -295,7 +296,7 @@ struct wpa_global { #ifdef CONFIG_WIFI_DISPLAY int wifi_display; -#define MAX_WFD_SUBELEMS 10 +#define MAX_WFD_SUBELEMS 12 struct wpabuf *wfd_subelem[MAX_WFD_SUBELEMS]; #endif /* CONFIG_WIFI_DISPLAY */ @@ -344,6 +345,7 @@ int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq, void radio_work_done(struct wpa_radio_work *work); void radio_remove_works(struct wpa_supplicant *wpa_s, const char *type, int remove_all); +void radio_remove_pending_work(struct wpa_supplicant *wpa_s, void *ctx); void radio_work_check_next(struct wpa_supplicant *wpa_s); struct wpa_radio_work * radio_work_pending(struct wpa_supplicant *wpa_s, const char *type); @@ -424,6 +426,12 @@ struct rrm_data { /* next_neighbor_rep_token - Next request's dialog token */ u8 next_neighbor_rep_token; + + /* token - Dialog token of the current radio measurement */ + u8 token; + + /* destination address of the current radio measurement request */ + u8 dst_addr[ETH_ALEN]; }; enum wpa_supplicant_test_failure { @@ -443,7 +451,30 @@ struct icon_entry { struct wpa_bss_tmp_disallowed { struct dl_list list; u8 bssid[ETH_ALEN]; - struct os_reltime disallowed_until; + int rssi_threshold; +}; + +struct beacon_rep_data { + u8 token; + u8 last_indication; + struct wpa_driver_scan_params scan_params; + u8 ssid[SSID_MAX_LEN]; + size_t ssid_len; + u8 bssid[ETH_ALEN]; + enum beacon_report_detail report_detail; + struct bitfield *eids; +}; + + +struct external_pmksa_cache { + struct dl_list list; + void *pmksa_cache; +}; + +struct fils_hlp_req { + struct dl_list list; + u8 dst[ETH_ALEN]; + struct wpabuf *pkt; }; /** @@ -463,15 +494,16 @@ struct wpa_supplicant { struct wpa_supplicant *next; struct l2_packet_data *l2; struct l2_packet_data *l2_br; + struct os_reltime roam_start; + struct os_reltime roam_time; + struct os_reltime session_start; + struct os_reltime session_length; unsigned char own_addr[ETH_ALEN]; unsigned char perm_addr[ETH_ALEN]; char ifname[100]; #ifdef CONFIG_MATCH_IFACE int matched; #endif /* CONFIG_MATCH_IFACE */ -#ifdef CONFIG_CTRL_IFACE_DBUS - char *dbus_path; -#endif /* CONFIG_CTRL_IFACE_DBUS */ #ifdef CONFIG_CTRL_IFACE_DBUS_NEW char *dbus_new_path; char *dbus_groupobj_path; @@ -503,6 +535,8 @@ struct wpa_supplicant { struct wpa_bss *current_bss; int ap_ies_from_associnfo; unsigned int assoc_freq; + u8 *last_con_fail_realm; + size_t last_con_fail_realm_len; /* Selected configuration (based on Beacon/ProbeResp WPA IE) */ int pairwise_cipher; @@ -639,6 +673,7 @@ struct wpa_supplicant { struct os_reltime scan_min_time; int scan_runs; /* number of scan runs since WPS was started */ int *next_scan_freqs; + int *select_network_scan_freqs; int *manual_scan_freqs; int *manual_sched_scan_freqs; unsigned int manual_scan_passive:1; @@ -652,6 +687,12 @@ struct wpa_supplicant { int normal_scans; /* normal scans run before sched_scan */ int scan_for_connection; /* whether the scan request was triggered for * finding a connection */ + /* + * A unique cookie representing the vendor scan request. This cookie is + * returned from the driver interface. 0 indicates that there is no + * pending vendor scan request. + */ + u64 curr_scan_cookie; #define MAX_SCAN_ID 16 int scan_id[MAX_SCAN_ID]; unsigned int scan_id_count; @@ -705,6 +746,12 @@ struct wpa_supplicant { unsigned int mac_addr_changed:1; unsigned int added_vif:1; unsigned int wnmsleep_used:1; + unsigned int owe_transition_select:1; + unsigned int owe_transition_search:1; + unsigned int connection_set:1; + unsigned int connection_ht:1; + unsigned int connection_vht:1; + unsigned int connection_he:1; struct os_reltime last_mac_addr_change; int last_mac_addr_style; @@ -715,13 +762,15 @@ struct wpa_supplicant { int sta_uapsd; int set_ap_uapsd; int ap_uapsd; + int auth_alg; + u16 last_owe_group; #ifdef CONFIG_SME struct { u8 ssid[SSID_MAX_LEN]; size_t ssid_len; int freq; - u8 assoc_req_ie[200]; + u8 assoc_req_ie[1500]; size_t assoc_req_ie_len; int mfp; int ft_used; @@ -752,6 +801,8 @@ struct wpa_supplicant { struct wpabuf *sae_token; int sae_group_index; unsigned int sae_pmksa_caching:1; + u16 seq_num; + struct external_auth ext_auth; #endif /* CONFIG_SAE */ } sme; #endif /* CONFIG_SME */ @@ -770,6 +821,11 @@ struct wpa_supplicant { unsigned int mesh_if_created:1; unsigned int mesh_ht_enabled:1; unsigned int mesh_vht_enabled:1; + struct wpa_driver_mesh_join_params *mesh_params; +#ifdef CONFIG_PMKSA_CACHE_EXTERNAL + /* struct external_pmksa_cache::list */ + struct dl_list mesh_external_pmksa_cache; +#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */ #endif /* CONFIG_MESH */ unsigned int off_channel_freq; @@ -789,6 +845,7 @@ struct wpa_supplicant { result); unsigned int roc_waiting_drv_freq; int action_tx_wait_time; + int action_tx_wait_time_used; int p2p_mgmt; @@ -856,11 +913,13 @@ struct wpa_supplicant { unsigned int p2p_auto_join:1; unsigned int p2p_auto_pd:1; + unsigned int p2p_go_do_acs:1; unsigned int p2p_persistent_group:1; unsigned int p2p_fallback_to_go_neg:1; unsigned int p2p_pd_before_go_neg:1; unsigned int p2p_go_ht40:1; unsigned int p2p_go_vht:1; + unsigned int p2p_go_he:1; unsigned int user_initiated_pd:1; unsigned int p2p_go_group_formation_completed:1; unsigned int group_formation_reported:1; @@ -871,6 +930,7 @@ struct wpa_supplicant { unsigned int p2p_disable_ip_addr_req:1; unsigned int p2ps_method_config_any:1; unsigned int p2p_cli_probe:1; + enum hostapd_hw_mode p2p_go_acs_band; int p2p_persistent_go_freq; int p2p_persistent_id; int p2p_go_intent; @@ -923,6 +983,7 @@ struct wpa_supplicant { int best_overall_freq; struct gas_query *gas; + struct gas_server *gas_server; #ifdef CONFIG_INTERWORKING unsigned int fetch_anqp_in_progress:1; @@ -966,6 +1027,10 @@ struct wpa_supplicant { /* WLAN_REASON_* reason codes. Negative if locally generated. */ int disconnect_reason; + /* WLAN_STATUS_* status codes from last received Authentication frame + * from the AP. */ + u16 auth_status_code; + /* WLAN_STATUS_* status codes from (Re)Association Response frame. */ u16 assoc_status_code; @@ -981,6 +1046,7 @@ struct wpa_supplicant { unsigned int wmm_ac_supported:1; unsigned int ext_work_in_progress:1; unsigned int own_disconnect_req:1; + unsigned int ignore_post_flush_scan_res:1; #define MAC_ADDR_RAND_SCAN BIT(0) #define MAC_ADDR_RAND_SCHED_SCAN BIT(1) @@ -1006,6 +1072,15 @@ struct wpa_supplicant { struct neighbor_report *wnm_neighbor_report_elements; struct os_reltime wnm_cand_valid_until; u8 wnm_cand_from_bss[ETH_ALEN]; + enum bss_trans_mgmt_status_code bss_tm_status; + struct wpabuf *coloc_intf_elems; + u8 coloc_intf_dialog_token; + u8 coloc_intf_auto_report; + u8 coloc_intf_timeout; +#ifdef CONFIG_MBO + unsigned int wnm_mbo_trans_reason_present:1; + u8 wnm_mbo_transition_reason; +#endif /* CONFIG_MBO */ #endif /* CONFIG_WNM */ #ifdef CONFIG_TESTING_GET_GTK @@ -1024,10 +1099,19 @@ struct wpa_supplicant { struct l2_packet_data *l2_test; unsigned int extra_roc_dur; enum wpa_supplicant_test_failure test_failure; + char *get_pref_freq_list_override; unsigned int reject_btm_req_reason; unsigned int p2p_go_csa_on_inv:1; unsigned int ignore_auth_resp:1; unsigned int ignore_assoc_disallow:1; + unsigned int testing_resend_assoc:1; + struct wpabuf *sae_commit_override; + enum wpa_alg last_tk_alg; + u8 last_tk_addr[ETH_ALEN]; + int last_tk_key_idx; + u8 last_tk[WPA_TK_MAX_LEN]; + size_t last_tk_len; + struct wpabuf *last_assoc_req_wpa_ie; #endif /* CONFIG_TESTING_OPTIONS */ struct wmm_ac_assoc_data *wmm_ac_assoc_info; @@ -1038,6 +1122,7 @@ struct wpa_supplicant { u8 last_tspecs_count; struct rrm_data rrm; + struct beacon_rep_data beacon_rep_data; #ifdef CONFIG_FST struct fst_iface *fst; @@ -1055,6 +1140,14 @@ struct wpa_supplicant { } *non_pref_chan; size_t non_pref_chan_num; u8 mbo_wnm_token; + /** + * enable_oce - Enable OCE if it is enabled by user and device also + * supports OCE. + * User can enable OCE with wpa_config's 'oce' parameter as follows - + * - Set BIT(0) to enable OCE in non-AP STA mode. + * - Set BIT(1) to enable OCE in STA-CFON mode. + */ + u8 enable_oce; #endif /* CONFIG_MBO */ /* @@ -1069,6 +1162,95 @@ struct wpa_supplicant { */ struct wpabuf *lci; struct os_reltime lci_time; + + struct os_reltime beacon_rep_scan; + + /* FILS HLP requests (struct fils_hlp_req) */ + struct dl_list fils_hlp_req; + + struct sched_scan_relative_params { + /** + * relative_rssi_set - Enable relatively preferred BSS reporting + * + * 0 = Disable reporting relatively preferred BSSs + * 1 = Enable reporting relatively preferred BSSs + */ + int relative_rssi_set; + + /** + * relative_rssi - Relative RSSI for reporting better BSSs + * + * Amount of RSSI by which a BSS should be better than the + * current connected BSS so that the new BSS can be reported + * to user space. This applies to sched_scan operations. + */ + int relative_rssi; + + /** + * relative_adjust_band - Band in which RSSI is to be adjusted + */ + enum set_band relative_adjust_band; + + /** + * relative_adjust_rssi - RSSI adjustment + * + * An amount of relative_adjust_rssi should be added to the + * BSSs that belong to the relative_adjust_band while comparing + * with other bands for BSS reporting. + */ + int relative_adjust_rssi; + } srp; + + /* RIC elements for FT protocol */ + struct wpabuf *ric_ies; + + int last_auth_timeout_sec; + +#ifdef CONFIG_DPP + struct dpp_global *dpp; + struct dpp_authentication *dpp_auth; + struct wpa_radio_work *dpp_listen_work; + unsigned int dpp_pending_listen_freq; + unsigned int dpp_listen_freq; + u8 dpp_allowed_roles; + int dpp_qr_mutual; + int dpp_netrole_ap; + int dpp_auth_ok_on_ack; + int dpp_in_response_listen; + int dpp_gas_client; + int dpp_gas_dialog_token; + u8 dpp_intro_bssid[ETH_ALEN]; + void *dpp_intro_network; + struct dpp_pkex *dpp_pkex; + struct dpp_bootstrap_info *dpp_pkex_bi; + char *dpp_pkex_code; + char *dpp_pkex_identifier; + char *dpp_pkex_auth_cmd; + char *dpp_configurator_params; + struct os_reltime dpp_last_init; + struct os_reltime dpp_init_iter_start; + unsigned int dpp_init_max_tries; + unsigned int dpp_init_retry_time; + unsigned int dpp_resp_wait_time; + unsigned int dpp_resp_max_tries; + unsigned int dpp_resp_retry_time; +#ifdef CONFIG_DPP2 + struct dpp_pfs *dpp_pfs; +#endif /* CONFIG_DPP2 */ +#ifdef CONFIG_TESTING_OPTIONS + char *dpp_config_obj_override; + char *dpp_discovery_override; + char *dpp_groups_override; + unsigned int dpp_ignore_netaccesskey_mismatch:1; +#endif /* CONFIG_TESTING_OPTIONS */ +#endif /* CONFIG_DPP */ + +#ifdef CONFIG_FILS + unsigned int disable_fils:1; +#endif /* CONFIG_FILS */ + unsigned int ieee80211ac:1; + unsigned int enabled_4addr_mode:1; + unsigned int multi_bss_support:1; }; @@ -1101,6 +1283,7 @@ void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s); void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr); void wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s, int sec, int usec); +void wpas_auth_timeout_restart(struct wpa_supplicant *wpa_s, int sec_diff); void wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s); void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s, enum wpa_states state); @@ -1158,6 +1341,7 @@ void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr, void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s); void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s); void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid); +void fils_connection_failure(struct wpa_supplicant *wpa_s); int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s); int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s); void wpas_auth_failed(struct wpa_supplicant *wpa_s, char *reason); @@ -1183,22 +1367,30 @@ int wpas_rrm_send_neighbor_rep_request(struct wpa_supplicant *wpa_s, struct wpabuf *neighbor_rep), void *cb_ctx); void wpas_rrm_handle_radio_measurement_request(struct wpa_supplicant *wpa_s, - const u8 *src, + const u8 *src, const u8 *dst, const u8 *frame, size_t len); void wpas_rrm_handle_link_measurement_request(struct wpa_supplicant *wpa_s, const u8 *src, const u8 *frame, size_t len, int rssi); +void wpas_rrm_refuse_request(struct wpa_supplicant *wpa_s); +int wpas_beacon_rep_scan_process(struct wpa_supplicant *wpa_s, + struct wpa_scan_results *scan_res, + struct scan_info *info); +void wpas_clear_beacon_rep_data(struct wpa_supplicant *wpa_s); +void wpas_flush_fils_hlp_req(struct wpa_supplicant *wpa_s); /* MBO functions */ -int wpas_mbo_ie(struct wpa_supplicant *wpa_s, u8 *buf, size_t len); +int wpas_mbo_ie(struct wpa_supplicant *wpa_s, u8 *buf, size_t len, + int add_oce_capa); +const u8 * mbo_attr_from_mbo_ie(const u8 *mbo_ie, enum mbo_attr_id attr); const u8 * wpas_mbo_get_bss_attr(struct wpa_bss *bss, enum mbo_attr_id attr); +const u8 * mbo_get_attr_from_ies(const u8 *ies, size_t ies_len, + enum mbo_attr_id attr); int wpas_mbo_update_non_pref_chan(struct wpa_supplicant *wpa_s, const char *non_pref_chan); void wpas_mbo_scan_ie(struct wpa_supplicant *wpa_s, struct wpabuf *ie); -int wpas_mbo_supp_op_class_ie(struct wpa_supplicant *wpa_s, int freq, u8 *pos, - size_t len); void wpas_mbo_ie_trans_req(struct wpa_supplicant *wpa_s, const u8 *ie, size_t len); size_t wpas_mbo_ie_bss_trans_reject(struct wpa_supplicant *wpa_s, u8 *pos, @@ -1206,7 +1398,22 @@ size_t wpas_mbo_ie_bss_trans_reject(struct wpa_supplicant *wpa_s, u8 *pos, enum mbo_transition_reject_reason reason); void wpas_mbo_update_cell_capa(struct wpa_supplicant *wpa_s, u8 mbo_cell_capa); struct wpabuf * mbo_build_anqp_buf(struct wpa_supplicant *wpa_s, - struct wpa_bss *bss); + struct wpa_bss *bss, u32 mbo_subtypes); +void mbo_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s, + struct wpa_bss *bss, const u8 *sa, + const u8 *data, size_t slen); +void wpas_update_mbo_connect_params(struct wpa_supplicant *wpa_s); + +/* op_classes.c */ +enum chan_allowed { + NOT_ALLOWED, NO_IR, ALLOWED +}; + +enum chan_allowed verify_channel(struct hostapd_hw_modes *mode, u8 channel, + u8 bw); +size_t wpas_supp_op_class_ie(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid, + int freq, u8 *pos, size_t len); /** * wpa_supplicant_ctrl_iface_ctrl_rsp_handle - Handle a control response @@ -1238,6 +1445,9 @@ void wnm_bss_keep_alive_deinit(struct wpa_supplicant *wpa_s); int wpa_supplicant_fast_associate(struct wpa_supplicant *wpa_s); struct wpa_bss * wpa_supplicant_pick_network(struct wpa_supplicant *wpa_s, struct wpa_ssid **selected_ssid); +int wpas_temp_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid); +void wpa_supplicant_update_channel_list(struct wpa_supplicant *wpa_s, + struct channel_list_changed *info); /* eap_register.c */ int eap_register_methods(void); @@ -1290,12 +1500,22 @@ struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes, u16 num_modes, enum hostapd_hw_mode mode); void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid, - unsigned int sec); -int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s, const u8 *bssid); + unsigned int sec, int rssi_threshold); +int wpa_is_bss_tmp_disallowed(struct wpa_supplicant *wpa_s, + struct wpa_bss *bss); +void free_bss_tmp_disallowed(struct wpa_supplicant *wpa_s); struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s, int i, struct wpa_bss *bss, struct wpa_ssid *group, - int only_first_ssid); + int only_first_ssid, int debug_print); + +int wpas_ctrl_iface_get_pref_freq_list_override(struct wpa_supplicant *wpa_s, + enum wpa_driver_if_type if_type, + unsigned int *num, + unsigned int *freq_list); + +int wpa_is_fils_supported(struct wpa_supplicant *wpa_s); +int wpa_is_fils_sk_pfs_supported(struct wpa_supplicant *wpa_s); #endif /* WPA_SUPPLICANT_I_H */ diff --git a/freebsd/contrib/wpa/wpa_supplicant/wpas_glue.c b/freebsd/contrib/wpa/wpa_supplicant/wpas_glue.c index 158cbb07..3dc6a216 100644 --- a/freebsd/contrib/wpa/wpa_supplicant/wpas_glue.c +++ b/freebsd/contrib/wpa/wpa_supplicant/wpas_glue.c @@ -12,6 +12,7 @@ #include "common.h" #include "eapol_supp/eapol_supp_sm.h" +#include "eap_peer/eap.h" #include "rsn_supp/wpa.h" #include "eloop.h" #include "config.h" @@ -147,6 +148,8 @@ static int wpa_supplicant_eapol_send(void *ctx, int type, const u8 *buf, * extra copy here */ if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) || + wpa_s->key_mgmt == WPA_KEY_MGMT_OWE || + wpa_s->key_mgmt == WPA_KEY_MGMT_DPP || wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) { /* Current SSID is not using IEEE 802.1X/EAP, so drop possible * EAPOL frames (mainly, EAPOL-Start) from EAPOL state @@ -295,7 +298,7 @@ static void wpa_supplicant_eapol_cb(struct eapol_sm *eapol, } if (result != EAPOL_SUPP_RESULT_SUCCESS || - !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE)) + !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X)) return; if (!wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) @@ -501,6 +504,16 @@ static int wpa_supplicant_set_key(void *_wpa_s, enum wpa_alg alg, wpa_s->last_gtk_len = 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; + } +#endif /* CONFIG_TESTING_OPTIONS */ return wpa_drv_set_key(wpa_s, alg, addr, key_idx, set_tx, seq, seq_len, key, key_len); } @@ -515,17 +528,74 @@ static int wpa_supplicant_mlme_setprotection(void *wpa_s, const u8 *addr, } -static int wpa_supplicant_add_pmkid(void *wpa_s, - const u8 *bssid, const u8 *pmkid) +static struct wpa_ssid * wpas_get_network_ctx(struct wpa_supplicant *wpa_s, + void *network_ctx) { - return wpa_drv_add_pmkid(wpa_s, bssid, pmkid); + struct wpa_ssid *ssid; + + for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) { + if (network_ctx == ssid) + return ssid; + } + + return NULL; } -static int wpa_supplicant_remove_pmkid(void *wpa_s, - const u8 *bssid, const u8 *pmkid) +static int wpa_supplicant_add_pmkid(void *_wpa_s, void *network_ctx, + const u8 *bssid, const u8 *pmkid, + const u8 *fils_cache_id, + const u8 *pmk, size_t pmk_len) { - return wpa_drv_remove_pmkid(wpa_s, bssid, pmkid); + struct wpa_supplicant *wpa_s = _wpa_s; + struct wpa_ssid *ssid; + struct wpa_pmkid_params params; + + os_memset(¶ms, 0, sizeof(params)); + ssid = wpas_get_network_ctx(wpa_s, network_ctx); + if (ssid) + wpa_msg(wpa_s, MSG_INFO, PMKSA_CACHE_ADDED MACSTR " %d", + MAC2STR(bssid), ssid->id); + if (ssid && fils_cache_id) { + params.ssid = ssid->ssid; + params.ssid_len = ssid->ssid_len; + params.fils_cache_id = fils_cache_id; + } else { + params.bssid = bssid; + } + + params.pmkid = pmkid; + params.pmk = pmk; + params.pmk_len = pmk_len; + + return wpa_drv_add_pmkid(wpa_s, ¶ms); +} + + +static int wpa_supplicant_remove_pmkid(void *_wpa_s, void *network_ctx, + const u8 *bssid, const u8 *pmkid, + const u8 *fils_cache_id) +{ + struct wpa_supplicant *wpa_s = _wpa_s; + struct wpa_ssid *ssid; + struct wpa_pmkid_params params; + + os_memset(¶ms, 0, sizeof(params)); + ssid = wpas_get_network_ctx(wpa_s, network_ctx); + if (ssid) + wpa_msg(wpa_s, MSG_INFO, PMKSA_CACHE_REMOVED MACSTR " %d", + MAC2STR(bssid), ssid->id); + if (ssid && fils_cache_id) { + params.ssid = ssid->ssid; + params.ssid_len = ssid->ssid_len; + params.fils_cache_id = fils_cache_id; + } else { + params.bssid = bssid; + } + + params.pmkid = pmkid; + + return wpa_drv_remove_pmkid(wpa_s, ¶ms); } @@ -867,12 +937,13 @@ static void wpa_supplicant_eap_param_needed(void *ctx, #ifdef CONFIG_EAP_PROXY + static void wpa_supplicant_eap_proxy_cb(void *ctx) { struct wpa_supplicant *wpa_s = ctx; size_t len; - wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, + wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, -1, wpa_s->imsi, &len); if (wpa_s->mnc_len > 0) { wpa_s->imsi[len] = '\0'; @@ -882,6 +953,52 @@ static void wpa_supplicant_eap_proxy_cb(void *ctx) wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available"); } } + + +static void wpa_sm_sim_state_error_handler(struct wpa_supplicant *wpa_s) +{ + int i; + struct wpa_ssid *ssid; + const struct eap_method_type *eap_methods; + + if (!wpa_s->conf) + return; + + for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) { + eap_methods = ssid->eap.eap_methods; + if (!eap_methods) + continue; + + for (i = 0; eap_methods[i].method != EAP_TYPE_NONE; i++) { + if (eap_methods[i].vendor == EAP_VENDOR_IETF && + (eap_methods[i].method == EAP_TYPE_SIM || + eap_methods[i].method == EAP_TYPE_AKA || + eap_methods[i].method == EAP_TYPE_AKA_PRIME)) { + wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid); + break; + } + } + } +} + + +static void +wpa_supplicant_eap_proxy_notify_sim_status(void *ctx, + enum eap_proxy_sim_state sim_state) +{ + struct wpa_supplicant *wpa_s = ctx; + + wpa_printf(MSG_DEBUG, "eap_proxy: SIM card status %u", sim_state); + switch (sim_state) { + case SIM_STATE_ERROR: + wpa_sm_sim_state_error_handler(wpa_s); + break; + default: + wpa_printf(MSG_DEBUG, "eap_proxy: SIM card status unknown"); + break; + } +} + #endif /* CONFIG_EAP_PROXY */ @@ -923,6 +1040,14 @@ static void wpa_supplicant_status_cb(void *ctx, const char *status, } +static void wpa_supplicant_eap_error_cb(void *ctx, int error_code) +{ + struct wpa_supplicant *wpa_s = ctx; + + wpas_notify_eap_error(wpa_s, error_code); +} + + static void wpa_supplicant_set_anon_id(void *ctx, const u8 *id, size_t len) { struct wpa_supplicant *wpa_s = ctx; @@ -992,12 +1117,15 @@ int wpa_supplicant_init_eapol(struct wpa_supplicant *wpa_s) ctx->eap_param_needed = wpa_supplicant_eap_param_needed; #ifdef CONFIG_EAP_PROXY ctx->eap_proxy_cb = wpa_supplicant_eap_proxy_cb; + ctx->eap_proxy_notify_sim_status = + wpa_supplicant_eap_proxy_notify_sim_status; #endif /* CONFIG_EAP_PROXY */ ctx->port_cb = wpa_supplicant_port_cb; ctx->cb = wpa_supplicant_eapol_cb; ctx->cert_cb = wpa_supplicant_cert_cb; ctx->cert_in_cb = wpa_s->conf->cert_in_cb; ctx->status_cb = wpa_supplicant_status_cb; + ctx->eap_error_cb = wpa_supplicant_eap_error_cb; ctx->set_anon_id = wpa_supplicant_set_anon_id; ctx->cb_ctx = wpa_s; wpa_s->eapol = eapol_sm_init(ctx); @@ -1014,6 +1142,7 @@ int wpa_supplicant_init_eapol(struct wpa_supplicant *wpa_s) #ifndef CONFIG_NO_WPA + static void wpa_supplicant_set_rekey_offload(void *ctx, const u8 *kek, size_t kek_len, const u8 *kck, size_t kck_len, @@ -1037,6 +1166,34 @@ static int wpa_supplicant_key_mgmt_set_pmk(void *ctx, const u8 *pmk, else return 0; } + + +static void wpa_supplicant_fils_hlp_rx(void *ctx, const u8 *dst, const u8 *src, + const u8 *pkt, size_t pkt_len) +{ + struct wpa_supplicant *wpa_s = ctx; + char *hex; + size_t hexlen; + + hexlen = pkt_len * 2 + 1; + hex = os_malloc(hexlen); + if (!hex) + return; + wpa_snprintf_hex(hex, hexlen, pkt, pkt_len); + wpa_msg(wpa_s, MSG_INFO, FILS_HLP_RX "dst=" MACSTR " src=" MACSTR + " frame=%s", MAC2STR(dst), MAC2STR(src), hex); + os_free(hex); +} + + +static int wpa_supplicant_channel_info(void *_wpa_s, + struct wpa_channel_info *ci) +{ + struct wpa_supplicant *wpa_s = _wpa_s; + + return wpa_drv_channel_info(wpa_s, ci); +} + #endif /* CONFIG_NO_WPA */ @@ -1086,6 +1243,8 @@ int wpa_supplicant_init_wpa(struct wpa_supplicant *wpa_s) #endif /* CONFIG_TDLS */ ctx->set_rekey_offload = wpa_supplicant_set_rekey_offload; ctx->key_mgmt_set_pmk = wpa_supplicant_key_mgmt_set_pmk; + ctx->fils_hlp_rx = wpa_supplicant_fils_hlp_rx; + ctx->channel_info = wpa_supplicant_channel_info; wpa_s->wpa = wpa_sm_init(ctx); if (wpa_s->wpa == NULL) { @@ -1107,7 +1266,6 @@ void wpa_supplicant_rsn_supp_set_config(struct wpa_supplicant *wpa_s, if (ssid) { os_memset(&conf, 0, sizeof(conf)); conf.network_ctx = ssid; - conf.peerkey_enabled = ssid->peerkey; conf.allowed_pairwise_cipher = ssid->pairwise_cipher; #ifdef IEEE8021X_EAPOL conf.proactive_key_caching = ssid->proactive_key_caching < 0 ? @@ -1135,6 +1293,11 @@ void wpa_supplicant_rsn_supp_set_config(struct wpa_supplicant *wpa_s, } #endif /* CONFIG_P2P */ conf.wpa_rsc_relaxation = wpa_s->conf->wpa_rsc_relaxation; +#ifdef CONFIG_FILS + if (wpa_key_mgmt_fils(wpa_s->key_mgmt)) + conf.fils_cache_id = + wpa_bss_get_fils_cache_id(wpa_s->current_bss); +#endif /* CONFIG_FILS */ } wpa_sm_set_config(wpa_s->wpa, ssid ? &conf : NULL); } diff --git a/freebsd/contrib/wpa/wpa_supplicant/wpas_kay.h b/freebsd/contrib/wpa/wpa_supplicant/wpas_kay.h index b7236d07..81f8e0ce 100644 --- a/freebsd/contrib/wpa/wpa_supplicant/wpas_kay.h +++ b/freebsd/contrib/wpa/wpa_supplicant/wpas_kay.h @@ -17,6 +17,9 @@ void * ieee802_1x_notify_create_actor(struct wpa_supplicant *wpa_s, const u8 *peer_addr); void ieee802_1x_dealloc_kay_sm(struct wpa_supplicant *wpa_s); +void * ieee802_1x_create_preshared_mka(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid); + #else /* CONFIG_MACSEC */ static inline int ieee802_1x_alloc_kay_sm(struct wpa_supplicant *wpa_s, @@ -36,6 +39,13 @@ static inline void ieee802_1x_dealloc_kay_sm(struct wpa_supplicant *wpa_s) { } +static inline void * +ieee802_1x_create_preshared_mka(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid) +{ + return 0; +} + #endif /* CONFIG_MACSEC */ #endif /* WPAS_KAY_H */ diff --git a/freebsd/contrib/wpa/wpa_supplicant/wps_supplicant.c b/freebsd/contrib/wpa/wpa_supplicant/wps_supplicant.c index 39440b36..6e33def5 100644 --- a/freebsd/contrib/wpa/wpa_supplicant/wps_supplicant.c +++ b/freebsd/contrib/wpa/wpa_supplicant/wps_supplicant.c @@ -205,6 +205,9 @@ static void wpas_wps_security_workaround(struct wpa_supplicant *wpa_s, if (ssid->ssid == NULL) return; bss = wpa_bss_get(wpa_s, cred->mac_addr, ssid->ssid, ssid->ssid_len); + if (!bss) + bss = wpa_bss_get(wpa_s, wpa_s->bssid, + ssid->ssid, ssid->ssid_len); if (bss == NULL) { wpa_printf(MSG_DEBUG, "WPS: The AP was not found from BSS " "table - use credential as-is"); @@ -492,6 +495,16 @@ static int wpa_supplicant_wps_cred(void *ctx, ssid->pairwise_cipher |= WPA_CIPHER_GCMP; ssid->group_cipher |= WPA_CIPHER_GCMP; } + if (wpa_s->drv_capa_known && + (wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_GCMP_256)) { + ssid->pairwise_cipher |= WPA_CIPHER_GCMP_256; + ssid->group_cipher |= WPA_CIPHER_GCMP_256; + } + if (wpa_s->drv_capa_known && + (wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_CCMP_256)) { + ssid->pairwise_cipher |= WPA_CIPHER_CCMP_256; + ssid->group_cipher |= WPA_CIPHER_CCMP_256; + } break; } @@ -519,11 +532,18 @@ static int wpa_supplicant_wps_cred(void *ctx, case WPS_AUTH_WPA2PSK: ssid->auth_alg = WPA_AUTH_ALG_OPEN; ssid->key_mgmt = WPA_KEY_MGMT_PSK; + if (wpa_s->conf->wps_cred_add_sae && + cred->key_len != 2 * PMK_LEN) { + ssid->key_mgmt |= WPA_KEY_MGMT_SAE; +#ifdef CONFIG_IEEE80211W + ssid->ieee80211w = MGMT_FRAME_PROTECTION_OPTIONAL; +#endif /* CONFIG_IEEE80211W */ + } ssid->proto = WPA_PROTO_RSN; break; } - if (ssid->key_mgmt == WPA_KEY_MGMT_PSK) { + if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) { if (cred->key_len == 2 * PMK_LEN) { if (hexstr2bin((const char *) cred->key, ssid->psk, PMK_LEN)) { @@ -1029,10 +1049,9 @@ static struct wpa_ssid * wpas_wps_add_network(struct wpa_supplicant *wpa_s, continue; os_free(ssid->ssid); - ssid->ssid = os_malloc(bss->ssid_len); + ssid->ssid = os_memdup(bss->ssid, bss->ssid_len); if (ssid->ssid == NULL) break; - os_memcpy(ssid->ssid, bss->ssid, bss->ssid_len); ssid->ssid_len = bss->ssid_len; wpa_hexdump_ascii(MSG_DEBUG, "WPS: Picked SSID from " "scan results", @@ -1127,9 +1146,10 @@ static void wpas_wps_reassoc(struct wpa_supplicant *wpa_s, int wpas_wps_start_pbc(struct wpa_supplicant *wpa_s, const u8 *bssid, - int p2p_group) + int p2p_group, int multi_ap_backhaul_sta) { struct wpa_ssid *ssid; + char phase1[32]; #ifdef CONFIG_AP if (wpa_s->ap_iface) { @@ -1167,10 +1187,15 @@ int wpas_wps_start_pbc(struct wpa_supplicant *wpa_s, const u8 *bssid, } } #endif /* CONFIG_P2P */ - if (wpa_config_set(ssid, "phase1", "\"pbc=1\"", 0) < 0) + os_snprintf(phase1, sizeof(phase1), "pbc=1%s", + multi_ap_backhaul_sta ? " multi_ap=1" : ""); + if (wpa_config_set_quoted(ssid, "phase1", phase1) < 0) return -1; if (wpa_s->wps_fragment_size) ssid->eap.fragment_size = wpa_s->wps_fragment_size; + if (multi_ap_backhaul_sta) + ssid->multi_ap_backhaul_sta = 1; + wpa_supplicant_wps_event(wpa_s, WPS_EV_PBC_ACTIVE, NULL); eloop_register_timeout(WPS_PBC_WALK_TIME, 0, wpas_wps_timeout, wpa_s, NULL); wpas_wps_reassoc(wpa_s, ssid, bssid, 0); @@ -1483,6 +1508,9 @@ static void wpas_wps_set_uuid(struct wpa_supplicant *wpa_s, wpa_s->global->ifaces->wps->uuid, WPS_UUID_LEN); src = "from the first interface"; + } else if (wpa_s->conf->auto_uuid == 1) { + uuid_random(wps->uuid); + src = "based on random data"; } else { uuid_gen_mac_addr(wpa_s->own_addr, wps->uuid); src = "based on MAC address"; diff --git a/freebsd/contrib/wpa/wpa_supplicant/wps_supplicant.h b/freebsd/contrib/wpa/wpa_supplicant/wps_supplicant.h index c8fe47e3..0fbc8517 100644 --- a/freebsd/contrib/wpa/wpa_supplicant/wps_supplicant.h +++ b/freebsd/contrib/wpa/wpa_supplicant/wps_supplicant.h @@ -30,7 +30,7 @@ void wpas_wps_deinit(struct wpa_supplicant *wpa_s); int wpas_wps_eapol_cb(struct wpa_supplicant *wpa_s); enum wps_request_type wpas_wps_get_req_type(struct wpa_ssid *ssid); int wpas_wps_start_pbc(struct wpa_supplicant *wpa_s, const u8 *bssid, - int p2p_group); + int p2p_group, int multi_ap_backhaul_sta); int wpas_wps_start_pin(struct wpa_supplicant *wpa_s, const u8 *bssid, const char *pin, int p2p_group, u16 dev_pw_id); void wpas_wps_pbc_overlap(struct wpa_supplicant *wpa_s); diff --git a/freebsd/crypto/openssl/apps/asn1pars.c b/freebsd/crypto/openssl/apps/asn1pars.c index ec75690e..b9e29e6b 100644 --- a/freebsd/crypto/openssl/apps/asn1pars.c +++ b/freebsd/crypto/openssl/apps/asn1pars.c @@ -6,7 +6,7 @@ #endif /* __rtems__ */ /* - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -177,17 +177,17 @@ int asn1parse_main(int argc, char **argv) if (derfile && (derout = bio_open_default(derfile, 'w', FORMAT_ASN1)) == NULL) goto end; + if ((buf = BUF_MEM_new()) == NULL) + goto end; if (strictpem) { - if (PEM_read_bio(in, &name, &header, &str, &num) != - 1) { + if (PEM_read_bio(in, &name, &header, &str, &num) != 1) { BIO_printf(bio_err, "Error reading PEM file\n"); ERR_print_errors(bio_err); goto end; } + buf->data = (char *)str; + buf->length = buf->max = num; } else { - - if ((buf = BUF_MEM_new()) == NULL) - goto end; if (!BUF_MEM_grow(buf, BUFSIZ * 8)) goto end; /* Pre-allocate :-) */ @@ -310,8 +310,6 @@ int asn1parse_main(int argc, char **argv) BUF_MEM_free(buf); OPENSSL_free(name); OPENSSL_free(header); - if (strictpem) - OPENSSL_free(str); ASN1_TYPE_free(at); sk_OPENSSL_STRING_free(osk); return ret; diff --git a/freebsd/crypto/openssl/apps/cms.c b/freebsd/crypto/openssl/apps/cms.c index b1340a34..43c132c2 100644 --- a/freebsd/crypto/openssl/apps/cms.c +++ b/freebsd/crypto/openssl/apps/cms.c @@ -6,7 +6,7 @@ #endif /* __rtems__ */ /* - * Copyright 2008-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2008-2019 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -643,6 +643,7 @@ int cms_main(int argc, char **argv) goto opthelp; } } else if (!operation) { + BIO_printf(bio_err, "No operation option (-encrypt|-decrypt|-sign|-verify|...) specified.\n"); goto opthelp; } diff --git a/freebsd/crypto/openssl/apps/enc.c b/freebsd/crypto/openssl/apps/enc.c index ddbea12e..35200315 100644 --- a/freebsd/crypto/openssl/apps/enc.c +++ b/freebsd/crypto/openssl/apps/enc.c @@ -6,7 +6,7 @@ #endif /* __rtems__ */ /* - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -512,7 +512,7 @@ int enc_main(int argc, char **argv) if (hiv != NULL) { int siz = EVP_CIPHER_iv_length(cipher); if (siz == 0) { - BIO_printf(bio_err, "warning: iv not use by this cipher\n"); + BIO_printf(bio_err, "warning: iv not used by this cipher\n"); } else if (!set_hex(hiv, iv, siz)) { BIO_printf(bio_err, "invalid hex iv value\n"); goto end; diff --git a/freebsd/crypto/openssl/apps/ocsp.c b/freebsd/crypto/openssl/apps/ocsp.c index 056fdc02..2aaf3b9f 100644 --- a/freebsd/crypto/openssl/apps/ocsp.c +++ b/freebsd/crypto/openssl/apps/ocsp.c @@ -648,8 +648,10 @@ redo_accept: goto end; } - if (req != NULL && add_nonce) - OCSP_request_add1_nonce(req, NULL, -1); + if (req != NULL && add_nonce) { + if (!OCSP_request_add1_nonce(req, NULL, -1)) + goto end; + } if (signfile != NULL) { if (keyfile == NULL) @@ -1252,7 +1254,10 @@ static void make_ocsp_response(BIO *err, OCSP_RESPONSE **resp, OCSP_REQUEST *req goto end; } } - OCSP_basic_sign_ctx(bs, rcert, mctx, rother, flags); + if (!OCSP_basic_sign_ctx(bs, rcert, mctx, rother, flags)) { + *resp = OCSP_response_create(OCSP_RESPONSE_STATUS_INTERNALERROR, bs); + goto end; + } if (badsig) { const ASN1_OCTET_STRING *sig = OCSP_resp_get0_signature(bs); diff --git a/freebsd/crypto/openssl/apps/s_cb.c b/freebsd/crypto/openssl/apps/s_cb.c index f8524620..3df95478 100644 --- a/freebsd/crypto/openssl/apps/s_cb.c +++ b/freebsd/crypto/openssl/apps/s_cb.c @@ -690,6 +690,53 @@ static STRINT_PAIR tlsext_types[] = { {NULL} }; +/* from rfc8446 4.2.3. + gost (https://tools.ietf.org/id/draft-smyshlyaev-tls12-gost-suites-04.html) */ +static STRINT_PAIR signature_tls13_scheme_list[] = { + {"rsa_pkcs1_sha1", 0x0201 /* TLSEXT_SIGALG_rsa_pkcs1_sha1 */}, + {"ecdsa_sha1", 0x0203 /* TLSEXT_SIGALG_ecdsa_sha1 */}, +/* {"rsa_pkcs1_sha224", 0x0301 TLSEXT_SIGALG_rsa_pkcs1_sha224}, not in rfc8446 */ +/* {"ecdsa_sha224", 0x0303 TLSEXT_SIGALG_ecdsa_sha224} not in rfc8446 */ + {"rsa_pkcs1_sha256", 0x0401 /* TLSEXT_SIGALG_rsa_pkcs1_sha256 */}, + {"ecdsa_secp256r1_sha256", 0x0403 /* TLSEXT_SIGALG_ecdsa_secp256r1_sha256 */}, + {"rsa_pkcs1_sha384", 0x0501 /* TLSEXT_SIGALG_rsa_pkcs1_sha384 */}, + {"ecdsa_secp384r1_sha384", 0x0503 /* TLSEXT_SIGALG_ecdsa_secp384r1_sha384 */}, + {"rsa_pkcs1_sha512", 0x0601 /* TLSEXT_SIGALG_rsa_pkcs1_sha512 */}, + {"ecdsa_secp521r1_sha512", 0x0603 /* TLSEXT_SIGALG_ecdsa_secp521r1_sha512 */}, + {"rsa_pss_rsae_sha256", 0x0804 /* TLSEXT_SIGALG_rsa_pss_rsae_sha256 */}, + {"rsa_pss_rsae_sha384", 0x0805 /* TLSEXT_SIGALG_rsa_pss_rsae_sha384 */}, + {"rsa_pss_rsae_sha512", 0x0806 /* TLSEXT_SIGALG_rsa_pss_rsae_sha512 */}, + {"ed25519", 0x0807 /* TLSEXT_SIGALG_ed25519 */}, + {"ed448", 0x0808 /* TLSEXT_SIGALG_ed448 */}, + {"rsa_pss_pss_sha256", 0x0809 /* TLSEXT_SIGALG_rsa_pss_pss_sha256 */}, + {"rsa_pss_pss_sha384", 0x080a /* TLSEXT_SIGALG_rsa_pss_pss_sha384 */}, + {"rsa_pss_pss_sha512", 0x080b /* TLSEXT_SIGALG_rsa_pss_pss_sha512 */}, + {"gostr34102001", 0xeded /* TLSEXT_SIGALG_gostr34102001_gostr3411 */}, + {"gostr34102012_256", 0xeeee /* TLSEXT_SIGALG_gostr34102012_256_gostr34112012_256 */}, + {"gostr34102012_512", 0xefef /* TLSEXT_SIGALG_gostr34102012_512_gostr34112012_512 */}, + {NULL} +}; + +/* from rfc5246 7.4.1.4.1. */ +static STRINT_PAIR signature_tls12_alg_list[] = { + {"anonymous", TLSEXT_signature_anonymous /* 0 */}, + {"RSA", TLSEXT_signature_rsa /* 1 */}, + {"DSA", TLSEXT_signature_dsa /* 2 */}, + {"ECDSA", TLSEXT_signature_ecdsa /* 3 */}, + {NULL} +}; + +/* from rfc5246 7.4.1.4.1. */ +static STRINT_PAIR signature_tls12_hash_list[] = { + {"none", TLSEXT_hash_none /* 0 */}, + {"MD5", TLSEXT_hash_md5 /* 1 */}, + {"SHA1", TLSEXT_hash_sha1 /* 2 */}, + {"SHA224", TLSEXT_hash_sha224 /* 3 */}, + {"SHA256", TLSEXT_hash_sha256 /* 4 */}, + {"SHA384", TLSEXT_hash_sha384 /* 5 */}, + {"SHA512", TLSEXT_hash_sha512 /* 6 */}, + {NULL} +}; + void tlsext_cb(SSL *s, int client_server, int type, const unsigned char *data, int len, void *arg) { @@ -1294,9 +1341,9 @@ static STRINT_PAIR callback_types[] = { {"Supported Curve", SSL_SECOP_CURVE_SUPPORTED}, {"Shared Curve", SSL_SECOP_CURVE_SHARED}, {"Check Curve", SSL_SECOP_CURVE_CHECK}, - {"Supported Signature Algorithm digest", SSL_SECOP_SIGALG_SUPPORTED}, - {"Shared Signature Algorithm digest", SSL_SECOP_SIGALG_SHARED}, - {"Check Signature Algorithm digest", SSL_SECOP_SIGALG_CHECK}, + {"Supported Signature Algorithm", SSL_SECOP_SIGALG_SUPPORTED}, + {"Shared Signature Algorithm", SSL_SECOP_SIGALG_SHARED}, + {"Check Signature Algorithm", SSL_SECOP_SIGALG_CHECK}, {"Signature Algorithm mask", SSL_SECOP_SIGALG_MASK}, {"Certificate chain EE key", SSL_SECOP_EE_KEY}, {"Certificate chain CA key", SSL_SECOP_CA_KEY}, @@ -1316,29 +1363,37 @@ static int security_callback_debug(const SSL *s, const SSL_CTX *ctx, security_debug_ex *sdb = ex; int rv, show_bits = 1, cert_md = 0; const char *nm; + int show_nm; rv = sdb->old_cb(s, ctx, op, bits, nid, other, ex); if (rv == 1 && sdb->verbose < 2) return 1; BIO_puts(sdb->out, "Security callback: "); nm = lookup(op, callback_types, NULL); + show_nm = nm != NULL; switch (op) { case SSL_SECOP_TICKET: case SSL_SECOP_COMPRESSION: show_bits = 0; - nm = NULL; + show_nm = 0; break; case SSL_SECOP_VERSION: BIO_printf(sdb->out, "Version=%s", lookup(nid, ssl_versions, "???")); show_bits = 0; - nm = NULL; + show_nm = 0; break; case SSL_SECOP_CA_MD: case SSL_SECOP_PEER_CA_MD: cert_md = 1; break; + case SSL_SECOP_SIGALG_SUPPORTED: + case SSL_SECOP_SIGALG_SHARED: + case SSL_SECOP_SIGALG_CHECK: + case SSL_SECOP_SIGALG_MASK: + show_nm = 0; + break; } - if (nm != NULL) + if (show_nm) BIO_printf(sdb->out, "%s=", nm); switch (op & SSL_SECOP_OTHER_TYPE) { @@ -1385,27 +1440,28 @@ static int security_callback_debug(const SSL *s, const SSL_CTX *ctx, { const unsigned char *salg = other; const char *sname = NULL; - switch (salg[1]) { - case TLSEXT_signature_anonymous: - sname = "anonymous"; - break; - case TLSEXT_signature_rsa: - sname = "RSA"; - break; - case TLSEXT_signature_dsa: - sname = "DSA"; - break; - case TLSEXT_signature_ecdsa: - sname = "ECDSA"; - break; - } + int raw_sig_code = (salg[0] << 8) + salg[1]; /* always big endian (msb, lsb) */ + /* raw_sig_code: signature_scheme from tls1.3, or signature_and_hash from tls1.2 */ - BIO_puts(sdb->out, OBJ_nid2sn(nid)); - if (sname) - BIO_printf(sdb->out, ", algorithm=%s", sname); + if (nm != NULL) + BIO_printf(sdb->out, "%s", nm); else - BIO_printf(sdb->out, ", algid=%d", salg[1]); - break; + BIO_printf(sdb->out, "s_cb.c:security_callback_debug op=0x%x", op); + + sname = lookup(raw_sig_code, signature_tls13_scheme_list, NULL); + if (sname != NULL) { + BIO_printf(sdb->out, " scheme=%s", sname); + } else { + int alg_code = salg[1]; + int hash_code = salg[0]; + const char *alg_str = lookup(alg_code, signature_tls12_alg_list, NULL); + const char *hash_str = lookup(hash_code, signature_tls12_hash_list, NULL); + + if (alg_str != NULL && hash_str != NULL) + BIO_printf(sdb->out, " digest=%s, algorithm=%s", hash_str, alg_str); + else + BIO_printf(sdb->out, " scheme=unknown(0x%04x)", raw_sig_code); + } } } diff --git a/freebsd/crypto/openssl/apps/s_client.c b/freebsd/crypto/openssl/apps/s_client.c index 086220b4..4c052ef5 100644 --- a/freebsd/crypto/openssl/apps/s_client.c +++ b/freebsd/crypto/openssl/apps/s_client.c @@ -2275,7 +2275,7 @@ int s_client_main(int argc, char **argv) do { mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ); } - while (mbuf_len > 3 && mbuf[3] == '-'); + while (mbuf_len > 3 && (!isdigit(mbuf[0]) || !isdigit(mbuf[1]) || !isdigit(mbuf[2]) || mbuf[3] != ' ')); (void)BIO_flush(fbio); BIO_pop(fbio); BIO_free(fbio); diff --git a/freebsd/crypto/openssl/apps/speed.c b/freebsd/crypto/openssl/apps/speed.c index bf429758..02eb30a6 100644 --- a/freebsd/crypto/openssl/apps/speed.c +++ b/freebsd/crypto/openssl/apps/speed.c @@ -499,30 +499,35 @@ static const OPT_PAIR rsa_choices[] = { static double rsa_results[RSA_NUM][2]; /* 2 ops: sign then verify */ #endif /* OPENSSL_NO_RSA */ -#define R_EC_P160 0 -#define R_EC_P192 1 -#define R_EC_P224 2 -#define R_EC_P256 3 -#define R_EC_P384 4 -#define R_EC_P521 5 -#define R_EC_K163 6 -#define R_EC_K233 7 -#define R_EC_K283 8 -#define R_EC_K409 9 -#define R_EC_K571 10 -#define R_EC_B163 11 -#define R_EC_B233 12 -#define R_EC_B283 13 -#define R_EC_B409 14 -#define R_EC_B571 15 -#define R_EC_BRP256R1 16 -#define R_EC_BRP256T1 17 -#define R_EC_BRP384R1 18 -#define R_EC_BRP384T1 19 -#define R_EC_BRP512R1 20 -#define R_EC_BRP512T1 21 -#define R_EC_X25519 22 -#define R_EC_X448 23 +enum { + R_EC_P160, + R_EC_P192, + R_EC_P224, + R_EC_P256, + R_EC_P384, + R_EC_P521, +#ifndef OPENSSL_NO_EC2M + R_EC_K163, + R_EC_K233, + R_EC_K283, + R_EC_K409, + R_EC_K571, + R_EC_B163, + R_EC_B233, + R_EC_B283, + R_EC_B409, + R_EC_B571, +#endif + R_EC_BRP256R1, + R_EC_BRP256T1, + R_EC_BRP384R1, + R_EC_BRP384T1, + R_EC_BRP512R1, + R_EC_BRP512T1, + R_EC_X25519, + R_EC_X448 +}; + #ifndef OPENSSL_NO_EC static OPT_PAIR ecdsa_choices[] = { {"ecdsap160", R_EC_P160}, @@ -531,6 +536,7 @@ static OPT_PAIR ecdsa_choices[] = { {"ecdsap256", R_EC_P256}, {"ecdsap384", R_EC_P384}, {"ecdsap521", R_EC_P521}, +# ifndef OPENSSL_NO_EC2M {"ecdsak163", R_EC_K163}, {"ecdsak233", R_EC_K233}, {"ecdsak283", R_EC_K283}, @@ -541,6 +547,7 @@ static OPT_PAIR ecdsa_choices[] = { {"ecdsab283", R_EC_B283}, {"ecdsab409", R_EC_B409}, {"ecdsab571", R_EC_B571}, +# endif {"ecdsabrp256r1", R_EC_BRP256R1}, {"ecdsabrp256t1", R_EC_BRP256T1}, {"ecdsabrp384r1", R_EC_BRP384R1}, @@ -559,6 +566,7 @@ static const OPT_PAIR ecdh_choices[] = { {"ecdhp256", R_EC_P256}, {"ecdhp384", R_EC_P384}, {"ecdhp521", R_EC_P521}, +# ifndef OPENSSL_NO_EC2M {"ecdhk163", R_EC_K163}, {"ecdhk233", R_EC_K233}, {"ecdhk283", R_EC_K283}, @@ -569,6 +577,7 @@ static const OPT_PAIR ecdh_choices[] = { {"ecdhb283", R_EC_B283}, {"ecdhb409", R_EC_B409}, {"ecdhb571", R_EC_B571}, +# endif {"ecdhbrp256r1", R_EC_BRP256R1}, {"ecdhbrp256t1", R_EC_BRP256T1}, {"ecdhbrp384r1", R_EC_BRP384R1}, @@ -1520,6 +1529,7 @@ int speed_main(int argc, char **argv) {"nistp256", NID_X9_62_prime256v1, 256}, {"nistp384", NID_secp384r1, 384}, {"nistp521", NID_secp521r1, 521}, +# ifndef OPENSSL_NO_EC2M /* Binary Curves */ {"nistk163", NID_sect163k1, 163}, {"nistk233", NID_sect233k1, 233}, @@ -1531,6 +1541,7 @@ int speed_main(int argc, char **argv) {"nistb283", NID_sect283r1, 283}, {"nistb409", NID_sect409r1, 409}, {"nistb571", NID_sect571r1, 571}, +# endif {"brainpoolP256r1", NID_brainpoolP256r1, 256}, {"brainpoolP256t1", NID_brainpoolP256t1, 256}, {"brainpoolP384r1", NID_brainpoolP384r1, 384}, @@ -2050,6 +2061,7 @@ int speed_main(int argc, char **argv) } } } +# ifndef OPENSSL_NO_EC2M ecdsa_c[R_EC_K163][0] = count / 1000; ecdsa_c[R_EC_K163][1] = count / 1000 / 2; for (i = R_EC_K233; i <= R_EC_K571; i++) { @@ -2078,6 +2090,7 @@ int speed_main(int argc, char **argv) } } } +# endif ecdh_c[R_EC_P160][0] = count / 1000; for (i = R_EC_P192; i <= R_EC_P521; i++) { @@ -2090,6 +2103,7 @@ int speed_main(int argc, char **argv) } } } +# ifndef OPENSSL_NO_EC2M ecdh_c[R_EC_K163][0] = count / 1000; for (i = R_EC_K233; i <= R_EC_K571; i++) { ecdh_c[i][0] = ecdh_c[i - 1][0] / 2; @@ -2112,6 +2126,7 @@ int speed_main(int argc, char **argv) } } } +# endif /* repeated code good to factorize */ ecdh_c[R_EC_BRP256R1][0] = count / 1000; for (i = R_EC_BRP384R1; i <= R_EC_BRP512R1; i += 2) { @@ -2633,16 +2648,28 @@ int speed_main(int argc, char **argv) for (k = 0; k < loopargs_len; k++) { loopargs[k].ctx = EVP_CIPHER_CTX_new(); - EVP_CipherInit_ex(loopargs[k].ctx, evp_cipher, NULL, NULL, - iv, decrypt ? 0 : 1); + if (loopargs[k].ctx == NULL) { + BIO_printf(bio_err, "\nEVP_CIPHER_CTX_new failure\n"); + exit(1); + } + if (!EVP_CipherInit_ex(loopargs[k].ctx, evp_cipher, NULL, + NULL, iv, decrypt ? 0 : 1)) { + BIO_printf(bio_err, "\nEVP_CipherInit_ex failure\n"); + ERR_print_errors(bio_err); + exit(1); + } EVP_CIPHER_CTX_set_padding(loopargs[k].ctx, 0); keylen = EVP_CIPHER_CTX_key_length(loopargs[k].ctx); loopargs[k].key = app_malloc(keylen, "evp_cipher key"); EVP_CIPHER_CTX_rand_key(loopargs[k].ctx, loopargs[k].key); - EVP_CipherInit_ex(loopargs[k].ctx, NULL, NULL, - loopargs[k].key, NULL, -1); + if (!EVP_CipherInit_ex(loopargs[k].ctx, NULL, NULL, + loopargs[k].key, NULL, -1)) { + BIO_printf(bio_err, "\nEVP_CipherInit_ex failure\n"); + ERR_print_errors(bio_err); + exit(1); + } OPENSSL_clear_free(loopargs[k].key, keylen); } diff --git a/freebsd/crypto/openssl/crypto/bio/b_addr.c b/freebsd/crypto/openssl/crypto/bio/b_addr.c index 0818431f..5a672da6 100644 --- a/freebsd/crypto/openssl/crypto/bio/b_addr.c +++ b/freebsd/crypto/openssl/crypto/bio/b_addr.c @@ -685,6 +685,12 @@ int BIO_lookup_ex(const char *host, const char *service, int lookup_type, hints.ai_family = family; hints.ai_socktype = socktype; hints.ai_protocol = protocol; +#ifdef AI_ADDRCONFIG +#ifdef AF_UNSPEC + if (family == AF_UNSPEC) +#endif + hints.ai_flags |= AI_ADDRCONFIG; +#endif if (lookup_type == BIO_LOOKUP_SERVER) hints.ai_flags |= AI_PASSIVE; diff --git a/freebsd/crypto/openssl/crypto/bio/bss_mem.c b/freebsd/crypto/openssl/crypto/bio/bss_mem.c index 0e02d0c0..8f14d790 100644 --- a/freebsd/crypto/openssl/crypto/bio/bss_mem.c +++ b/freebsd/crypto/openssl/crypto/bio/bss_mem.c @@ -59,7 +59,12 @@ static const BIO_METHOD secmem_method = { NULL, /* mem_callback_ctrl */ }; -/* BIO memory stores buffer and read pointer */ +/* + * BIO memory stores buffer and read pointer + * however the roles are different for read only BIOs. + * In that case the readp just stores the original state + * to be used for reset. + */ typedef struct bio_buf_mem_st { struct buf_mem_st *buf; /* allocated buffer */ struct buf_mem_st *readp; /* read pointer */ @@ -194,11 +199,14 @@ static int mem_read(BIO *b, char *out, int outl) BIO_BUF_MEM *bbm = (BIO_BUF_MEM *)b->ptr; BUF_MEM *bm = bbm->readp; + if (b->flags & BIO_FLAGS_MEM_RDONLY) + bm = bbm->buf; BIO_clear_retry_flags(b); ret = (outl >= 0 && (size_t)outl > bm->length) ? (int)bm->length : outl; if ((out != NULL) && (ret > 0)) { memcpy(out, bm->data, ret); bm->length -= ret; + bm->max -= ret; bm->data += ret; } else if (bm->length == 0) { ret = b->num; @@ -243,29 +251,36 @@ static long mem_ctrl(BIO *b, int cmd, long num, void *ptr) BIO_BUF_MEM *bbm = (BIO_BUF_MEM *)b->ptr; BUF_MEM *bm; + if (b->flags & BIO_FLAGS_MEM_RDONLY) + bm = bbm->buf; + else + bm = bbm->readp; + switch (cmd) { case BIO_CTRL_RESET: bm = bbm->buf; if (bm->data != NULL) { - /* For read only case reset to the start again */ - if ((b->flags & BIO_FLAGS_MEM_RDONLY) || (b->flags & BIO_FLAGS_NONCLEAR_RST)) { - bm->length = bm->max; + if (!(b->flags & BIO_FLAGS_MEM_RDONLY)) { + if (b->flags & BIO_FLAGS_NONCLEAR_RST) { + bm->length = bm->max; + } else { + memset(bm->data, 0, bm->max); + bm->length = 0; + } + *bbm->readp = *bbm->buf; } else { - memset(bm->data, 0, bm->max); - bm->length = 0; + /* For read only case just reset to the start again */ + *bbm->buf = *bbm->readp; } - *bbm->readp = *bbm->buf; } break; case BIO_CTRL_EOF: - bm = bbm->readp; ret = (long)(bm->length == 0); break; case BIO_C_SET_BUF_MEM_EOF_RETURN: b->num = (int)num; break; case BIO_CTRL_INFO: - bm = bbm->readp; ret = (long)bm->length; if (ptr != NULL) { pptr = (char **)ptr; @@ -280,8 +295,9 @@ static long mem_ctrl(BIO *b, int cmd, long num, void *ptr) break; case BIO_C_GET_BUF_MEM_PTR: if (ptr != NULL) { - mem_buf_sync(b); - bm = bbm->readp; + if (!(b->flags & BIO_FLAGS_MEM_RDONLY)) + mem_buf_sync(b); + bm = bbm->buf; pptr = (char **)ptr; *pptr = (char *)bm; } @@ -296,7 +312,6 @@ static long mem_ctrl(BIO *b, int cmd, long num, void *ptr) ret = 0L; break; case BIO_CTRL_PENDING: - bm = bbm->readp; ret = (long)bm->length; break; case BIO_CTRL_DUP: @@ -320,6 +335,8 @@ static int mem_gets(BIO *bp, char *buf, int size) BIO_BUF_MEM *bbm = (BIO_BUF_MEM *)bp->ptr; BUF_MEM *bm = bbm->readp; + if (bp->flags & BIO_FLAGS_MEM_RDONLY) + bm = bbm->buf; BIO_clear_retry_flags(bp); j = bm->length; if ((size - 1) < j) diff --git a/freebsd/crypto/openssl/crypto/blake2/blake2b.c b/freebsd/crypto/openssl/crypto/blake2/blake2b.c index 461d1318..efbdbeb0 100644 --- a/freebsd/crypto/openssl/crypto/blake2/blake2b.c +++ b/freebsd/crypto/openssl/crypto/blake2/blake2b.c @@ -1,7 +1,7 @@ #include <machine/rtems-bsd-user-space.h> /* - * Copyright 2016-2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -25,10 +25,10 @@ static const uint64_t blake2b_IV[8] = { - 0x6a09e667f3bcc908U, 0xbb67ae8584caa73bU, - 0x3c6ef372fe94f82bU, 0xa54ff53a5f1d36f1U, - 0x510e527fade682d1U, 0x9b05688c2b3e6c1fU, - 0x1f83d9abfb41bd6bU, 0x5be0cd19137e2179U + 0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL, + 0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL, + 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL, + 0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL }; static const uint8_t blake2b_sigma[12][16] = diff --git a/freebsd/crypto/openssl/crypto/bn/bn_ctx.c b/freebsd/crypto/openssl/crypto/bn/bn_ctx.c index 5db64ef6..96bcde8a 100644 --- a/freebsd/crypto/openssl/crypto/bn/bn_ctx.c +++ b/freebsd/crypto/openssl/crypto/bn/bn_ctx.c @@ -196,6 +196,8 @@ void BN_CTX_start(BN_CTX *ctx) void BN_CTX_end(BN_CTX *ctx) { + if (ctx == NULL) + return; CTXDBG_ENTRY("BN_CTX_end", ctx); if (ctx->err_stack) ctx->err_stack--; diff --git a/freebsd/crypto/openssl/crypto/bn/bn_lib.c b/freebsd/crypto/openssl/crypto/bn/bn_lib.c index a37d5441..e900e4ae 100644 --- a/freebsd/crypto/openssl/crypto/bn/bn_lib.c +++ b/freebsd/crypto/openssl/crypto/bn/bn_lib.c @@ -340,6 +340,8 @@ void BN_swap(BIGNUM *a, BIGNUM *b) void BN_clear(BIGNUM *a) { + if (a == NULL) + return; bn_check_top(a); if (a->d != NULL) OPENSSL_cleanse(a->d, sizeof(*a->d) * a->dmax); diff --git a/freebsd/crypto/openssl/crypto/bn/bn_prime.c b/freebsd/crypto/openssl/crypto/bn/bn_prime.c index 9e924a55..c379eab8 100644 --- a/freebsd/crypto/openssl/crypto/bn/bn_prime.c +++ b/freebsd/crypto/openssl/crypto/bn/bn_prime.c @@ -1,7 +1,7 @@ #include <machine/rtems-bsd-user-space.h> /* - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -137,8 +137,7 @@ int BN_generate_prime_ex(BIGNUM *ret, int bits, int safe, found = 1; err: OPENSSL_free(mods); - if (ctx != NULL) - BN_CTX_end(ctx); + BN_CTX_end(ctx); BN_CTX_free(ctx); bn_check_top(ret); return found; diff --git a/freebsd/crypto/openssl/crypto/conf/conf_sap.c b/freebsd/crypto/openssl/crypto/conf/conf_sap.c index a76b3660..5010574b 100644 --- a/freebsd/crypto/openssl/crypto/conf/conf_sap.c +++ b/freebsd/crypto/openssl/crypto/conf/conf_sap.c @@ -37,6 +37,7 @@ void OPENSSL_config(const char *appname) memset(&settings, 0, sizeof(settings)); if (appname != NULL) settings.appname = strdup(appname); + settings.flags = DEFAULT_CONF_MFLAGS; OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, &settings); } #endif diff --git a/freebsd/crypto/openssl/crypto/dh/dh_check.c b/freebsd/crypto/openssl/crypto/dh/dh_check.c index ff5d8f81..0ff2d5f7 100644 --- a/freebsd/crypto/openssl/crypto/dh/dh_check.c +++ b/freebsd/crypto/openssl/crypto/dh/dh_check.c @@ -1,7 +1,7 @@ #include <machine/rtems-bsd-user-space.h> /* - * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -14,6 +14,8 @@ #include <openssl/bn.h> #include "dh_locl.h" +# define DH_NUMBER_ITERATIONS_FOR_PRIME 64 + /*- * Check that p and g are suitable enough * @@ -60,10 +62,8 @@ int DH_check_params(const DH *dh, int *ret) ok = 1; err: - if (ctx != NULL) { - BN_CTX_end(ctx); - BN_CTX_free(ctx); - } + BN_CTX_end(ctx); + BN_CTX_free(ctx); return ok; } @@ -129,7 +129,7 @@ int DH_check(const DH *dh, int *ret) if (!BN_is_one(t1)) *ret |= DH_NOT_SUITABLE_GENERATOR; } - r = BN_is_prime_ex(dh->q, BN_prime_checks, ctx, NULL); + r = BN_is_prime_ex(dh->q, DH_NUMBER_ITERATIONS_FOR_PRIME, ctx, NULL); if (r < 0) goto err; if (!r) @@ -157,7 +157,7 @@ int DH_check(const DH *dh, int *ret) } else *ret |= DH_UNABLE_TO_CHECK_GENERATOR; - r = BN_is_prime_ex(dh->p, BN_prime_checks, ctx, NULL); + r = BN_is_prime_ex(dh->p, DH_NUMBER_ITERATIONS_FOR_PRIME, ctx, NULL); if (r < 0) goto err; if (!r) @@ -165,7 +165,7 @@ int DH_check(const DH *dh, int *ret) else if (!dh->q) { if (!BN_rshift1(t1, dh->p)) goto err; - r = BN_is_prime_ex(t1, BN_prime_checks, ctx, NULL); + r = BN_is_prime_ex(t1, DH_NUMBER_ITERATIONS_FOR_PRIME, ctx, NULL); if (r < 0) goto err; if (!r) @@ -173,10 +173,8 @@ int DH_check(const DH *dh, int *ret) } ok = 1; err: - if (ctx != NULL) { - BN_CTX_end(ctx); - BN_CTX_free(ctx); - } + BN_CTX_end(ctx); + BN_CTX_free(ctx); return ok; } @@ -227,9 +225,7 @@ int DH_check_pub_key(const DH *dh, const BIGNUM *pub_key, int *ret) ok = 1; err: - if (ctx != NULL) { - BN_CTX_end(ctx); - BN_CTX_free(ctx); - } + BN_CTX_end(ctx); + BN_CTX_free(ctx); return ok; } diff --git a/freebsd/crypto/openssl/crypto/dh/dh_gen.c b/freebsd/crypto/openssl/crypto/dh/dh_gen.c index 74079d40..74c9cdbb 100644 --- a/freebsd/crypto/openssl/crypto/dh/dh_gen.c +++ b/freebsd/crypto/openssl/crypto/dh/dh_gen.c @@ -1,7 +1,7 @@ #include <machine/rtems-bsd-user-space.h> /* - * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -124,9 +124,7 @@ static int dh_builtin_genparams(DH *ret, int prime_len, int generator, ok = 0; } - if (ctx != NULL) { - BN_CTX_end(ctx); - BN_CTX_free(ctx); - } + BN_CTX_end(ctx); + BN_CTX_free(ctx); return ok; } diff --git a/freebsd/crypto/openssl/crypto/dh/dh_key.c b/freebsd/crypto/openssl/crypto/dh/dh_key.c index 4cf29bc7..64d6e7da 100644 --- a/freebsd/crypto/openssl/crypto/dh/dh_key.c +++ b/freebsd/crypto/openssl/crypto/dh/dh_key.c @@ -1,7 +1,7 @@ #include <machine/rtems-bsd-user-space.h> /* - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -207,10 +207,8 @@ static int compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh) ret = BN_bn2bin(tmp, key); err: - if (ctx != NULL) { - BN_CTX_end(ctx); - BN_CTX_free(ctx); - } + BN_CTX_end(ctx); + BN_CTX_free(ctx); return ret; } diff --git a/freebsd/crypto/openssl/crypto/dh/dh_pmeth.c b/freebsd/crypto/openssl/crypto/dh/dh_pmeth.c index b2fa93c4..a182378e 100644 --- a/freebsd/crypto/openssl/crypto/dh/dh_pmeth.c +++ b/freebsd/crypto/openssl/crypto/dh/dh_pmeth.c @@ -1,7 +1,7 @@ #include <machine/rtems-bsd-user-space.h> /* - * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2006-2019 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -56,7 +56,7 @@ static int pkey_dh_init(EVP_PKEY_CTX *ctx) DHerr(DH_F_PKEY_DH_INIT, ERR_R_MALLOC_FAILURE); return 0; } - dctx->prime_len = 1024; + dctx->prime_len = 2048; dctx->subprime_len = -1; dctx->generator = 2; dctx->kdf_type = EVP_PKEY_DH_KDF_NONE; diff --git a/freebsd/crypto/openssl/crypto/dsa/dsa_gen.c b/freebsd/crypto/openssl/crypto/dsa/dsa_gen.c index 84d18b3d..a16a61eb 100644 --- a/freebsd/crypto/openssl/crypto/dsa/dsa_gen.c +++ b/freebsd/crypto/openssl/crypto/dsa/dsa_gen.c @@ -1,7 +1,7 @@ #include <machine/rtems-bsd-user-space.h> /* - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -294,8 +294,7 @@ int dsa_builtin_paramgen(DSA *ret, size_t bits, size_t qbits, if (seed_out) memcpy(seed_out, seed, qsize); } - if (ctx) - BN_CTX_end(ctx); + BN_CTX_end(ctx); BN_CTX_free(ctx); BN_MONT_CTX_free(mont); return ok; @@ -609,8 +608,7 @@ int dsa_builtin_paramgen2(DSA *ret, size_t L, size_t N, OPENSSL_free(seed); if (seed_out != seed_tmp) OPENSSL_free(seed_tmp); - if (ctx) - BN_CTX_end(ctx); + BN_CTX_end(ctx); BN_CTX_free(ctx); BN_MONT_CTX_free(mont); EVP_MD_CTX_free(mctx); diff --git a/freebsd/crypto/openssl/crypto/dsa/dsa_ossl.c b/freebsd/crypto/openssl/crypto/dsa/dsa_ossl.c index 09d2c440..b6834f5d 100644 --- a/freebsd/crypto/openssl/crypto/dsa/dsa_ossl.c +++ b/freebsd/crypto/openssl/crypto/dsa/dsa_ossl.c @@ -1,7 +1,7 @@ #include <machine/rtems-bsd-user-space.h> /* - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -192,6 +192,12 @@ static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, return 0; } + /* Reject obviously invalid parameters */ + if (BN_is_zero(dsa->p) || BN_is_zero(dsa->q) || BN_is_zero(dsa->g)) { + DSAerr(DSA_F_DSA_SIGN_SETUP, DSA_R_INVALID_PARAMETERS); + return 0; + } + k = BN_new(); l = BN_new(); if (k == NULL || l == NULL) diff --git a/freebsd/crypto/openssl/crypto/dsa/dsa_pmeth.c b/freebsd/crypto/openssl/crypto/dsa/dsa_pmeth.c index 0e2dd54a..64aa8c29 100644 --- a/freebsd/crypto/openssl/crypto/dsa/dsa_pmeth.c +++ b/freebsd/crypto/openssl/crypto/dsa/dsa_pmeth.c @@ -1,7 +1,7 @@ #include <machine/rtems-bsd-user-space.h> /* - * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2006-2019 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -22,8 +22,8 @@ typedef struct { /* Parameter gen parameters */ - int nbits; /* size of p in bits (default: 1024) */ - int qbits; /* size of q in bits (default: 160) */ + int nbits; /* size of p in bits (default: 2048) */ + int qbits; /* size of q in bits (default: 224) */ const EVP_MD *pmd; /* MD for parameter generation */ /* Keygen callback info */ int gentmp[2]; @@ -37,8 +37,8 @@ static int pkey_dsa_init(EVP_PKEY_CTX *ctx) if (dctx == NULL) return 0; - dctx->nbits = 1024; - dctx->qbits = 160; + dctx->nbits = 2048; + dctx->qbits = 224; dctx->pmd = NULL; dctx->md = NULL; @@ -140,7 +140,11 @@ static int pkey_dsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) EVP_MD_type((const EVP_MD *)p2) != NID_sha224 && EVP_MD_type((const EVP_MD *)p2) != NID_sha256 && EVP_MD_type((const EVP_MD *)p2) != NID_sha384 && - EVP_MD_type((const EVP_MD *)p2) != NID_sha512) { + EVP_MD_type((const EVP_MD *)p2) != NID_sha512 && + EVP_MD_type((const EVP_MD *)p2) != NID_sha3_224 && + EVP_MD_type((const EVP_MD *)p2) != NID_sha3_256 && + EVP_MD_type((const EVP_MD *)p2) != NID_sha3_384 && + EVP_MD_type((const EVP_MD *)p2) != NID_sha3_512) { DSAerr(DSA_F_PKEY_DSA_CTRL, DSA_R_INVALID_DIGEST_TYPE); return 0; } diff --git a/freebsd/crypto/openssl/crypto/ec/curve25519.c b/freebsd/crypto/openssl/crypto/ec/curve25519.c index 8594d4e9..94d7a9e6 100644 --- a/freebsd/crypto/openssl/crypto/ec/curve25519.c +++ b/freebsd/crypto/openssl/crypto/ec/curve25519.c @@ -1,7 +1,7 @@ #include <machine/rtems-bsd-user-space.h> /* - * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -256,6 +256,7 @@ static void x25519_scalar_mulx(uint8_t out[32], const uint8_t scalar[32], #if defined(X25519_ASM) \ || ( (defined(__SIZEOF_INT128__) && __SIZEOF_INT128__ == 16) \ && !defined(__sparc__) \ + && (!defined(__SIZEOF_LONG__) || (__SIZEOF_LONG__ == 8)) \ && !(defined(__ANDROID__) && !defined(__clang__)) ) /* * Base 2^51 implementation. It's virtually no different from reference diff --git a/freebsd/crypto/openssl/crypto/ec/curve448/curve448.c b/freebsd/crypto/openssl/crypto/ec/curve448/curve448.c index c7d3b29b..e85ace90 100644 --- a/freebsd/crypto/openssl/crypto/ec/curve448/curve448.c +++ b/freebsd/crypto/openssl/crypto/ec/curve448/curve448.c @@ -1,7 +1,7 @@ #include <machine/rtems-bsd-user-space.h> /* - * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved. * Copyright 2015-2016 Cryptography Research, Inc. * * Licensed under the OpenSSL license (the "License"). You may not use @@ -29,8 +29,8 @@ static const curve448_scalar_t precomputed_scalarmul_adjustment = { { { - SC_LIMB(0xc873d6d54a7bb0cf), SC_LIMB(0xe933d8d723a70aad), - SC_LIMB(0xbb124b65129c96fd), SC_LIMB(0x00000008335dc163) + SC_LIMB(0xc873d6d54a7bb0cfULL), SC_LIMB(0xe933d8d723a70aadULL), + SC_LIMB(0xbb124b65129c96fdULL), SC_LIMB(0x00000008335dc163ULL) } } }; diff --git a/freebsd/crypto/openssl/crypto/ec/curve448/curve448_tables.c b/freebsd/crypto/openssl/crypto/ec/curve448/curve448_tables.c index 3a6e9fa6..2e95acb2 100644 --- a/freebsd/crypto/openssl/crypto/ec/curve448/curve448_tables.c +++ b/freebsd/crypto/openssl/crypto/ec/curve448/curve448_tables.c @@ -1,7 +1,7 @@ #include <machine/rtems-bsd-user-space.h> /* - * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved. * Copyright 2015-2016 Cryptography Research, Inc. * * Licensed under the OpenSSL license (the "License"). You may not use @@ -18,325 +18,1045 @@ static const curve448_precomputed_s curve448_precomputed_base_table = { { {{ - {FIELD_LITERAL(0x00cc3b062366f4cc,0x003d6e34e314aa3c,0x00d51c0a7521774d,0x0094e060eec6ab8b,0x00d21291b4d80082,0x00befed12b55ef1e,0x00c3dd2df5c94518,0x00e0a7b112b8d4e6)}, - {FIELD_LITERAL(0x0019eb5608d8723a,0x00d1bab52fb3aedb,0x00270a7311ebc90c,0x0037c12b91be7f13,0x005be16cd8b5c704,0x003e181acda888e1,0x00bc1f00fc3fc6d0,0x00d3839bfa319e20)}, - {FIELD_LITERAL(0x003caeb88611909f,0x00ea8b378c4df3d4,0x00b3295b95a5a19a,0x00a65f97514bdfb5,0x00b39efba743cab1,0x0016ba98b862fd2d,0x0001508812ee71d7,0x000a75740eea114a)}, - }}, {{ - {FIELD_LITERAL(0x00ebcf0eb649f823,0x00166d332e98ea03,0x0059ddf64f5cd5f6,0x0047763123d9471b,0x00a64065c53ef62f,0x00978e44c480153d,0x000b5b2a0265f194,0x0046a24b9f32965a)}, - {FIELD_LITERAL(0x00b9eef787034df0,0x0020bc24de3390cd,0x000022160bae99bb,0x00ae66e886e97946,0x0048d4bbe02cbb8b,0x0072ba97b34e38d4,0x00eae7ec8f03e85a,0x005ba92ecf808b2c)}, - {FIELD_LITERAL(0x00c9cfbbe74258fd,0x00843a979ea9eaa7,0x000cbb4371cfbe90,0x0059bac8f7f0a628,0x004b3dff882ff530,0x0011869df4d90733,0x00595aa71f4abfc2,0x0070e2d38990c2e6)}, - }}, {{ - {FIELD_LITERAL(0x00de2010c0a01733,0x00c739a612e24297,0x00a7212643141d7c,0x00f88444f6b67c11,0x00484b7b16ec28f2,0x009c1b8856af9c68,0x00ff4669591fe9d6,0x0054974be08a32c8)}, - {FIELD_LITERAL(0x0010de3fd682ceed,0x008c07642d83ca4e,0x0013bb064e00a1cc,0x009411ae27870e11,0x00ea8e5b4d531223,0x0032fe7d2aaece2e,0x00d989e243e7bb41,0x000fe79a508e9b8b)}, - {FIELD_LITERAL(0x005e0426b9bfc5b1,0x0041a5b1d29ee4fa,0x0015b0def7774391,0x00bc164f1f51af01,0x00d543b0942797b9,0x003c129b6398099c,0x002b114c6e5adf18,0x00b4e630e4018a7b)}, - }}, {{ - {FIELD_LITERAL(0x00d490afc95f8420,0x00b096bf50c1d9b9,0x00799fd707679866,0x007c74d9334afbea,0x00efaa8be80ff4ed,0x0075c4943bb81694,0x00c21c2fca161f36,0x00e77035d492bfee)}, - {FIELD_LITERAL(0x006658a190dd6661,0x00e0e9bab38609a6,0x0028895c802237ed,0x006a0229c494f587,0x002dcde96c9916b7,0x00d158822de16218,0x00173b917a06856f,0x00ca78a79ae07326)}, - {FIELD_LITERAL(0x00e35bfc79caced4,0x0087238a3e1fe3bb,0x00bcbf0ff4ceff5b,0x00a19c1c94099b91,0x0071e102b49db976,0x0059e3d004eada1e,0x008da78afa58a47e,0x00579c8ebf269187)}, - }}, {{ - {FIELD_LITERAL(0x00a16c2905eee75f,0x009d4bcaea2c7e1d,0x00d3bd79bfad19df,0x0050da745193342c,0x006abdb8f6b29ab1,0x00a24fe0a4fef7ef,0x0063730da1057dfb,0x00a08c312c8eb108)}, - {FIELD_LITERAL(0x00b583be005375be,0x00a40c8f8a4e3df4,0x003fac4a8f5bdbf7,0x00d4481d872cd718,0x004dc8749cdbaefe,0x00cce740d5e5c975,0x000b1c1f4241fd21,0x00a76de1b4e1cd07)}, - {FIELD_LITERAL(0x007a076500d30b62,0x000a6e117b7f090f,0x00c8712ae7eebd9a,0x000fbd6c1d5f6ff7,0x003a7977246ebf11,0x00166ed969c6600e,0x00aa42e469c98bec,0x00dc58f307cf0666)}, - }}, {{ - {FIELD_LITERAL(0x004b491f65a9a28b,0x006a10309e8a55b7,0x00b67210185187ef,0x00cf6497b12d9b8f,0x0085778c56e2b1ba,0x0015b4c07a814d85,0x00686479e62da561,0x008de5d88f114916)}, - {FIELD_LITERAL(0x00e37c88d6bba7b1,0x003e4577e1b8d433,0x0050d8ea5f510ec0,0x0042fc9f2da9ef59,0x003bd074c1141420,0x00561b8b7b68774e,0x00232e5e5d1013a3,0x006b7f2cb3d7e73f)}, - {FIELD_LITERAL(0x004bdd0f0b41e6a0,0x001773057c405d24,0x006029f99915bd97,0x006a5ba70a17fe2f,0x0046111977df7e08,0x004d8124c89fb6b7,0x00580983b2bb2724,0x00207bf330d6f3fe)}, - }}, {{ - {FIELD_LITERAL(0x007efdc93972a48b,0x002f5e50e78d5fee,0x0080dc11d61c7fe5,0x0065aa598707245b,0x009abba2300641be,0x000c68787656543a,0x00ffe0fef2dc0a17,0x00007ffbd6cb4f3a)}, - {FIELD_LITERAL(0x0036012f2b836efc,0x00458c126d6b5fbc,0x00a34436d719ad1e,0x0097be6167117dea,0x0009c219c879cff3,0x0065564493e60755,0x00993ac94a8cdec0,0x002d4885a4d0dbaf)}, - {FIELD_LITERAL(0x00598b60b4c068ba,0x00c547a0be7f1afd,0x009582164acf12af,0x00af4acac4fbbe40,0x005f6ca7c539121a,0x003b6e752ebf9d66,0x00f08a30d5cac5d4,0x00e399bb5f97c5a9)}, - }}, {{ - {FIELD_LITERAL(0x007445a0409c0a66,0x00a65c369f3829c0,0x0031d248a4f74826,0x006817f34defbe8e,0x00649741d95ebf2e,0x00d46466ab16b397,0x00fdc35703bee414,0x00343b43334525f8)}, - {FIELD_LITERAL(0x001796bea93f6401,0x00090c5a42e85269,0x00672412ba1252ed,0x001201d47b6de7de,0x006877bccfe66497,0x00b554fd97a4c161,0x009753f42dbac3cf,0x00e983e3e378270a)}, - {FIELD_LITERAL(0x00ac3eff18849872,0x00f0eea3bff05690,0x00a6d72c21dd505d,0x001b832642424169,0x00a6813017b540e5,0x00a744bd71b385cd,0x0022a7d089130a7b,0x004edeec9a133486)}, - }}, {{ - {FIELD_LITERAL(0x00b2d6729196e8a9,0x0088a9bb2031cef4,0x00579e7787dc1567,0x0030f49feb059190,0x00a0b1d69c7f7d8f,0x0040bdcc6d9d806f,0x00d76c4037edd095,0x00bbf24376415dd7)}, - {FIELD_LITERAL(0x00240465ff5a7197,0x00bb97e76caf27d0,0x004b4edbf8116d39,0x001d8586f708cbaa,0x000f8ee8ff8e4a50,0x00dde5a1945dd622,0x00e6fc1c0957e07c,0x0041c9cdabfd88a0)}, - {FIELD_LITERAL(0x005344b0bf5b548c,0x002957d0b705cc99,0x00f586a70390553d,0x0075b3229f583cc3,0x00a1aa78227490e4,0x001bf09cf7957717,0x00cf6bf344325f52,0x0065bd1c23ca3ecf)}, - }}, {{ - {FIELD_LITERAL(0x009bff3b3239363c,0x00e17368796ef7c0,0x00528b0fe0971f3a,0x0008014fc8d4a095,0x00d09f2e8a521ec4,0x006713ab5dde5987,0x0003015758e0dbb1,0x00215999f1ba212d)}, - {FIELD_LITERAL(0x002c88e93527da0e,0x0077c78f3456aad5,0x0071087a0a389d1c,0x00934dac1fb96dbd,0x008470e801162697,0x005bc2196cd4ad49,0x00e535601d5087c3,0x00769888700f497f)}, - {FIELD_LITERAL(0x00da7a4b557298ad,0x0019d2589ea5df76,0x00ef3e38be0c6497,0x00a9644e1312609a,0x004592f61b2558da,0x0082c1df510d7e46,0x0042809a535c0023,0x00215bcb5afd7757)}, - }}, {{ - {FIELD_LITERAL(0x002b9df55a1a4213,0x00dcfc3b464a26be,0x00c4f9e07a8144d5,0x00c8e0617a92b602,0x008e3c93accafae0,0x00bf1bcb95b2ca60,0x004ce2426a613bf3,0x00266cac58e40921)}, - {FIELD_LITERAL(0x008456d5db76e8f0,0x0032ca9cab2ce163,0x0059f2b8bf91abcf,0x0063c2a021712788,0x00f86155af22f72d,0x00db98b2a6c005a0,0x00ac6e416a693ac4,0x007a93572af53226)}, - {FIELD_LITERAL(0x0087767520f0de22,0x0091f64012279fb5,0x001050f1f0644999,0x004f097a2477ad3c,0x006b37913a9947bd,0x001a3d78645af241,0x0057832bbb3008a7,0x002c1d902b80dc20)}, - }}, {{ - {FIELD_LITERAL(0x001a6002bf178877,0x009bce168aa5af50,0x005fc318ff04a7f5,0x0052818f55c36461,0x008768f5d4b24afb,0x0037ffbae7b69c85,0x0018195a4b61edc0,0x001e12ea088434b2)}, - {FIELD_LITERAL(0x0047d3f804e7ab07,0x00a809ab5f905260,0x00b3ffc7cdaf306d,0x00746e8ec2d6e509,0x00d0dade8887a645,0x00acceeebde0dd37,0x009bc2579054686b,0x0023804f97f1c2bf)}, - {FIELD_LITERAL(0x0043e2e2e50b80d7,0x00143aafe4427e0f,0x005594aaecab855b,0x008b12ccaaecbc01,0x002deeb091082bc3,0x009cca4be2ae7514,0x00142b96e696d047,0x00ad2a2b1c05256a)}, - }}, {{ - {FIELD_LITERAL(0x003914f2f144b78b,0x007a95dd8bee6f68,0x00c7f4384d61c8e6,0x004e51eb60f1bdb2,0x00f64be7aa4621d8,0x006797bfec2f0ac0,0x007d17aab3c75900,0x001893e73cac8bc5)}, - {FIELD_LITERAL(0x00140360b768665b,0x00b68aca4967f977,0x0001089b66195ae4,0x00fe71122185e725,0x000bca2618d49637,0x00a54f0557d7e98a,0x00cdcd2f91d6f417,0x00ab8c13741fd793)}, - {FIELD_LITERAL(0x00725ee6b1e549e0,0x007124a0769777fa,0x000b68fdad07ae42,0x0085b909cd4952df,0x0092d2e3c81606f4,0x009f22f6cac099a0,0x00f59da57f2799a8,0x00f06c090122f777)}, - }}, {{ - {FIELD_LITERAL(0x00ce0bed0a3532bc,0x001a5048a22df16b,0x00e31db4cbad8bf1,0x00e89292120cf00e,0x007d1dd1a9b00034,0x00e2a9041ff8f680,0x006a4c837ae596e7,0x00713af1068070b3)}, - {FIELD_LITERAL(0x00c4fe64ce66d04b,0x00b095d52e09b3d7,0x00758bbecb1a3a8e,0x00f35cce8d0650c0,0x002b878aa5984473,0x0062e0a3b7544ddc,0x00b25b290ed116fe,0x007b0f6abe0bebf2)}, - {FIELD_LITERAL(0x0081d4e3addae0a8,0x003410c836c7ffcc,0x00c8129ad89e4314,0x000e3d5a23922dcd,0x00d91e46f29c31f3,0x006c728cde8c5947,0x002bc655ba2566c0,0x002ca94721533108)}, - }}, {{ - {FIELD_LITERAL(0x0051e4b3f764d8a9,0x0019792d46e904a0,0x00853bc13dbc8227,0x000840208179f12d,0x0068243474879235,0x0013856fbfe374d0,0x00bda12fe8676424,0x00bbb43635926eb2)}, - {FIELD_LITERAL(0x0012cdc880a93982,0x003c495b21cd1b58,0x00b7e5c93f22a26e,0x0044aa82dfb99458,0x009ba092cdffe9c0,0x00a14b3ab2083b73,0x000271c2f70e1c4b,0x00eea9cac0f66eb8)}, - {FIELD_LITERAL(0x001a1847c4ac5480,0x00b1b412935bb03a,0x00f74285983bf2b2,0x00624138b5b5d0f1,0x008820c0b03d38bf,0x00b94e50a18c1572,0x0060f6934841798f,0x00c52f5d66d6ebe2)}, - }}, {{ - {FIELD_LITERAL(0x00da23d59f9bcea6,0x00e0f27007a06a4b,0x00128b5b43a6758c,0x000cf50190fa8b56,0x00fc877aba2b2d72,0x00623bef52edf53f,0x00e6af6b819669e2,0x00e314dc34fcaa4f)}, - {FIELD_LITERAL(0x0066e5eddd164d1e,0x00418a7c6fe28238,0x0002e2f37e962c25,0x00f01f56b5975306,0x0048842fa503875c,0x0057b0e968078143,0x00ff683024f3d134,0x0082ae28fcad12e4)}, - {FIELD_LITERAL(0x0011ddfd21260e42,0x00d05b0319a76892,0x00183ea4368e9b8f,0x00b0815662affc96,0x00b466a5e7ce7c88,0x00db93b07506e6ee,0x0033885f82f62401,0x0086f9090ec9b419)}, - }}, {{ - {FIELD_LITERAL(0x00d95d1c5fcb435a,0x0016d1ed6b5086f9,0x00792aa0b7e54d71,0x0067b65715f1925d,0x00a219755ec6176b,0x00bc3f026b12c28f,0x00700c897ffeb93e,0x0089b83f6ec50b46)}, - {FIELD_LITERAL(0x003c97e6384da36e,0x00423d53eac81a09,0x00b70d68f3cdce35,0x00ee7959b354b92c,0x00f4e9718819c8ca,0x009349f12acbffe9,0x005aee7b62cb7da6,0x00d97764154ffc86)}, - {FIELD_LITERAL(0x00526324babb46dc,0x002ee99b38d7bf9e,0x007ea51794706ef4,0x00abeb04da6e3c39,0x006b457c1d281060,0x00fe243e9a66c793,0x00378de0fb6c6ee4,0x003e4194b9c3cb93)}, - }}, {{ - {FIELD_LITERAL(0x00fed3cd80ca2292,0x0015b043a73ca613,0x000a9fd7bf9be227,0x003b5e03de2db983,0x005af72d46904ef7,0x00c0f1b5c49faa99,0x00dc86fc3bd305e1,0x00c92f08c1cb1797)}, - {FIELD_LITERAL(0x0079680ce111ed3b,0x001a1ed82806122c,0x000c2e7466d15df3,0x002c407f6f7150fd,0x00c5e7c96b1b0ce3,0x009aa44626863ff9,0x00887b8b5b80be42,0x00b6023cec964825)}, - {FIELD_LITERAL(0x00e4a8e1048970c8,0x0062887b7830a302,0x00bcf1c8cd81402b,0x0056dbb81a68f5be,0x0014eced83f12452,0x00139e1a510150df,0x00bb81140a82d1a3,0x000febcc1aaf1aa7)}, - }}, {{ - {FIELD_LITERAL(0x00a7527958238159,0x0013ec9537a84cd6,0x001d7fee7d562525,0x00b9eefa6191d5e5,0x00dbc97db70bcb8a,0x00481affc7a4d395,0x006f73d3e70c31bb,0x00183f324ed96a61)}, - {FIELD_LITERAL(0x0039dd7ce7fc6860,0x00d64f6425653da1,0x003e037c7f57d0af,0x0063477a06e2bcf2,0x001727dbb7ac67e6,0x0049589f5efafe2e,0x00fc0fef2e813d54,0x008baa5d087fb50d)}, - {FIELD_LITERAL(0x0024fb59d9b457c7,0x00a7d4e060223e4c,0x00c118d1b555fd80,0x0082e216c732f22a,0x00cd2a2993089504,0x003638e836a3e13d,0x000d855ee89b4729,0x008ec5b7d4810c91)}, - }}, {{ - {FIELD_LITERAL(0x001bf51f7d65cdfd,0x00d14cdafa16a97d,0x002c38e60fcd10e7,0x00a27446e393efbd,0x000b5d8946a71fdd,0x0063df2cde128f2f,0x006c8679569b1888,0x0059ffc4925d732d)}, - {FIELD_LITERAL(0x00ece96f95f2b66f,0x00ece7952813a27b,0x0026fc36592e489e,0x007157d1a2de0f66,0x00759dc111d86ddf,0x0012881e5780bb0f,0x00c8ccc83ad29496,0x0012b9bd1929eb71)}, - {FIELD_LITERAL(0x000fa15a20da5df0,0x00349ddb1a46cd31,0x002c512ad1d8e726,0x00047611f669318d,0x009e68fba591e17e,0x004320dffa803906,0x00a640874951a3d3,0x00b6353478baa24f)}, - }}, {{ - {FIELD_LITERAL(0x009696510000d333,0x00ec2f788bc04826,0x000e4d02b1f67ba5,0x00659aa8dace08b6,0x00d7a38a3a3ae533,0x008856defa8c746b,0x004d7a4402d3da1a,0x00ea82e06229260f)}, - {FIELD_LITERAL(0x006a15bb20f75c0c,0x0079a144027a5d0c,0x00d19116ce0b4d70,0x0059b83bcb0b268e,0x005f58f63f16c127,0x0079958318ee2c37,0x00defbb063d07f82,0x00f1f0b931d2d446)}, - {FIELD_LITERAL(0x00cb5e4c3c35d422,0x008df885ca43577f,0x00fa50b16ca3e471,0x005a0e58e17488c8,0x00b2ceccd6d34d19,0x00f01d5d235e36e9,0x00db2e7e4be6ca44,0x00260ab77f35fccd)}, - }}, {{ - {FIELD_LITERAL(0x006f6fd9baac61d5,0x002a7710a020a895,0x009de0db7fc03d4d,0x00cdedcb1875f40b,0x00050caf9b6b1e22,0x005e3a6654456ab0,0x00775fdf8c4423d4,0x0028701ea5738b5d)}, - {FIELD_LITERAL(0x009ffd90abfeae96,0x00cba3c2b624a516,0x005ef08bcee46c91,0x00e6fde30afb6185,0x00f0b4db4f818ce4,0x006c54f45d2127f5,0x00040125035854c7,0x00372658a3287e13)}, - {FIELD_LITERAL(0x00d7070fb1beb2ab,0x0078fc845a93896b,0x006894a4b2f224a6,0x005bdd8192b9dbde,0x00b38839874b3a9e,0x00f93618b04b7a57,0x003e3ec75fd2c67e,0x00bf5e6bfc29494a)}, - }}, {{ - {FIELD_LITERAL(0x00f19224ebba2aa5,0x0074f89d358e694d,0x00eea486597135ad,0x0081579a4555c7e1,0x0010b9b872930a9d,0x00f002e87a30ecc0,0x009b9d66b6de56e2,0x00a3c4f45e8004eb)}, - {FIELD_LITERAL(0x0045e8dda9400888,0x002ff12e5fc05db7,0x00a7098d54afe69c,0x00cdbe846a500585,0x00879c1593ca1882,0x003f7a7fea76c8b0,0x002cd73dd0c8e0a1,0x00645d6ce96f51fe)}, - {FIELD_LITERAL(0x002b7e83e123d6d6,0x00398346f7419c80,0x0042922e55940163,0x005e7fc5601886a3,0x00e88f2cee1d3103,0x00e7fab135f2e377,0x00b059984dbf0ded,0x0009ce080faa5bb8)}, - }}, {{ - {FIELD_LITERAL(0x0085e78af7758979,0x00275a4ee1631a3a,0x00d26bc0ed78b683,0x004f8355ea21064f,0x00d618e1a32696e5,0x008d8d7b150e5680,0x00a74cd854b278d2,0x001dd62702203ea0)}, - {FIELD_LITERAL(0x00f89335c2a59286,0x00a0f5c905d55141,0x00b41fb836ee9382,0x00e235d51730ca43,0x00a5cb37b5c0a69a,0x009b966ffe136c45,0x00cb2ea10bf80ed1,0x00fb2b370b40dc35)}, - {FIELD_LITERAL(0x00d687d16d4ee8ba,0x0071520bdd069dff,0x00de85c60d32355d,0x0087d2e3565102f4,0x00cde391b8dfc9aa,0x00e18d69efdfefe5,0x004a9d0591954e91,0x00fa36dd8b50eee5)}, - }}, {{ - {FIELD_LITERAL(0x002e788749a865f7,0x006e4dc3116861ea,0x009f1428c37276e6,0x00e7d2e0fc1e1226,0x003aeebc6b6c45f6,0x0071a8073bf500c9,0x004b22ad986b530c,0x00f439e63c0d79d4)}, - {FIELD_LITERAL(0x006bc3d53011f470,0x00032d6e692b83e8,0x00059722f497cd0b,0x0009b4e6f0c497cc,0x0058a804b7cce6c0,0x002b71d3302bbd5d,0x00e2f82a36765fce,0x008dded99524c703)}, - {FIELD_LITERAL(0x004d058953747d64,0x00701940fe79aa6f,0x00a620ac71c760bf,0x009532b611158b75,0x00547ed7f466f300,0x003cb5ab53a8401a,0x00c7763168ce3120,0x007e48e33e4b9ab2)}, - }}, {{ - {FIELD_LITERAL(0x001b2fc57bf3c738,0x006a3f918993fb80,0x0026f7a14fdec288,0x0075a2cdccef08db,0x00d3ecbc9eecdbf1,0x0048c40f06e5bf7f,0x00d63e423009896b,0x000598bc99c056a8)}, - {FIELD_LITERAL(0x002f194eaafa46dc,0x008e38f57fe87613,0x00dc8e5ae25f4ab2,0x000a17809575e6bd,0x00d3ec7923ba366a,0x003a7e72e0ad75e3,0x0010024b88436e0a,0x00ed3c5444b64051)}, - {FIELD_LITERAL(0x00831fc1340af342,0x00c9645669466d35,0x007692b4cc5a080f,0x009fd4a47ac9259f,0x001eeddf7d45928b,0x003c0446fc45f28b,0x002c0713aa3e2507,0x0095706935f0f41e)}, - }}, {{ - {FIELD_LITERAL(0x00766ae4190ec6d8,0x0065768cabc71380,0x00b902598416cdc2,0x00380021ad38df52,0x008f0b89d6551134,0x004254d4cc62c5a5,0x000d79f4484b9b94,0x00b516732ae3c50e)}, - {FIELD_LITERAL(0x001fb73475c45509,0x00d2b2e5ea43345a,0x00cb3c3842077bd1,0x0029f90ad820946e,0x007c11b2380778aa,0x009e54ece62c1704,0x004bc60c41ca01c3,0x004525679a5a0b03)}, - {FIELD_LITERAL(0x00c64fbddbed87b3,0x0040601d11731faa,0x009c22475b6f9d67,0x0024b79dae875f15,0x00616fed3f02c3b0,0x0000cf39f6af2d3b,0x00c46bac0aa9a688,0x00ab23e2800da204)}, - }}, {{ - {FIELD_LITERAL(0x000b3a37617632b0,0x00597199fe1cfb6c,0x0042a7ccdfeafdd6,0x004cc9f15ebcea17,0x00f436e596a6b4a4,0x00168861142df0d8,0x000753edfec26af5,0x000c495d7e388116)}, - {FIELD_LITERAL(0x0017085f4a346148,0x00c7cf7a37f62272,0x001776e129bc5c30,0x009955134c9eef2a,0x001ba5bdf1df07be,0x00ec39497103a55c,0x006578354fda6cfb,0x005f02719d4f15ee)}, - {FIELD_LITERAL(0x0052b9d9b5d9655d,0x00d4ec7ba1b461c3,0x00f95df4974f280b,0x003d8e5ca11aeb51,0x00d4981eb5a70b26,0x000af9a4f6659f29,0x004598c846faeb43,0x0049d9a183a47670)}, - }}, {{ - {FIELD_LITERAL(0x000a72d23dcb3f1f,0x00a3737f84011727,0x00f870c0fbbf4a47,0x00a7aadd04b5c9ca,0x000c7715c67bd072,0x00015a136afcd74e,0x0080d5caea499634,0x0026b448ec7514b7)}, - {FIELD_LITERAL(0x00b60167d9e7d065,0x00e60ba0d07381e8,0x003a4f17b725c2d4,0x006c19fe176b64fa,0x003b57b31af86ccb,0x0021047c286180fd,0x00bdc8fb00c6dbb6,0x00fe4a9f4bab4f3f)}, - {FIELD_LITERAL(0x0088ffc3a16111f7,0x009155e4245d0bc8,0x00851d68220572d5,0x00557ace1e514d29,0x0031d7c339d91022,0x00101d0ae2eaceea,0x00246ab3f837b66a,0x00d5216d381ff530)}, - }}, {{ - {FIELD_LITERAL(0x0057e7ea35f36dae,0x00f47d7ad15de22e,0x00d757ea4b105115,0x008311457d579d7e,0x00b49b75b1edd4eb,0x0081c7ff742fd63a,0x00ddda3187433df6,0x00475727d55f9c66)}, - {FIELD_LITERAL(0x00a6295218dc136a,0x00563b3af0e9c012,0x00d3753b0145db1b,0x004550389c043dc1,0x00ea94ae27401bdf,0x002b0b949f2b7956,0x00c63f780ad8e23c,0x00e591c47d6bab15)}, - {FIELD_LITERAL(0x00416c582b058eb6,0x004107da5b2cc695,0x00b3cd2556aeec64,0x00c0b418267e57a1,0x001799293579bd2e,0x0046ed44590e4d07,0x001d7459b3630a1e,0x00c6afba8b6696aa)}, - }}, {{ - {FIELD_LITERAL(0x008d6009b26da3f8,0x00898e88ca06b1ca,0x00edb22b2ed7fe62,0x00fbc93516aabe80,0x008b4b470c42ce0d,0x00e0032ba7d0dcbb,0x00d76da3a956ecc8,0x007f20fe74e3852a)}, - {FIELD_LITERAL(0x002419222c607674,0x00a7f23af89188b3,0x00ad127284e73d1c,0x008bba582fae1c51,0x00fc6aa7ca9ecab1,0x003df5319eb6c2ba,0x002a05af8a8b199a,0x004bf8354558407c)}, - {FIELD_LITERAL(0x00ce7d4a30f0fcbf,0x00d02c272629f03d,0x0048c001f7400bc2,0x002c21368011958d,0x0098a550391e96b5,0x002d80b66390f379,0x001fa878760cc785,0x001adfce54b613d5)}, - }}, {{ - {FIELD_LITERAL(0x001ed4dc71fa2523,0x005d0bff19bf9b5c,0x00c3801cee065a64,0x001ed0b504323fbf,0x0003ab9fdcbbc593,0x00df82070178b8d2,0x00a2bcaa9c251f85,0x00c628a3674bd02e)}, - {FIELD_LITERAL(0x006b7a0674f9f8de,0x00a742414e5c7cff,0x0041cbf3c6e13221,0x00e3a64fd207af24,0x0087c05f15fbe8d1,0x004c50936d9e8a33,0x001306ec21042b6d,0x00a4f4137d1141c2)}, - {FIELD_LITERAL(0x0009e6fb921568b0,0x00b3c60120219118,0x002a6c3460dd503a,0x009db1ef11654b54,0x0063e4bf0be79601,0x00670d34bb2592b9,0x00dcee2f6c4130ce,0x00b2682e88e77f54)}, - }}, {{ - {FIELD_LITERAL(0x000d5b4b3da135ab,0x00838f3e5064d81d,0x00d44eb50f6d94ed,0x0008931ab502ac6d,0x00debe01ca3d3586,0x0025c206775f0641,0x005ad4b6ae912763,0x007e2c318ad8f247)}, - {FIELD_LITERAL(0x00ddbe0750dd1add,0x004b3c7b885844b8,0x00363e7ecf12f1ae,0x0062e953e6438f9d,0x0023cc73b076afe9,0x00b09fa083b4da32,0x00c7c3d2456c541d,0x005b591ec6b694d4)}, - {FIELD_LITERAL(0x0028656e19d62fcf,0x0052a4af03df148d,0x00122765ddd14e42,0x00f2252904f67157,0x004741965b636f3a,0x006441d296132cb9,0x005e2106f956a5b7,0x00247029592d335c)}, - }}, {{ - {FIELD_LITERAL(0x003fe038eb92f894,0x000e6da1b72e8e32,0x003a1411bfcbe0fa,0x00b55d473164a9e4,0x00b9a775ac2df48d,0x0002ddf350659e21,0x00a279a69eb19cb3,0x00f844eab25cba44)}, - {FIELD_LITERAL(0x00c41d1f9c1f1ac1,0x007b2df4e9f19146,0x00b469355fd5ba7a,0x00b5e1965afc852a,0x00388d5f1e2d8217,0x0022079e4c09ae93,0x0014268acd4ef518,0x00c1dd8d9640464c)}, - {FIELD_LITERAL(0x0038526adeed0c55,0x00dd68c607e3fe85,0x00f746ddd48a5d57,0x0042f2952b963b7c,0x001cbbd6876d5ec2,0x005e341470bca5c2,0x00871d41e085f413,0x00e53ab098f45732)}, - }}, {{ - {FIELD_LITERAL(0x004d51124797c831,0x008f5ae3750347ad,0x0070ced94c1a0c8e,0x00f6db2043898e64,0x000d00c9a5750cd0,0x000741ec59bad712,0x003c9d11aab37b7f,0x00a67ba169807714)}, - {FIELD_LITERAL(0x00adb2c1566e8b8f,0x0096c68a35771a9a,0x00869933356f334a,0x00ba9c93459f5962,0x009ec73fb6e8ca4b,0x003c3802c27202e1,0x0031f5b733e0c008,0x00f9058c19611fa9)}, - {FIELD_LITERAL(0x00238f01814a3421,0x00c325a44b6cce28,0x002136f97aeb0e73,0x000cac8268a4afe2,0x0022fd218da471b3,0x009dcd8dfff8def9,0x00cb9f8181d999bb,0x00143ae56edea349)}, - }}, {{ - {FIELD_LITERAL(0x0000623bf87622c5,0x00a1966fdd069496,0x00c315b7b812f9fc,0x00bdf5efcd128b97,0x001d464f532e3e16,0x003cd94f081bfd7e,0x00ed9dae12ce4009,0x002756f5736eee70)}, - {FIELD_LITERAL(0x00a5187e6ee7341b,0x00e6d52e82d83b6e,0x00df3c41323094a7,0x00b3324f444e9de9,0x00689eb21a35bfe5,0x00f16363becd548d,0x00e187cc98e7f60f,0x00127d9062f0ccab)}, - {FIELD_LITERAL(0x004ad71b31c29e40,0x00a5fcace12fae29,0x004425b5597280ed,0x00e7ef5d716c3346,0x0010b53ada410ac8,0x0092310226060c9b,0x0091c26128729c7e,0x0088b42900f8ec3b)}, - }}, {{ - {FIELD_LITERAL(0x00f1e26e9762d4a8,0x00d9d74082183414,0x00ffec9bd57a0282,0x000919e128fd497a,0x00ab7ae7d00fe5f8,0x0054dc442851ff68,0x00c9ebeb3b861687,0x00507f7cab8b698f)}, - {FIELD_LITERAL(0x00c13c5aae3ae341,0x009c6c9ed98373e7,0x00098f26864577a8,0x0015b886e9488b45,0x0037692c42aadba5,0x00b83170b8e7791c,0x001670952ece1b44,0x00fd932a39276da2)}, - {FIELD_LITERAL(0x0081a3259bef3398,0x005480fff416107b,0x00ce4f607d21be98,0x003ffc084b41df9b,0x0043d0bb100502d1,0x00ec35f575ba3261,0x00ca18f677300ef3,0x00e8bb0a827d8548)}, - }}, {{ - {FIELD_LITERAL(0x00df76b3328ada72,0x002e20621604a7c2,0x00f910638a105b09,0x00ef4724d96ef2cd,0x00377d83d6b8a2f7,0x00b4f48805ade324,0x001cd5da8b152018,0x0045af671a20ca7f)}, - {FIELD_LITERAL(0x009ae3b93a56c404,0x004a410b7a456699,0x00023a619355e6b2,0x009cdc7297387257,0x0055b94d4ae70d04,0x002cbd607f65b005,0x003208b489697166,0x00ea2aa058867370)}, - {FIELD_LITERAL(0x00f29d2598ee3f32,0x00b4ac5385d82adc,0x007633eaf04df19b,0x00aa2d3d77ceab01,0x004a2302fcbb778a,0x00927f225d5afa34,0x004a8e9d5047f237,0x008224ae9dbce530)}, - }}, {{ - {FIELD_LITERAL(0x001cf640859b02f8,0x00758d1d5d5ce427,0x00763c784ef4604c,0x005fa81aee205270,0x00ac537bfdfc44cb,0x004b919bd342d670,0x00238508d9bf4b7a,0x00154888795644f3)}, - {FIELD_LITERAL(0x00c845923c084294,0x00072419a201bc25,0x0045f408b5f8e669,0x00e9d6a186b74dfe,0x00e19108c68fa075,0x0017b91d874177b7,0x002f0ca2c7912c5a,0x009400aa385a90a2)}, - {FIELD_LITERAL(0x0071110b01482184,0x00cfed0044f2bef8,0x0034f2901cf4662e,0x003b4ae2a67f9834,0x00cca9b96fe94810,0x00522507ae77abd0,0x00bac7422721e73e,0x0066622b0f3a62b0)}, - }}, {{ - {FIELD_LITERAL(0x00f8ac5cf4705b6a,0x00867d82dcb457e3,0x007e13ab2ccc2ce9,0x009ee9a018d3930e,0x008370f8ecb42df8,0x002d9f019add263e,0x003302385b92d196,0x00a15654536e2c0c)}, - {FIELD_LITERAL(0x0026ef1614e160af,0x00c023f9edfc9c76,0x00cff090da5f57ba,0x0076db7a66643ae9,0x0019462f8c646999,0x008fec00b3854b22,0x00d55041692a0a1c,0x0065db894215ca00)}, - {FIELD_LITERAL(0x00a925036e0a451c,0x002a0390c36b6cc1,0x00f27020d90894f4,0x008d90d52cbd3d7f,0x00e1d0137392f3b8,0x00f017c158b51a8f,0x00cac313d3ed7dbc,0x00b99a81e3eb42d3)}, - }}, {{ - {FIELD_LITERAL(0x00b54850275fe626,0x0053a3fd1ec71140,0x00e3d2d7dbe096fa,0x00e4ac7b595cce4c,0x0077bad449c0a494,0x00b7c98814afd5b3,0x0057226f58486cf9,0x00b1557154f0cc57)}, - {FIELD_LITERAL(0x008cc9cd236315c0,0x0031d9c5b39fda54,0x00a5713ef37e1171,0x00293d5ae2886325,0x00c4aba3e05015e1,0x0003f35ef78e4fc6,0x0039d6bd3ac1527b,0x0019d7c3afb77106)}, - {FIELD_LITERAL(0x007b162931a985af,0x00ad40a2e0daa713,0x006df27c4009f118,0x00503e9f4e2e8bec,0x00751a77c82c182d,0x000298937769245b,0x00ffb1e8fabf9ee5,0x0008334706e09abe)}, - }}, {{ - {FIELD_LITERAL(0x00dbca4e98a7dcd9,0x00ee29cfc78bde99,0x00e4a3b6995f52e9,0x0045d70189ae8096,0x00fd2a8a3b9b0d1b,0x00af1793b107d8e1,0x00dbf92cbe4afa20,0x00da60f798e3681d)}, - {FIELD_LITERAL(0x004246bfcecc627a,0x004ba431246c03a4,0x00bd1d101872d497,0x003b73d3f185ee16,0x001feb2e2678c0e3,0x00ff13c5a89dec76,0x00ed06042e771d8f,0x00a4fd2a897a83dd)}, - {FIELD_LITERAL(0x009a4a3be50d6597,0x00de3165fc5a1096,0x004f3f56e345b0c7,0x00f7bf721d5ab8bc,0x004313e47b098c50,0x00e4c7d5c0e1adbb,0x002e3e3db365051e,0x00a480c2cd6a96fb)}, - }}, {{ - {FIELD_LITERAL(0x00417fa30a7119ed,0x00af257758419751,0x00d358a487b463d4,0x0089703cc720b00d,0x00ce56314ff7f271,0x0064db171ade62c1,0x00640b36d4a22fed,0x00424eb88696d23f)}, - {FIELD_LITERAL(0x004ede34af2813f3,0x00d4a8e11c9e8216,0x004796d5041de8a5,0x00c4c6b4d21cc987,0x00e8a433ee07fa1e,0x0055720b5abcc5a1,0x008873ea9c74b080,0x005b3fec1ab65d48)}, - {FIELD_LITERAL(0x0047e5277db70ec5,0x000a096c66db7d6b,0x00b4164cc1730159,0x004a9f783fe720fe,0x00a8177b94449dbc,0x0095a24ff49a599f,0x0069c1c578250cbc,0x00452019213debf4)}, - }}, {{ - {FIELD_LITERAL(0x0021ce99e09ebda3,0x00fcbd9f91875ad0,0x009bbf6b7b7a0b5f,0x00388886a69b1940,0x00926a56d0f81f12,0x00e12903c3358d46,0x005dfce4e8e1ce9d,0x0044cfa94e2f7e23)}, - {FIELD_LITERAL(0x001bd59c09e982ea,0x00f72daeb937b289,0x0018b76dca908e0e,0x00edb498512384ad,0x00ce0243b6cc9538,0x00f96ff690cb4e70,0x007c77bf9f673c8d,0x005bf704c088a528)}, - {FIELD_LITERAL(0x0093d4628dcb33be,0x0095263d51d42582,0x0049b3222458fe06,0x00e7fce73b653a7f,0x003ca2ebce60b369,0x00c5de239a32bea4,0x0063b8b3d71fb6bf,0x0039aeeb78a1a839)}, - }}, {{ - {FIELD_LITERAL(0x007dc52da400336c,0x001fded1e15b9457,0x00902e00f5568e3a,0x00219bef40456d2d,0x005684161fb3dbc9,0x004a4e9be49a76ea,0x006e685ae88b78ff,0x0021c42f13042d3c)}, - {FIELD_LITERAL(0x00fb22bb5fd3ce50,0x0017b48aada7ae54,0x00fd5c44ad19a536,0x000ccc4e4e55e45c,0x00fd637d45b4c3f5,0x0038914e023c37cf,0x00ac1881d6a8d898,0x00611ed8d3d943a8)}, - {FIELD_LITERAL(0x0056e2259d113d2b,0x00594819b284ec16,0x00c7bf794bb36696,0x00721ee75097cdc6,0x00f71be9047a2892,0x00df6ba142564edf,0x0069580b7a184e8d,0x00f056e38fca0fee)}, - }}, {{ - {FIELD_LITERAL(0x009df98566a18c6d,0x00cf3a200968f219,0x0044ba60da6d9086,0x00dbc9c0e344da03,0x000f9401c4466855,0x00d46a57c5b0a8d1,0x00875a635d7ac7c6,0x00ef4a933b7e0ae6)}, - {FIELD_LITERAL(0x005e8694077a1535,0x008bef75f71c8f1d,0x000a7c1316423511,0x00906e1d70604320,0x003fc46c1a2ffbd6,0x00d1d5022e68f360,0x002515fba37bbf46,0x00ca16234e023b44)}, - {FIELD_LITERAL(0x00787c99561f4690,0x00a857a8c1561f27,0x00a10df9223c09fe,0x00b98a9562e3b154,0x004330b8744c3ed2,0x00e06812807ec5c4,0x00e4cf6a7db9f1e3,0x00d95b089f132a34)}, - }}, {{ - {FIELD_LITERAL(0x002922b39ca33eec,0x0090d12a5f3ab194,0x00ab60c02fb5f8ed,0x00188d292abba1cf,0x00e10edec9698f6e,0x0069a4d9934133c8,0x0024aac40e6d3d06,0x001702c2177661b0)}, - {FIELD_LITERAL(0x00139078397030bd,0x000e3c447e859a00,0x0064a5b334c82393,0x00b8aabeb7358093,0x00020778bb9ae73b,0x0032ee94c7892a18,0x008215253cb41bda,0x005e2797593517ae)}, - {FIELD_LITERAL(0x0083765a5f855d4a,0x0051b6d1351b8ee2,0x00116de548b0f7bb,0x0087bd88703affa0,0x0095b2cc34d7fdd2,0x0084cd81b53f0bc8,0x008562fc995350ed,0x00a39abb193651e3)}, - }}, {{ - {FIELD_LITERAL(0x0019e23f0474b114,0x00eb94c2ad3b437e,0x006ddb34683b75ac,0x00391f9209b564c6,0x00083b3bb3bff7aa,0x00eedcd0f6dceefc,0x00b50817f794fe01,0x0036474deaaa75c9)}, - {FIELD_LITERAL(0x0091868594265aa2,0x00797accae98ca6d,0x0008d8c5f0f8a184,0x00d1f4f1c2b2fe6e,0x0036783dfb48a006,0x008c165120503527,0x0025fd780058ce9b,0x0068beb007be7d27)}, - {FIELD_LITERAL(0x00d0ff88aa7c90c2,0x00b2c60dacf53394,0x0094a7284d9666d6,0x00bed9022ce7a19d,0x00c51553f0cd7682,0x00c3fb870b124992,0x008d0bc539956c9b,0x00fc8cf258bb8885)}, - }}, {{ - {FIELD_LITERAL(0x003667bf998406f8,0x0000115c43a12975,0x001e662f3b20e8fd,0x0019ffa534cb24eb,0x00016be0dc8efb45,0x00ff76a8b26243f5,0x00ae20d241a541e3,0x0069bd6af13cd430)}, - {FIELD_LITERAL(0x0045fdc16487cda3,0x00b2d8e844cf2ed7,0x00612c50e88c1607,0x00a08aabc66c1672,0x006031fdcbb24d97,0x001b639525744b93,0x004409d62639ab17,0x00a1853d0347ab1d)}, - {FIELD_LITERAL(0x0075a1a56ebf5c21,0x00a3e72be9ac53ed,0x00efcde1629170c2,0x0004225fe91ef535,0x0088049fc73dfda7,0x004abc74857e1288,0x0024e2434657317c,0x00d98cb3d3e5543c)}, - }}, {{ - {FIELD_LITERAL(0x00b4b53eab6bdb19,0x009b22d8b43711d0,0x00d948b9d961785d,0x00cb167b6f279ead,0x00191de3a678e1c9,0x00d9dd9511095c2e,0x00f284324cd43067,0x00ed74fa535151dd)}, - {FIELD_LITERAL(0x007e32c049b5c477,0x009d2bfdbd9bcfd8,0x00636e93045938c6,0x007fde4af7687298,0x0046a5184fafa5d3,0x0079b1e7f13a359b,0x00875adf1fb927d6,0x00333e21c61bcad2)}, - {FIELD_LITERAL(0x00048014f73d8b8d,0x0075684aa0966388,0x0092be7df06dc47c,0x0097cebcd0f5568a,0x005a7004d9c4c6a9,0x00b0ecbb659924c7,0x00d90332dd492a7c,0x0057fc14df11493d)}, - }}, {{ - {FIELD_LITERAL(0x0008ed8ea0ad95be,0x0041d324b9709645,0x00e25412257a19b4,0x0058df9f3423d8d2,0x00a9ab20def71304,0x009ae0dbf8ac4a81,0x00c9565977e4392a,0x003c9269444baf55)}, - {FIELD_LITERAL(0x007df6cbb926830b,0x00d336058ae37865,0x007af47dac696423,0x0048d3011ec64ac8,0x006b87666e40049f,0x0036a2e0e51303d7,0x00ba319bd79dbc55,0x003e2737ecc94f53)}, - {FIELD_LITERAL(0x00d296ff726272d9,0x00f6d097928fcf57,0x00e0e616a55d7013,0x00deaf454ed9eac7,0x0073a56bedef4d92,0x006ccfdf6fc92e19,0x009d1ee1371a7218,0x00ee3c2ee4462d80)}, - }}, {{ - {FIELD_LITERAL(0x00437bce9bccdf9d,0x00e0c8e2f85dc0a3,0x00c91a7073995a19,0x00856ec9fe294559,0x009e4b33394b156e,0x00e245b0dc497e5c,0x006a54e687eeaeff,0x00f1cd1cd00fdb7c)}, - {FIELD_LITERAL(0x008132ae5c5d8cd1,0x00121d68324a1d9f,0x00d6be9dafcb8c76,0x00684d9070edf745,0x00519fbc96d7448e,0x00388182fdc1f27e,0x000235baed41f158,0x00bf6cf6f1a1796a)}, - {FIELD_LITERAL(0x002adc4b4d148219,0x003084ada0d3a90a,0x0046de8aab0f2e4e,0x00452d342a67b5fd,0x00d4b50f01d4de21,0x00db6d9fc0cefb79,0x008c184c86a462cd,0x00e17c83764d42da)}, - }}, {{ - {FIELD_LITERAL(0x007b2743b9a1e01a,0x007847ffd42688c4,0x006c7844d610a316,0x00f0cb8b250aa4b0,0x00a19060143b3ae6,0x0014eb10b77cfd80,0x000170905729dd06,0x00063b5b9cd72477)}, - {FIELD_LITERAL(0x00ce382dc7993d92,0x00021153e938b4c8,0x00096f7567f48f51,0x0058f81ddfe4b0d5,0x00cc379a56b355c7,0x002c760770d3e819,0x00ee22d1d26e5a40,0x00de6d93d5b082d7)}, - {FIELD_LITERAL(0x000a91a42c52e056,0x00185f6b77fce7ea,0x000803c51962f6b5,0x0022528582ba563d,0x0043f8040e9856d6,0x0085a29ec81fb860,0x005f9a611549f5ff,0x00c1f974ecbd4b06)}, - }}, {{ - {FIELD_LITERAL(0x005b64c6fd65ec97,0x00c1fdd7f877bc7f,0x000d9cc6c89f841c,0x005c97b7f1aff9ad,0x0075e3c61475d47e,0x001ecb1ba8153011,0x00fe7f1c8d71d40d,0x003fa9757a229832)}, - {FIELD_LITERAL(0x00ffc5c89d2b0cba,0x00d363d42e3e6fc3,0x0019a1a0118e2e8a,0x00f7baeff48882e1,0x001bd5af28c6b514,0x0055476ca2253cb2,0x00d8eb1977e2ddf3,0x00b173b1adb228a1)}, - {FIELD_LITERAL(0x00f2cb99dd0ad707,0x00e1e08b6859ddd8,0x000008f2d0650bcc,0x00d7ed392f8615c3,0x00976750a94da27f,0x003e83bb0ecb69ba,0x00df8e8d15c14ac6,0x00f9f7174295d9c2)}, - }}, {{ - {FIELD_LITERAL(0x00f11cc8e0e70bcb,0x00e5dc689974e7dd,0x0014e409f9ee5870,0x00826e6689acbd63,0x008a6f4e3d895d88,0x00b26a8da41fd4ad,0x000fb7723f83efd7,0x009c749db0a5f6c3)}, - {FIELD_LITERAL(0x002389319450f9ba,0x003677f31aa1250a,0x0092c3db642f38cb,0x00f8b64c0dfc9773,0x00cd49fe3505b795,0x0068105a4090a510,0x00df0ba2072a8bb6,0x00eb396143afd8be)}, - {FIELD_LITERAL(0x00a0d4ecfb24cdff,0x00ddaf8008ba6479,0x00f0b3e36d4b0f44,0x003734bd3af1f146,0x00b87e2efc75527e,0x00d230df55ddab50,0x002613257ae56c1d,0x00bc0946d135934d)}, - }}, {{ - {FIELD_LITERAL(0x00468711bd994651,0x0033108fa67561bf,0x0089d760192a54b4,0x00adc433de9f1871,0x000467d05f36e050,0x007847e0f0579f7f,0x00a2314ad320052d,0x00b3a93649f0b243)}, - {FIELD_LITERAL(0x0067f8f0c4fe26c9,0x0079c4a3cc8f67b9,0x0082b1e62f23550d,0x00f2d409caefd7f5,0x0080e67dcdb26e81,0x0087ae993ea1f98a,0x00aa108becf61d03,0x001acf11efb608a3)}, - {FIELD_LITERAL(0x008225febbab50d9,0x00f3b605e4dd2083,0x00a32b28189e23d2,0x00d507e5e5eb4c97,0x005a1a84e302821f,0x0006f54c1c5f08c7,0x00a347c8cb2843f0,0x0009f73e9544bfa5)}, - }}, {{ - {FIELD_LITERAL(0x006c59c9ae744185,0x009fc32f1b4282cd,0x004d6348ca59b1ac,0x00105376881be067,0x00af4096013147dc,0x004abfb5a5cb3124,0x000d2a7f8626c354,0x009c6ed568e07431)}, - {FIELD_LITERAL(0x00e828333c297f8b,0x009ef3cf8c3f7e1f,0x00ab45f8fff31cb9,0x00c8b4178cb0b013,0x00d0c50dd3260a3f,0x0097126ac257f5bc,0x0042376cc90c705a,0x001d96fdb4a1071e)}, - {FIELD_LITERAL(0x00542d44d89ee1a8,0x00306642e0442d98,0x0090853872b87338,0x002362cbf22dc044,0x002c222adff663b8,0x0067c924495fcb79,0x000e621d983c977c,0x00df77a9eccb66fb)}, - }}, {{ - {FIELD_LITERAL(0x002809e4bbf1814a,0x00b9e854f9fafb32,0x00d35e67c10f7a67,0x008f1bcb76e748cf,0x004224d9515687d2,0x005ba0b774e620c4,0x00b5e57db5d54119,0x00e15babe5683282)}, - {FIELD_LITERAL(0x00832d02369b482c,0x00cba52ff0d93450,0x003fa9c908d554db,0x008d1e357b54122f,0x00abd91c2dc950c6,0x007eff1df4c0ec69,0x003f6aeb13fb2d31,0x00002d6179fc5b2c)}, - {FIELD_LITERAL(0x0046c9eda81c9c89,0x00b60cb71c8f62fc,0x0022f5a683baa558,0x00f87319fccdf997,0x009ca09b51ce6a22,0x005b12baf4af7d77,0x008a46524a1e33e2,0x00035a77e988be0d)}, - }}, {{ - {FIELD_LITERAL(0x00a7efe46a7dbe2f,0x002f66fd55014fe7,0x006a428afa1ff026,0x0056caaa9604ab72,0x0033f3bcd7fac8ae,0x00ccb1aa01c86764,0x00158d1edf13bf40,0x009848ee76fcf3b4)}, - {FIELD_LITERAL(0x00a9e7730a819691,0x00d9cc73c4992b70,0x00e299bde067de5a,0x008c314eb705192a,0x00e7226f17e8a3cc,0x0029dfd956e65a47,0x0053a8e839073b12,0x006f942b2ab1597e)}, - {FIELD_LITERAL(0x001c3d780ecd5e39,0x0094f247fbdcc5fe,0x00d5c786fd527764,0x00b6f4da74f0db2a,0x0080f1f8badcd5fc,0x00f36a373ad2e23b,0x00f804f9f4343bf2,0x00d1af40ec623982)}, - }}, {{ - {FIELD_LITERAL(0x0082aeace5f1b144,0x00f68b3108cf4dd3,0x00634af01dde3020,0x000beab5df5c2355,0x00e8b790d1b49b0b,0x00e48d15854e36f4,0x0040ab2d95f3db9f,0x002711c4ed9e899a)}, - {FIELD_LITERAL(0x0039343746531ebe,0x00c8509d835d429d,0x00e79eceff6b0018,0x004abfd31e8efce5,0x007bbfaaa1e20210,0x00e3be89c193e179,0x001c420f4c31d585,0x00f414a315bef5ae)}, - {FIELD_LITERAL(0x007c296a24990df8,0x00d5d07525a75588,0x00dd8e113e94b7e7,0x007bbc58febe0cc8,0x0029f51af9bfcad3,0x007e9311ec7ab6f3,0x009a884de1676343,0x0050d5f2dce84be9)}, - }}, {{ - {FIELD_LITERAL(0x005fa020cca2450a,0x00491c29db6416d8,0x0037cefe3f9f9a85,0x003d405230647066,0x0049e835f0fdbe89,0x00feb78ac1a0815c,0x00828e4b32dc9724,0x00db84f2dc8d6fd4)}, - {FIELD_LITERAL(0x0098cddc8b39549a,0x006da37e3b05d22c,0x00ce633cfd4eb3cb,0x00fda288ef526acd,0x0025338878c5d30a,0x00f34438c4e5a1b4,0x00584efea7c310f1,0x0041a551f1b660ad)}, - {FIELD_LITERAL(0x00d7f7a8fbd6437a,0x0062872413bf3753,0x00ad4bbcb43c584b,0x007fe49be601d7e3,0x0077c659789babf4,0x00eb45fcb06a741b,0x005ce244913f9708,0x0088426401736326)}, - }}, {{ - {FIELD_LITERAL(0x007bf562ca768d7c,0x006c1f3a174e387c,0x00f024b447fee939,0x007e7af75f01143f,0x003adb70b4eed89d,0x00e43544021ad79a,0x0091f7f7042011f6,0x0093c1a1ee3a0ddc)}, - {FIELD_LITERAL(0x00a0b68ec1eb72d2,0x002c03235c0d45a0,0x00553627323fe8c5,0x006186e94b17af94,0x00a9906196e29f14,0x0025b3aee6567733,0x007e0dd840080517,0x0018eb5801a4ba93)}, - {FIELD_LITERAL(0x00d7fe7017bf6a40,0x006e3f0624be0c42,0x00ffbba205358245,0x00f9fc2cf8194239,0x008d93b37bf15b4e,0x006ddf2e38be8e95,0x002b6e79bf5fcff9,0x00ab355da425e2de)}, - }}, {{ - {FIELD_LITERAL(0x00938f97e20be973,0x0099141a36aaf306,0x0057b0ca29e545a1,0x0085db571f9fbc13,0x008b333c554b4693,0x0043ab6ef3e241cb,0x0054fb20aa1e5c70,0x00be0ff852760adf)}, - {FIELD_LITERAL(0x003973d8938971d6,0x002aca26fa80c1f5,0x00108af1faa6b513,0x00daae275d7924e6,0x0053634ced721308,0x00d2355fe0bbd443,0x00357612b2d22095,0x00f9bb9dd4136cf3)}, - {FIELD_LITERAL(0x002bff12cf5e03a5,0x001bdb1fa8a19cf8,0x00c91c6793f84d39,0x00f869f1b2eba9af,0x0059bc547dc3236b,0x00d91611d6d38689,0x00e062daaa2c0214,0x00ed3c047cc2bc82)}, - }}, {{ - {FIELD_LITERAL(0x000050d70c32b31a,0x001939d576d437b3,0x00d709e598bf9fe6,0x00a885b34bd2ee9e,0x00dd4b5c08ab1a50,0x0091bebd50b55639,0x00cf79ff64acdbc6,0x006067a39d826336)}, - {FIELD_LITERAL(0x0062dd0fb31be374,0x00fcc96b84c8e727,0x003f64f1375e6ae3,0x0057d9b6dd1af004,0x00d6a167b1103c7b,0x00dd28f3180fb537,0x004ff27ad7167128,0x008934c33461f2ac)}, - {FIELD_LITERAL(0x0065b472b7900043,0x00ba7efd2ff1064b,0x000b67d6c4c3020f,0x0012d28469f4e46d,0x0031c32939703ec7,0x00b49f0bce133066,0x00f7e10416181d47,0x005c90f51867eecc)}, - }}, {{ - {FIELD_LITERAL(0x0051207abd179101,0x00fc2a5c20d9c5da,0x00fb9d5f2701b6df,0x002dd040fdea82b8,0x00f163b0738442ff,0x00d9736bd68855b8,0x00e0d8e93005e61c,0x00df5a40b3988570)}, - {FIELD_LITERAL(0x0006918f5dfce6dc,0x00d4bf1c793c57fb,0x0069a3f649435364,0x00e89a50e5b0cd6e,0x00b9f6a237e973af,0x006d4ed8b104e41d,0x00498946a3924cd2,0x00c136ec5ac9d4f7)}, - {FIELD_LITERAL(0x0011a9c290ac5336,0x002b9a2d4a6a6533,0x009a8a68c445d937,0x00361b27b07e5e5c,0x003c043b1755b974,0x00b7eb66cf1155ee,0x0077af5909eefff2,0x0098f609877cc806)}, - }}, {{ - {FIELD_LITERAL(0x00ab13af436bf8f4,0x000bcf0a0dac8574,0x00d50c864f705045,0x00c40e611debc842,0x0085010489bd5caa,0x007c5050acec026f,0x00f67d943c8da6d1,0x00de1da0278074c6)}, - {FIELD_LITERAL(0x00b373076597455f,0x00e83f1af53ac0f5,0x0041f63c01dc6840,0x0097dea19b0c6f4b,0x007f9d63b4c1572c,0x00e692d492d0f5f0,0x00cbcb392e83b4ad,0x0069c0f39ed9b1a8)}, - {FIELD_LITERAL(0x00861030012707c9,0x009fbbdc7fd4aafb,0x008f591d6b554822,0x00df08a41ea18ade,0x009d7d83e642abea,0x0098c71bda3b78ff,0x0022c89e7021f005,0x0044d29a3fe1e3c4)}, - }}, {{ - {FIELD_LITERAL(0x00e748cd7b5c52f2,0x00ea9df883f89cc3,0x0018970df156b6c7,0x00c5a46c2a33a847,0x00cbde395e32aa09,0x0072474ebb423140,0x00fb00053086a23d,0x001dafcfe22d4e1f)}, - {FIELD_LITERAL(0x00c903ee6d825540,0x00add6c4cf98473e,0x007636efed4227f1,0x00905124ae55e772,0x00e6b38fab12ed53,0x0045e132b863fe55,0x003974662edb366a,0x00b1787052be8208)}, - {FIELD_LITERAL(0x00a614b00d775c7c,0x00d7c78941cc7754,0x00422dd68b5dabc4,0x00a6110f0167d28b,0x00685a309c252886,0x00b439ffd5143660,0x003656e29ee7396f,0x00c7c9b9ed5ad854)}, - }}, {{ - {FIELD_LITERAL(0x0040f7e7c5b37bf2,0x0064e4dc81181bba,0x00a8767ae2a366b6,0x001496b4f90546f2,0x002a28493f860441,0x0021f59513049a3a,0x00852d369a8b7ee3,0x00dd2e7d8b7d30a9)}, - {FIELD_LITERAL(0x00006e34a35d9fbc,0x00eee4e48b2f019a,0x006b344743003a5f,0x00541d514f04a7e3,0x00e81f9ee7647455,0x005e2b916c438f81,0x00116f8137b7eff0,0x009bd3decc7039d1)}, - {FIELD_LITERAL(0x0005d226f434110d,0x00af8288b8ef21d5,0x004a7a52ef181c8c,0x00be0b781b4b06de,0x00e6e3627ded07e1,0x00e43aa342272b8b,0x00e86ab424577d84,0x00fb292c566e35bb)}, - }}, {{ - {FIELD_LITERAL(0x00334f5303ea1222,0x00dfb3dbeb0a5d3e,0x002940d9592335c1,0x00706a7a63e8938a,0x005a533558bc4caf,0x00558e33192022a9,0x00970d9faf74c133,0x002979fcb63493ca)}, - {FIELD_LITERAL(0x00e38abece3c82ab,0x005a51f18a2c7a86,0x009dafa2e86d592e,0x00495a62eb688678,0x00b79df74c0eb212,0x0023e8cc78b75982,0x005998cb91075e13,0x00735aa9ba61bc76)}, - {FIELD_LITERAL(0x00d9f7a82ddbe628,0x00a1fc782889ae0f,0x0071ffda12d14b66,0x0037cf4eca7fb3d5,0x00c80bc242c58808,0x0075bf8c2d08c863,0x008d41f31afc52a7,0x00197962ecf38741)}, - }}, {{ - {FIELD_LITERAL(0x006e9f475cccf2ee,0x00454b9cd506430c,0x00224a4fb79ee479,0x0062e3347ef0b5e2,0x0034fd2a3512232a,0x00b8b3cb0f457046,0x00eb20165daa38ec,0x00128eebc2d9c0f7)}, - {FIELD_LITERAL(0x00bfc5fa1e4ea21f,0x00c21d7b6bb892e6,0x00cf043f3acf0291,0x00c13f2f849b3c90,0x00d1a97ebef10891,0x0061e130a445e7fe,0x0019513fdedbf22b,0x001d60c813bff841)}, - {FIELD_LITERAL(0x0019561c7fcf0213,0x00e3dca6843ebd77,0x0068ea95b9ca920e,0x009bdfb70f253595,0x00c68f59186aa02a,0x005aee1cca1c3039,0x00ab79a8a937a1ce,0x00b9a0e549959e6f)}, - }}, {{ - {FIELD_LITERAL(0x00c79e0b6d97dfbd,0x00917c71fd2bc6e8,0x00db7529ccfb63d8,0x00be5be957f17866,0x00a9e11fdc2cdac1,0x007b91a8e1f44443,0x00a3065e4057d80f,0x004825f5b8d5f6d4)}, - {FIELD_LITERAL(0x003e4964fa8a8fc8,0x00f6a1cdbcf41689,0x00943cb18fe7fda7,0x00606dafbf34440a,0x005d37a86399c789,0x00e79a2a69417403,0x00fe34f7e68b8866,0x0011f448ed2df10e)}, - {FIELD_LITERAL(0x00f1f57efcc1fcc4,0x00513679117de154,0x002e5b5b7c86d8c3,0x009f6486561f9cfb,0x00169e74b0170cf7,0x00900205af4af696,0x006acfddb77853f3,0x00df184c90f31068)}, - }}, {{ - {FIELD_LITERAL(0x00b37396c3320791,0x00fc7b67175c5783,0x00c36d2cd73ecc38,0x0080ebcc0b328fc5,0x0043a5b22b35d35d,0x00466c9f1713c9da,0x0026ad346dcaa8da,0x007c684e701183a6)}, - {FIELD_LITERAL(0x00fd579ffb691713,0x00b76af4f81c412d,0x00f239de96110f82,0x00e965fb437f0306,0x00ca7e9436900921,0x00e487f1325fa24a,0x00633907de476380,0x00721c62ac5b8ea0)}, - {FIELD_LITERAL(0x00c0d54e542eb4f9,0x004ed657171c8dcf,0x00b743a4f7c2a39b,0x00fd9f93ed6cc567,0x00307fae3113e58b,0x0058aa577c93c319,0x00d254556f35b346,0x00491aada2203f0d)}, - }}, {{ - {FIELD_LITERAL(0x00dff3103786ff34,0x000144553b1f20c3,0x0095613baeb930e4,0x00098058275ea5d4,0x007cd1402b046756,0x0074d74e4d58aee3,0x005f93fc343ff69b,0x00873df17296b3b0)}, - {FIELD_LITERAL(0x00c4a1fb48635413,0x00b5dd54423ad59f,0x009ff5d53fd24a88,0x003c98d267fc06a7,0x002db7cb20013641,0x00bd1d6716e191f2,0x006dbc8b29094241,0x0044bbf233dafa2c)}, - {FIELD_LITERAL(0x0055838d41f531e6,0x00bf6a2dd03c81b2,0x005827a061c4839e,0x0000de2cbb36aac3,0x002efa29d9717478,0x00f9e928cc8a77ba,0x00c134b458def9ef,0x00958a182223fc48)}, - }}, {{ - {FIELD_LITERAL(0x000a9ee23c06881f,0x002c727d3d871945,0x00f47d971512d24a,0x00671e816f9ef31a,0x00883af2cfaad673,0x00601f98583d6c9a,0x00b435f5adc79655,0x00ad87b71c04bff2)}, - {FIELD_LITERAL(0x007860d99db787cf,0x00fda8983018f4a8,0x008c8866bac4743c,0x00ef471f84c82a3f,0x00abea5976d3b8e7,0x00714882896cd015,0x00b49fae584ddac5,0x008e33a1a0b69c81)}, - {FIELD_LITERAL(0x007b6ee2c9e8a9ec,0x002455dbbd89d622,0x006490cf4eaab038,0x00d925f6c3081561,0x00153b3047de7382,0x003b421f8bdceb6f,0x00761a4a5049da78,0x00980348c5202433)}, - }}, {{ - {FIELD_LITERAL(0x007f8a43da97dd5c,0x00058539c800fc7b,0x0040f3cf5a28414a,0x00d68dd0d95283d6,0x004adce9da90146e,0x00befa41c7d4f908,0x007603bc2e3c3060,0x00bdf360ab3545db)}, - {FIELD_LITERAL(0x00eebfd4e2312cc3,0x00474b2564e4fc8c,0x003303ef14b1da9b,0x003c93e0e66beb1d,0x0013619b0566925a,0x008817c24d901bf3,0x00b62bd8898d218b,0x0075a7716f1e88a2)}, - {FIELD_LITERAL(0x0009218da1e6890f,0x0026907f5fd02575,0x004dabed5f19d605,0x003abf181870249d,0x00b52fd048cc92c4,0x00b6dd51e415a5c5,0x00d9eb82bd2b4014,0x002c865a43b46b43)}, - }}, {{ - {FIELD_LITERAL(0x0070047189452f4c,0x00f7ad12e1ce78d5,0x00af1ba51ec44a8b,0x005f39f63e667cd6,0x00058eac4648425e,0x00d7fdab42bea03b,0x0028576a5688de15,0x00af973209e77c10)}, - {FIELD_LITERAL(0x00c338b915d8fef0,0x00a893292045c39a,0x0028ab4f2eba6887,0x0060743cb519fd61,0x0006213964093ac0,0x007c0b7a43f6266d,0x008e3557c4fa5bda,0x002da976de7b8d9d)}, - {FIELD_LITERAL(0x0048729f8a8b6dcd,0x00fe23b85cc4d323,0x00e7384d16e4db0e,0x004a423970678942,0x00ec0b763345d4ba,0x00c477b9f99ed721,0x00c29dad3777b230,0x001c517b466f7df6)}, - }}, {{ - {FIELD_LITERAL(0x006366c380f7b574,0x001c7d1f09ff0438,0x003e20a7301f5b22,0x00d3efb1916d28f6,0x0049f4f81060ce83,0x00c69d91ea43ced1,0x002b6f3e5cd269ed,0x005b0fb22ce9ec65)}, - {FIELD_LITERAL(0x00aa2261022d883f,0x00ebcca4548010ac,0x002528512e28a437,0x0070ca7676b66082,0x0084bda170f7c6d3,0x00581b4747c9b8bb,0x005c96a01061c7e2,0x00fb7c4a362b5273)}, - {FIELD_LITERAL(0x00c30020eb512d02,0x0060f288283a4d26,0x00b7ed13becde260,0x0075ebb74220f6e9,0x00701079fcfe8a1f,0x001c28fcdff58938,0x002e4544b8f4df6b,0x0060c5bc4f1a7d73)}, - }}, {{ - {FIELD_LITERAL(0x00ae307cf069f701,0x005859f222dd618b,0x00212d6c46ec0b0d,0x00a0fe4642afb62d,0x00420d8e4a0a8903,0x00a80ff639bdf7b0,0x0019bee1490b5d8e,0x007439e4b9c27a86)}, - {FIELD_LITERAL(0x00a94700032a093f,0x0076e96c225216e7,0x00a63a4316e45f91,0x007d8bbb4645d3b2,0x00340a6ff22793eb,0x006f935d4572aeb7,0x00b1fb69f00afa28,0x009e8f3423161ed3)}, - {FIELD_LITERAL(0x009ef49c6b5ced17,0x00a555e6269e9f0a,0x007e6f1d79ec73b5,0x009ac78695a32ac4,0x0001d77fbbcd5682,0x008cea1fee0aaeed,0x00f42bea82a53462,0x002e46ab96cafcc9)}, - }}, {{ - {FIELD_LITERAL(0x0051cfcc5885377a,0x00dce566cb1803ca,0x00430c7643f2c7d4,0x00dce1a1337bdcc0,0x0010d5bd7283c128,0x003b1b547f9b46fe,0x000f245e37e770ab,0x007b72511f022b37)}, - {FIELD_LITERAL(0x0060db815bc4786c,0x006fab25beedc434,0x00c610d06084797c,0x000c48f08537bec0,0x0031aba51c5b93da,0x007968fa6e01f347,0x0030070da52840c6,0x00c043c225a4837f)}, - {FIELD_LITERAL(0x001bcfd00649ee93,0x006dceb47e2a0fd5,0x00f2cebda0cf8fd0,0x00b6b9d9d1fbdec3,0x00815262e6490611,0x00ef7f5ce3176760,0x00e49cd0c998d58b,0x005fc6cc269ba57c)}, - }}, {{ - {FIELD_LITERAL(0x008940211aa0d633,0x00addae28136571d,0x00d68fdbba20d673,0x003bc6129bc9e21a,0x000346cf184ebe9a,0x0068774d741ebc7f,0x0019d5e9e6966557,0x0003cbd7f981b651)}, - {FIELD_LITERAL(0x004a2902926f8d3f,0x00ad79b42637ab75,0x0088f60b90f2d4e8,0x0030f54ef0e398c4,0x00021dc9bf99681e,0x007ebf66fde74ee3,0x004ade654386e9a4,0x00e7485066be4c27)}, - {FIELD_LITERAL(0x00445f1263983be0,0x004cf371dda45e6a,0x00744a89d5a310e7,0x001f20ce4f904833,0x00e746edebe66e29,0x000912ab1f6c153d,0x00f61d77d9b2444c,0x0001499cd6647610)}, + {FIELD_LITERAL(0x00cc3b062366f4ccULL, 0x003d6e34e314aa3cULL, + 0x00d51c0a7521774dULL, 0x0094e060eec6ab8bULL, + 0x00d21291b4d80082ULL, 0x00befed12b55ef1eULL, + 0x00c3dd2df5c94518ULL, 0x00e0a7b112b8d4e6ULL)}, + {FIELD_LITERAL(0x0019eb5608d8723aULL, 0x00d1bab52fb3aedbULL, + 0x00270a7311ebc90cULL, 0x0037c12b91be7f13ULL, + 0x005be16cd8b5c704ULL, 0x003e181acda888e1ULL, + 0x00bc1f00fc3fc6d0ULL, 0x00d3839bfa319e20ULL)}, + {FIELD_LITERAL(0x003caeb88611909fULL, 0x00ea8b378c4df3d4ULL, + 0x00b3295b95a5a19aULL, 0x00a65f97514bdfb5ULL, + 0x00b39efba743cab1ULL, 0x0016ba98b862fd2dULL, + 0x0001508812ee71d7ULL, 0x000a75740eea114aULL)}, + }}, {{ + {FIELD_LITERAL(0x00ebcf0eb649f823ULL, 0x00166d332e98ea03ULL, + 0x0059ddf64f5cd5f6ULL, 0x0047763123d9471bULL, + 0x00a64065c53ef62fULL, 0x00978e44c480153dULL, + 0x000b5b2a0265f194ULL, 0x0046a24b9f32965aULL)}, + {FIELD_LITERAL(0x00b9eef787034df0ULL, 0x0020bc24de3390cdULL, + 0x000022160bae99bbULL, 0x00ae66e886e97946ULL, + 0x0048d4bbe02cbb8bULL, 0x0072ba97b34e38d4ULL, + 0x00eae7ec8f03e85aULL, 0x005ba92ecf808b2cULL)}, + {FIELD_LITERAL(0x00c9cfbbe74258fdULL, 0x00843a979ea9eaa7ULL, + 0x000cbb4371cfbe90ULL, 0x0059bac8f7f0a628ULL, + 0x004b3dff882ff530ULL, 0x0011869df4d90733ULL, + 0x00595aa71f4abfc2ULL, 0x0070e2d38990c2e6ULL)}, + }}, {{ + {FIELD_LITERAL(0x00de2010c0a01733ULL, 0x00c739a612e24297ULL, + 0x00a7212643141d7cULL, 0x00f88444f6b67c11ULL, + 0x00484b7b16ec28f2ULL, 0x009c1b8856af9c68ULL, + 0x00ff4669591fe9d6ULL, 0x0054974be08a32c8ULL)}, + {FIELD_LITERAL(0x0010de3fd682ceedULL, 0x008c07642d83ca4eULL, + 0x0013bb064e00a1ccULL, 0x009411ae27870e11ULL, + 0x00ea8e5b4d531223ULL, 0x0032fe7d2aaece2eULL, + 0x00d989e243e7bb41ULL, 0x000fe79a508e9b8bULL)}, + {FIELD_LITERAL(0x005e0426b9bfc5b1ULL, 0x0041a5b1d29ee4faULL, + 0x0015b0def7774391ULL, 0x00bc164f1f51af01ULL, + 0x00d543b0942797b9ULL, 0x003c129b6398099cULL, + 0x002b114c6e5adf18ULL, 0x00b4e630e4018a7bULL)}, + }}, {{ + {FIELD_LITERAL(0x00d490afc95f8420ULL, 0x00b096bf50c1d9b9ULL, + 0x00799fd707679866ULL, 0x007c74d9334afbeaULL, + 0x00efaa8be80ff4edULL, 0x0075c4943bb81694ULL, + 0x00c21c2fca161f36ULL, 0x00e77035d492bfeeULL)}, + {FIELD_LITERAL(0x006658a190dd6661ULL, 0x00e0e9bab38609a6ULL, + 0x0028895c802237edULL, 0x006a0229c494f587ULL, + 0x002dcde96c9916b7ULL, 0x00d158822de16218ULL, + 0x00173b917a06856fULL, 0x00ca78a79ae07326ULL)}, + {FIELD_LITERAL(0x00e35bfc79caced4ULL, 0x0087238a3e1fe3bbULL, + 0x00bcbf0ff4ceff5bULL, 0x00a19c1c94099b91ULL, + 0x0071e102b49db976ULL, 0x0059e3d004eada1eULL, + 0x008da78afa58a47eULL, 0x00579c8ebf269187ULL)}, + }}, {{ + {FIELD_LITERAL(0x00a16c2905eee75fULL, 0x009d4bcaea2c7e1dULL, + 0x00d3bd79bfad19dfULL, 0x0050da745193342cULL, + 0x006abdb8f6b29ab1ULL, 0x00a24fe0a4fef7efULL, + 0x0063730da1057dfbULL, 0x00a08c312c8eb108ULL)}, + {FIELD_LITERAL(0x00b583be005375beULL, 0x00a40c8f8a4e3df4ULL, + 0x003fac4a8f5bdbf7ULL, 0x00d4481d872cd718ULL, + 0x004dc8749cdbaefeULL, 0x00cce740d5e5c975ULL, + 0x000b1c1f4241fd21ULL, 0x00a76de1b4e1cd07ULL)}, + {FIELD_LITERAL(0x007a076500d30b62ULL, 0x000a6e117b7f090fULL, + 0x00c8712ae7eebd9aULL, 0x000fbd6c1d5f6ff7ULL, + 0x003a7977246ebf11ULL, 0x00166ed969c6600eULL, + 0x00aa42e469c98becULL, 0x00dc58f307cf0666ULL)}, + }}, {{ + {FIELD_LITERAL(0x004b491f65a9a28bULL, 0x006a10309e8a55b7ULL, + 0x00b67210185187efULL, 0x00cf6497b12d9b8fULL, + 0x0085778c56e2b1baULL, 0x0015b4c07a814d85ULL, + 0x00686479e62da561ULL, 0x008de5d88f114916ULL)}, + {FIELD_LITERAL(0x00e37c88d6bba7b1ULL, 0x003e4577e1b8d433ULL, + 0x0050d8ea5f510ec0ULL, 0x0042fc9f2da9ef59ULL, + 0x003bd074c1141420ULL, 0x00561b8b7b68774eULL, + 0x00232e5e5d1013a3ULL, 0x006b7f2cb3d7e73fULL)}, + {FIELD_LITERAL(0x004bdd0f0b41e6a0ULL, 0x001773057c405d24ULL, + 0x006029f99915bd97ULL, 0x006a5ba70a17fe2fULL, + 0x0046111977df7e08ULL, 0x004d8124c89fb6b7ULL, + 0x00580983b2bb2724ULL, 0x00207bf330d6f3feULL)}, + }}, {{ + {FIELD_LITERAL(0x007efdc93972a48bULL, 0x002f5e50e78d5feeULL, + 0x0080dc11d61c7fe5ULL, 0x0065aa598707245bULL, + 0x009abba2300641beULL, 0x000c68787656543aULL, + 0x00ffe0fef2dc0a17ULL, 0x00007ffbd6cb4f3aULL)}, + {FIELD_LITERAL(0x0036012f2b836efcULL, 0x00458c126d6b5fbcULL, + 0x00a34436d719ad1eULL, 0x0097be6167117deaULL, + 0x0009c219c879cff3ULL, 0x0065564493e60755ULL, + 0x00993ac94a8cdec0ULL, 0x002d4885a4d0dbafULL)}, + {FIELD_LITERAL(0x00598b60b4c068baULL, 0x00c547a0be7f1afdULL, + 0x009582164acf12afULL, 0x00af4acac4fbbe40ULL, + 0x005f6ca7c539121aULL, 0x003b6e752ebf9d66ULL, + 0x00f08a30d5cac5d4ULL, 0x00e399bb5f97c5a9ULL)}, + }}, {{ + {FIELD_LITERAL(0x007445a0409c0a66ULL, 0x00a65c369f3829c0ULL, + 0x0031d248a4f74826ULL, 0x006817f34defbe8eULL, + 0x00649741d95ebf2eULL, 0x00d46466ab16b397ULL, + 0x00fdc35703bee414ULL, 0x00343b43334525f8ULL)}, + {FIELD_LITERAL(0x001796bea93f6401ULL, 0x00090c5a42e85269ULL, + 0x00672412ba1252edULL, 0x001201d47b6de7deULL, + 0x006877bccfe66497ULL, 0x00b554fd97a4c161ULL, + 0x009753f42dbac3cfULL, 0x00e983e3e378270aULL)}, + {FIELD_LITERAL(0x00ac3eff18849872ULL, 0x00f0eea3bff05690ULL, + 0x00a6d72c21dd505dULL, 0x001b832642424169ULL, + 0x00a6813017b540e5ULL, 0x00a744bd71b385cdULL, + 0x0022a7d089130a7bULL, 0x004edeec9a133486ULL)}, + }}, {{ + {FIELD_LITERAL(0x00b2d6729196e8a9ULL, 0x0088a9bb2031cef4ULL, + 0x00579e7787dc1567ULL, 0x0030f49feb059190ULL, + 0x00a0b1d69c7f7d8fULL, 0x0040bdcc6d9d806fULL, + 0x00d76c4037edd095ULL, 0x00bbf24376415dd7ULL)}, + {FIELD_LITERAL(0x00240465ff5a7197ULL, 0x00bb97e76caf27d0ULL, + 0x004b4edbf8116d39ULL, 0x001d8586f708cbaaULL, + 0x000f8ee8ff8e4a50ULL, 0x00dde5a1945dd622ULL, + 0x00e6fc1c0957e07cULL, 0x0041c9cdabfd88a0ULL)}, + {FIELD_LITERAL(0x005344b0bf5b548cULL, 0x002957d0b705cc99ULL, + 0x00f586a70390553dULL, 0x0075b3229f583cc3ULL, + 0x00a1aa78227490e4ULL, 0x001bf09cf7957717ULL, + 0x00cf6bf344325f52ULL, 0x0065bd1c23ca3ecfULL)}, + }}, {{ + {FIELD_LITERAL(0x009bff3b3239363cULL, 0x00e17368796ef7c0ULL, + 0x00528b0fe0971f3aULL, 0x0008014fc8d4a095ULL, + 0x00d09f2e8a521ec4ULL, 0x006713ab5dde5987ULL, + 0x0003015758e0dbb1ULL, 0x00215999f1ba212dULL)}, + {FIELD_LITERAL(0x002c88e93527da0eULL, 0x0077c78f3456aad5ULL, + 0x0071087a0a389d1cULL, 0x00934dac1fb96dbdULL, + 0x008470e801162697ULL, 0x005bc2196cd4ad49ULL, + 0x00e535601d5087c3ULL, 0x00769888700f497fULL)}, + {FIELD_LITERAL(0x00da7a4b557298adULL, 0x0019d2589ea5df76ULL, + 0x00ef3e38be0c6497ULL, 0x00a9644e1312609aULL, + 0x004592f61b2558daULL, 0x0082c1df510d7e46ULL, + 0x0042809a535c0023ULL, 0x00215bcb5afd7757ULL)}, + }}, {{ + {FIELD_LITERAL(0x002b9df55a1a4213ULL, 0x00dcfc3b464a26beULL, + 0x00c4f9e07a8144d5ULL, 0x00c8e0617a92b602ULL, + 0x008e3c93accafae0ULL, 0x00bf1bcb95b2ca60ULL, + 0x004ce2426a613bf3ULL, 0x00266cac58e40921ULL)}, + {FIELD_LITERAL(0x008456d5db76e8f0ULL, 0x0032ca9cab2ce163ULL, + 0x0059f2b8bf91abcfULL, 0x0063c2a021712788ULL, + 0x00f86155af22f72dULL, 0x00db98b2a6c005a0ULL, + 0x00ac6e416a693ac4ULL, 0x007a93572af53226ULL)}, + {FIELD_LITERAL(0x0087767520f0de22ULL, 0x0091f64012279fb5ULL, + 0x001050f1f0644999ULL, 0x004f097a2477ad3cULL, + 0x006b37913a9947bdULL, 0x001a3d78645af241ULL, + 0x0057832bbb3008a7ULL, 0x002c1d902b80dc20ULL)}, + }}, {{ + {FIELD_LITERAL(0x001a6002bf178877ULL, 0x009bce168aa5af50ULL, + 0x005fc318ff04a7f5ULL, 0x0052818f55c36461ULL, + 0x008768f5d4b24afbULL, 0x0037ffbae7b69c85ULL, + 0x0018195a4b61edc0ULL, 0x001e12ea088434b2ULL)}, + {FIELD_LITERAL(0x0047d3f804e7ab07ULL, 0x00a809ab5f905260ULL, + 0x00b3ffc7cdaf306dULL, 0x00746e8ec2d6e509ULL, + 0x00d0dade8887a645ULL, 0x00acceeebde0dd37ULL, + 0x009bc2579054686bULL, 0x0023804f97f1c2bfULL)}, + {FIELD_LITERAL(0x0043e2e2e50b80d7ULL, 0x00143aafe4427e0fULL, + 0x005594aaecab855bULL, 0x008b12ccaaecbc01ULL, + 0x002deeb091082bc3ULL, 0x009cca4be2ae7514ULL, + 0x00142b96e696d047ULL, 0x00ad2a2b1c05256aULL)}, + }}, {{ + {FIELD_LITERAL(0x003914f2f144b78bULL, 0x007a95dd8bee6f68ULL, + 0x00c7f4384d61c8e6ULL, 0x004e51eb60f1bdb2ULL, + 0x00f64be7aa4621d8ULL, 0x006797bfec2f0ac0ULL, + 0x007d17aab3c75900ULL, 0x001893e73cac8bc5ULL)}, + {FIELD_LITERAL(0x00140360b768665bULL, 0x00b68aca4967f977ULL, + 0x0001089b66195ae4ULL, 0x00fe71122185e725ULL, + 0x000bca2618d49637ULL, 0x00a54f0557d7e98aULL, + 0x00cdcd2f91d6f417ULL, 0x00ab8c13741fd793ULL)}, + {FIELD_LITERAL(0x00725ee6b1e549e0ULL, 0x007124a0769777faULL, + 0x000b68fdad07ae42ULL, 0x0085b909cd4952dfULL, + 0x0092d2e3c81606f4ULL, 0x009f22f6cac099a0ULL, + 0x00f59da57f2799a8ULL, 0x00f06c090122f777ULL)}, + }}, {{ + {FIELD_LITERAL(0x00ce0bed0a3532bcULL, 0x001a5048a22df16bULL, + 0x00e31db4cbad8bf1ULL, 0x00e89292120cf00eULL, + 0x007d1dd1a9b00034ULL, 0x00e2a9041ff8f680ULL, + 0x006a4c837ae596e7ULL, 0x00713af1068070b3ULL)}, + {FIELD_LITERAL(0x00c4fe64ce66d04bULL, 0x00b095d52e09b3d7ULL, + 0x00758bbecb1a3a8eULL, 0x00f35cce8d0650c0ULL, + 0x002b878aa5984473ULL, 0x0062e0a3b7544ddcULL, + 0x00b25b290ed116feULL, 0x007b0f6abe0bebf2ULL)}, + {FIELD_LITERAL(0x0081d4e3addae0a8ULL, 0x003410c836c7ffccULL, + 0x00c8129ad89e4314ULL, 0x000e3d5a23922dcdULL, + 0x00d91e46f29c31f3ULL, 0x006c728cde8c5947ULL, + 0x002bc655ba2566c0ULL, 0x002ca94721533108ULL)}, + }}, {{ + {FIELD_LITERAL(0x0051e4b3f764d8a9ULL, 0x0019792d46e904a0ULL, + 0x00853bc13dbc8227ULL, 0x000840208179f12dULL, + 0x0068243474879235ULL, 0x0013856fbfe374d0ULL, + 0x00bda12fe8676424ULL, 0x00bbb43635926eb2ULL)}, + {FIELD_LITERAL(0x0012cdc880a93982ULL, 0x003c495b21cd1b58ULL, + 0x00b7e5c93f22a26eULL, 0x0044aa82dfb99458ULL, + 0x009ba092cdffe9c0ULL, 0x00a14b3ab2083b73ULL, + 0x000271c2f70e1c4bULL, 0x00eea9cac0f66eb8ULL)}, + {FIELD_LITERAL(0x001a1847c4ac5480ULL, 0x00b1b412935bb03aULL, + 0x00f74285983bf2b2ULL, 0x00624138b5b5d0f1ULL, + 0x008820c0b03d38bfULL, 0x00b94e50a18c1572ULL, + 0x0060f6934841798fULL, 0x00c52f5d66d6ebe2ULL)}, + }}, {{ + {FIELD_LITERAL(0x00da23d59f9bcea6ULL, 0x00e0f27007a06a4bULL, + 0x00128b5b43a6758cULL, 0x000cf50190fa8b56ULL, + 0x00fc877aba2b2d72ULL, 0x00623bef52edf53fULL, + 0x00e6af6b819669e2ULL, 0x00e314dc34fcaa4fULL)}, + {FIELD_LITERAL(0x0066e5eddd164d1eULL, 0x00418a7c6fe28238ULL, + 0x0002e2f37e962c25ULL, 0x00f01f56b5975306ULL, + 0x0048842fa503875cULL, 0x0057b0e968078143ULL, + 0x00ff683024f3d134ULL, 0x0082ae28fcad12e4ULL)}, + {FIELD_LITERAL(0x0011ddfd21260e42ULL, 0x00d05b0319a76892ULL, + 0x00183ea4368e9b8fULL, 0x00b0815662affc96ULL, + 0x00b466a5e7ce7c88ULL, 0x00db93b07506e6eeULL, + 0x0033885f82f62401ULL, 0x0086f9090ec9b419ULL)}, + }}, {{ + {FIELD_LITERAL(0x00d95d1c5fcb435aULL, 0x0016d1ed6b5086f9ULL, + 0x00792aa0b7e54d71ULL, 0x0067b65715f1925dULL, + 0x00a219755ec6176bULL, 0x00bc3f026b12c28fULL, + 0x00700c897ffeb93eULL, 0x0089b83f6ec50b46ULL)}, + {FIELD_LITERAL(0x003c97e6384da36eULL, 0x00423d53eac81a09ULL, + 0x00b70d68f3cdce35ULL, 0x00ee7959b354b92cULL, + 0x00f4e9718819c8caULL, 0x009349f12acbffe9ULL, + 0x005aee7b62cb7da6ULL, 0x00d97764154ffc86ULL)}, + {FIELD_LITERAL(0x00526324babb46dcULL, 0x002ee99b38d7bf9eULL, + 0x007ea51794706ef4ULL, 0x00abeb04da6e3c39ULL, + 0x006b457c1d281060ULL, 0x00fe243e9a66c793ULL, + 0x00378de0fb6c6ee4ULL, 0x003e4194b9c3cb93ULL)}, + }}, {{ + {FIELD_LITERAL(0x00fed3cd80ca2292ULL, 0x0015b043a73ca613ULL, + 0x000a9fd7bf9be227ULL, 0x003b5e03de2db983ULL, + 0x005af72d46904ef7ULL, 0x00c0f1b5c49faa99ULL, + 0x00dc86fc3bd305e1ULL, 0x00c92f08c1cb1797ULL)}, + {FIELD_LITERAL(0x0079680ce111ed3bULL, 0x001a1ed82806122cULL, + 0x000c2e7466d15df3ULL, 0x002c407f6f7150fdULL, + 0x00c5e7c96b1b0ce3ULL, 0x009aa44626863ff9ULL, + 0x00887b8b5b80be42ULL, 0x00b6023cec964825ULL)}, + {FIELD_LITERAL(0x00e4a8e1048970c8ULL, 0x0062887b7830a302ULL, + 0x00bcf1c8cd81402bULL, 0x0056dbb81a68f5beULL, + 0x0014eced83f12452ULL, 0x00139e1a510150dfULL, + 0x00bb81140a82d1a3ULL, 0x000febcc1aaf1aa7ULL)}, + }}, {{ + {FIELD_LITERAL(0x00a7527958238159ULL, 0x0013ec9537a84cd6ULL, + 0x001d7fee7d562525ULL, 0x00b9eefa6191d5e5ULL, + 0x00dbc97db70bcb8aULL, 0x00481affc7a4d395ULL, + 0x006f73d3e70c31bbULL, 0x00183f324ed96a61ULL)}, + {FIELD_LITERAL(0x0039dd7ce7fc6860ULL, 0x00d64f6425653da1ULL, + 0x003e037c7f57d0afULL, 0x0063477a06e2bcf2ULL, + 0x001727dbb7ac67e6ULL, 0x0049589f5efafe2eULL, + 0x00fc0fef2e813d54ULL, 0x008baa5d087fb50dULL)}, + {FIELD_LITERAL(0x0024fb59d9b457c7ULL, 0x00a7d4e060223e4cULL, + 0x00c118d1b555fd80ULL, 0x0082e216c732f22aULL, + 0x00cd2a2993089504ULL, 0x003638e836a3e13dULL, + 0x000d855ee89b4729ULL, 0x008ec5b7d4810c91ULL)}, + }}, {{ + {FIELD_LITERAL(0x001bf51f7d65cdfdULL, 0x00d14cdafa16a97dULL, + 0x002c38e60fcd10e7ULL, 0x00a27446e393efbdULL, + 0x000b5d8946a71fddULL, 0x0063df2cde128f2fULL, + 0x006c8679569b1888ULL, 0x0059ffc4925d732dULL)}, + {FIELD_LITERAL(0x00ece96f95f2b66fULL, 0x00ece7952813a27bULL, + 0x0026fc36592e489eULL, 0x007157d1a2de0f66ULL, + 0x00759dc111d86ddfULL, 0x0012881e5780bb0fULL, + 0x00c8ccc83ad29496ULL, 0x0012b9bd1929eb71ULL)}, + {FIELD_LITERAL(0x000fa15a20da5df0ULL, 0x00349ddb1a46cd31ULL, + 0x002c512ad1d8e726ULL, 0x00047611f669318dULL, + 0x009e68fba591e17eULL, 0x004320dffa803906ULL, + 0x00a640874951a3d3ULL, 0x00b6353478baa24fULL)}, + }}, {{ + {FIELD_LITERAL(0x009696510000d333ULL, 0x00ec2f788bc04826ULL, + 0x000e4d02b1f67ba5ULL, 0x00659aa8dace08b6ULL, + 0x00d7a38a3a3ae533ULL, 0x008856defa8c746bULL, + 0x004d7a4402d3da1aULL, 0x00ea82e06229260fULL)}, + {FIELD_LITERAL(0x006a15bb20f75c0cULL, 0x0079a144027a5d0cULL, + 0x00d19116ce0b4d70ULL, 0x0059b83bcb0b268eULL, + 0x005f58f63f16c127ULL, 0x0079958318ee2c37ULL, + 0x00defbb063d07f82ULL, 0x00f1f0b931d2d446ULL)}, + {FIELD_LITERAL(0x00cb5e4c3c35d422ULL, 0x008df885ca43577fULL, + 0x00fa50b16ca3e471ULL, 0x005a0e58e17488c8ULL, + 0x00b2ceccd6d34d19ULL, 0x00f01d5d235e36e9ULL, + 0x00db2e7e4be6ca44ULL, 0x00260ab77f35fccdULL)}, + }}, {{ + {FIELD_LITERAL(0x006f6fd9baac61d5ULL, 0x002a7710a020a895ULL, + 0x009de0db7fc03d4dULL, 0x00cdedcb1875f40bULL, + 0x00050caf9b6b1e22ULL, 0x005e3a6654456ab0ULL, + 0x00775fdf8c4423d4ULL, 0x0028701ea5738b5dULL)}, + {FIELD_LITERAL(0x009ffd90abfeae96ULL, 0x00cba3c2b624a516ULL, + 0x005ef08bcee46c91ULL, 0x00e6fde30afb6185ULL, + 0x00f0b4db4f818ce4ULL, 0x006c54f45d2127f5ULL, + 0x00040125035854c7ULL, 0x00372658a3287e13ULL)}, + {FIELD_LITERAL(0x00d7070fb1beb2abULL, 0x0078fc845a93896bULL, + 0x006894a4b2f224a6ULL, 0x005bdd8192b9dbdeULL, + 0x00b38839874b3a9eULL, 0x00f93618b04b7a57ULL, + 0x003e3ec75fd2c67eULL, 0x00bf5e6bfc29494aULL)}, + }}, {{ + {FIELD_LITERAL(0x00f19224ebba2aa5ULL, 0x0074f89d358e694dULL, + 0x00eea486597135adULL, 0x0081579a4555c7e1ULL, + 0x0010b9b872930a9dULL, 0x00f002e87a30ecc0ULL, + 0x009b9d66b6de56e2ULL, 0x00a3c4f45e8004ebULL)}, + {FIELD_LITERAL(0x0045e8dda9400888ULL, 0x002ff12e5fc05db7ULL, + 0x00a7098d54afe69cULL, 0x00cdbe846a500585ULL, + 0x00879c1593ca1882ULL, 0x003f7a7fea76c8b0ULL, + 0x002cd73dd0c8e0a1ULL, 0x00645d6ce96f51feULL)}, + {FIELD_LITERAL(0x002b7e83e123d6d6ULL, 0x00398346f7419c80ULL, + 0x0042922e55940163ULL, 0x005e7fc5601886a3ULL, + 0x00e88f2cee1d3103ULL, 0x00e7fab135f2e377ULL, + 0x00b059984dbf0dedULL, 0x0009ce080faa5bb8ULL)}, + }}, {{ + {FIELD_LITERAL(0x0085e78af7758979ULL, 0x00275a4ee1631a3aULL, + 0x00d26bc0ed78b683ULL, 0x004f8355ea21064fULL, + 0x00d618e1a32696e5ULL, 0x008d8d7b150e5680ULL, + 0x00a74cd854b278d2ULL, 0x001dd62702203ea0ULL)}, + {FIELD_LITERAL(0x00f89335c2a59286ULL, 0x00a0f5c905d55141ULL, + 0x00b41fb836ee9382ULL, 0x00e235d51730ca43ULL, + 0x00a5cb37b5c0a69aULL, 0x009b966ffe136c45ULL, + 0x00cb2ea10bf80ed1ULL, 0x00fb2b370b40dc35ULL)}, + {FIELD_LITERAL(0x00d687d16d4ee8baULL, 0x0071520bdd069dffULL, + 0x00de85c60d32355dULL, 0x0087d2e3565102f4ULL, + 0x00cde391b8dfc9aaULL, 0x00e18d69efdfefe5ULL, + 0x004a9d0591954e91ULL, 0x00fa36dd8b50eee5ULL)}, + }}, {{ + {FIELD_LITERAL(0x002e788749a865f7ULL, 0x006e4dc3116861eaULL, + 0x009f1428c37276e6ULL, 0x00e7d2e0fc1e1226ULL, + 0x003aeebc6b6c45f6ULL, 0x0071a8073bf500c9ULL, + 0x004b22ad986b530cULL, 0x00f439e63c0d79d4ULL)}, + {FIELD_LITERAL(0x006bc3d53011f470ULL, 0x00032d6e692b83e8ULL, + 0x00059722f497cd0bULL, 0x0009b4e6f0c497ccULL, + 0x0058a804b7cce6c0ULL, 0x002b71d3302bbd5dULL, + 0x00e2f82a36765fceULL, 0x008dded99524c703ULL)}, + {FIELD_LITERAL(0x004d058953747d64ULL, 0x00701940fe79aa6fULL, + 0x00a620ac71c760bfULL, 0x009532b611158b75ULL, + 0x00547ed7f466f300ULL, 0x003cb5ab53a8401aULL, + 0x00c7763168ce3120ULL, 0x007e48e33e4b9ab2ULL)}, + }}, {{ + {FIELD_LITERAL(0x001b2fc57bf3c738ULL, 0x006a3f918993fb80ULL, + 0x0026f7a14fdec288ULL, 0x0075a2cdccef08dbULL, + 0x00d3ecbc9eecdbf1ULL, 0x0048c40f06e5bf7fULL, + 0x00d63e423009896bULL, 0x000598bc99c056a8ULL)}, + {FIELD_LITERAL(0x002f194eaafa46dcULL, 0x008e38f57fe87613ULL, + 0x00dc8e5ae25f4ab2ULL, 0x000a17809575e6bdULL, + 0x00d3ec7923ba366aULL, 0x003a7e72e0ad75e3ULL, + 0x0010024b88436e0aULL, 0x00ed3c5444b64051ULL)}, + {FIELD_LITERAL(0x00831fc1340af342ULL, 0x00c9645669466d35ULL, + 0x007692b4cc5a080fULL, 0x009fd4a47ac9259fULL, + 0x001eeddf7d45928bULL, 0x003c0446fc45f28bULL, + 0x002c0713aa3e2507ULL, 0x0095706935f0f41eULL)}, + }}, {{ + {FIELD_LITERAL(0x00766ae4190ec6d8ULL, 0x0065768cabc71380ULL, + 0x00b902598416cdc2ULL, 0x00380021ad38df52ULL, + 0x008f0b89d6551134ULL, 0x004254d4cc62c5a5ULL, + 0x000d79f4484b9b94ULL, 0x00b516732ae3c50eULL)}, + {FIELD_LITERAL(0x001fb73475c45509ULL, 0x00d2b2e5ea43345aULL, + 0x00cb3c3842077bd1ULL, 0x0029f90ad820946eULL, + 0x007c11b2380778aaULL, 0x009e54ece62c1704ULL, + 0x004bc60c41ca01c3ULL, 0x004525679a5a0b03ULL)}, + {FIELD_LITERAL(0x00c64fbddbed87b3ULL, 0x0040601d11731faaULL, + 0x009c22475b6f9d67ULL, 0x0024b79dae875f15ULL, + 0x00616fed3f02c3b0ULL, 0x0000cf39f6af2d3bULL, + 0x00c46bac0aa9a688ULL, 0x00ab23e2800da204ULL)}, + }}, {{ + {FIELD_LITERAL(0x000b3a37617632b0ULL, 0x00597199fe1cfb6cULL, + 0x0042a7ccdfeafdd6ULL, 0x004cc9f15ebcea17ULL, + 0x00f436e596a6b4a4ULL, 0x00168861142df0d8ULL, + 0x000753edfec26af5ULL, 0x000c495d7e388116ULL)}, + {FIELD_LITERAL(0x0017085f4a346148ULL, 0x00c7cf7a37f62272ULL, + 0x001776e129bc5c30ULL, 0x009955134c9eef2aULL, + 0x001ba5bdf1df07beULL, 0x00ec39497103a55cULL, + 0x006578354fda6cfbULL, 0x005f02719d4f15eeULL)}, + {FIELD_LITERAL(0x0052b9d9b5d9655dULL, 0x00d4ec7ba1b461c3ULL, + 0x00f95df4974f280bULL, 0x003d8e5ca11aeb51ULL, + 0x00d4981eb5a70b26ULL, 0x000af9a4f6659f29ULL, + 0x004598c846faeb43ULL, 0x0049d9a183a47670ULL)}, + }}, {{ + {FIELD_LITERAL(0x000a72d23dcb3f1fULL, 0x00a3737f84011727ULL, + 0x00f870c0fbbf4a47ULL, 0x00a7aadd04b5c9caULL, + 0x000c7715c67bd072ULL, 0x00015a136afcd74eULL, + 0x0080d5caea499634ULL, 0x0026b448ec7514b7ULL)}, + {FIELD_LITERAL(0x00b60167d9e7d065ULL, 0x00e60ba0d07381e8ULL, + 0x003a4f17b725c2d4ULL, 0x006c19fe176b64faULL, + 0x003b57b31af86ccbULL, 0x0021047c286180fdULL, + 0x00bdc8fb00c6dbb6ULL, 0x00fe4a9f4bab4f3fULL)}, + {FIELD_LITERAL(0x0088ffc3a16111f7ULL, 0x009155e4245d0bc8ULL, + 0x00851d68220572d5ULL, 0x00557ace1e514d29ULL, + 0x0031d7c339d91022ULL, 0x00101d0ae2eaceeaULL, + 0x00246ab3f837b66aULL, 0x00d5216d381ff530ULL)}, + }}, {{ + {FIELD_LITERAL(0x0057e7ea35f36daeULL, 0x00f47d7ad15de22eULL, + 0x00d757ea4b105115ULL, 0x008311457d579d7eULL, + 0x00b49b75b1edd4ebULL, 0x0081c7ff742fd63aULL, + 0x00ddda3187433df6ULL, 0x00475727d55f9c66ULL)}, + {FIELD_LITERAL(0x00a6295218dc136aULL, 0x00563b3af0e9c012ULL, + 0x00d3753b0145db1bULL, 0x004550389c043dc1ULL, + 0x00ea94ae27401bdfULL, 0x002b0b949f2b7956ULL, + 0x00c63f780ad8e23cULL, 0x00e591c47d6bab15ULL)}, + {FIELD_LITERAL(0x00416c582b058eb6ULL, 0x004107da5b2cc695ULL, + 0x00b3cd2556aeec64ULL, 0x00c0b418267e57a1ULL, + 0x001799293579bd2eULL, 0x0046ed44590e4d07ULL, + 0x001d7459b3630a1eULL, 0x00c6afba8b6696aaULL)}, + }}, {{ + {FIELD_LITERAL(0x008d6009b26da3f8ULL, 0x00898e88ca06b1caULL, + 0x00edb22b2ed7fe62ULL, 0x00fbc93516aabe80ULL, + 0x008b4b470c42ce0dULL, 0x00e0032ba7d0dcbbULL, + 0x00d76da3a956ecc8ULL, 0x007f20fe74e3852aULL)}, + {FIELD_LITERAL(0x002419222c607674ULL, 0x00a7f23af89188b3ULL, + 0x00ad127284e73d1cULL, 0x008bba582fae1c51ULL, + 0x00fc6aa7ca9ecab1ULL, 0x003df5319eb6c2baULL, + 0x002a05af8a8b199aULL, 0x004bf8354558407cULL)}, + {FIELD_LITERAL(0x00ce7d4a30f0fcbfULL, 0x00d02c272629f03dULL, + 0x0048c001f7400bc2ULL, 0x002c21368011958dULL, + 0x0098a550391e96b5ULL, 0x002d80b66390f379ULL, + 0x001fa878760cc785ULL, 0x001adfce54b613d5ULL)}, + }}, {{ + {FIELD_LITERAL(0x001ed4dc71fa2523ULL, 0x005d0bff19bf9b5cULL, + 0x00c3801cee065a64ULL, 0x001ed0b504323fbfULL, + 0x0003ab9fdcbbc593ULL, 0x00df82070178b8d2ULL, + 0x00a2bcaa9c251f85ULL, 0x00c628a3674bd02eULL)}, + {FIELD_LITERAL(0x006b7a0674f9f8deULL, 0x00a742414e5c7cffULL, + 0x0041cbf3c6e13221ULL, 0x00e3a64fd207af24ULL, + 0x0087c05f15fbe8d1ULL, 0x004c50936d9e8a33ULL, + 0x001306ec21042b6dULL, 0x00a4f4137d1141c2ULL)}, + {FIELD_LITERAL(0x0009e6fb921568b0ULL, 0x00b3c60120219118ULL, + 0x002a6c3460dd503aULL, 0x009db1ef11654b54ULL, + 0x0063e4bf0be79601ULL, 0x00670d34bb2592b9ULL, + 0x00dcee2f6c4130ceULL, 0x00b2682e88e77f54ULL)}, + }}, {{ + {FIELD_LITERAL(0x000d5b4b3da135abULL, 0x00838f3e5064d81dULL, + 0x00d44eb50f6d94edULL, 0x0008931ab502ac6dULL, + 0x00debe01ca3d3586ULL, 0x0025c206775f0641ULL, + 0x005ad4b6ae912763ULL, 0x007e2c318ad8f247ULL)}, + {FIELD_LITERAL(0x00ddbe0750dd1addULL, 0x004b3c7b885844b8ULL, + 0x00363e7ecf12f1aeULL, 0x0062e953e6438f9dULL, + 0x0023cc73b076afe9ULL, 0x00b09fa083b4da32ULL, + 0x00c7c3d2456c541dULL, 0x005b591ec6b694d4ULL)}, + {FIELD_LITERAL(0x0028656e19d62fcfULL, 0x0052a4af03df148dULL, + 0x00122765ddd14e42ULL, 0x00f2252904f67157ULL, + 0x004741965b636f3aULL, 0x006441d296132cb9ULL, + 0x005e2106f956a5b7ULL, 0x00247029592d335cULL)}, + }}, {{ + {FIELD_LITERAL(0x003fe038eb92f894ULL, 0x000e6da1b72e8e32ULL, + 0x003a1411bfcbe0faULL, 0x00b55d473164a9e4ULL, + 0x00b9a775ac2df48dULL, 0x0002ddf350659e21ULL, + 0x00a279a69eb19cb3ULL, 0x00f844eab25cba44ULL)}, + {FIELD_LITERAL(0x00c41d1f9c1f1ac1ULL, 0x007b2df4e9f19146ULL, + 0x00b469355fd5ba7aULL, 0x00b5e1965afc852aULL, + 0x00388d5f1e2d8217ULL, 0x0022079e4c09ae93ULL, + 0x0014268acd4ef518ULL, 0x00c1dd8d9640464cULL)}, + {FIELD_LITERAL(0x0038526adeed0c55ULL, 0x00dd68c607e3fe85ULL, + 0x00f746ddd48a5d57ULL, 0x0042f2952b963b7cULL, + 0x001cbbd6876d5ec2ULL, 0x005e341470bca5c2ULL, + 0x00871d41e085f413ULL, 0x00e53ab098f45732ULL)}, + }}, {{ + {FIELD_LITERAL(0x004d51124797c831ULL, 0x008f5ae3750347adULL, + 0x0070ced94c1a0c8eULL, 0x00f6db2043898e64ULL, + 0x000d00c9a5750cd0ULL, 0x000741ec59bad712ULL, + 0x003c9d11aab37b7fULL, 0x00a67ba169807714ULL)}, + {FIELD_LITERAL(0x00adb2c1566e8b8fULL, 0x0096c68a35771a9aULL, + 0x00869933356f334aULL, 0x00ba9c93459f5962ULL, + 0x009ec73fb6e8ca4bULL, 0x003c3802c27202e1ULL, + 0x0031f5b733e0c008ULL, 0x00f9058c19611fa9ULL)}, + {FIELD_LITERAL(0x00238f01814a3421ULL, 0x00c325a44b6cce28ULL, + 0x002136f97aeb0e73ULL, 0x000cac8268a4afe2ULL, + 0x0022fd218da471b3ULL, 0x009dcd8dfff8def9ULL, + 0x00cb9f8181d999bbULL, 0x00143ae56edea349ULL)}, + }}, {{ + {FIELD_LITERAL(0x0000623bf87622c5ULL, 0x00a1966fdd069496ULL, + 0x00c315b7b812f9fcULL, 0x00bdf5efcd128b97ULL, + 0x001d464f532e3e16ULL, 0x003cd94f081bfd7eULL, + 0x00ed9dae12ce4009ULL, 0x002756f5736eee70ULL)}, + {FIELD_LITERAL(0x00a5187e6ee7341bULL, 0x00e6d52e82d83b6eULL, + 0x00df3c41323094a7ULL, 0x00b3324f444e9de9ULL, + 0x00689eb21a35bfe5ULL, 0x00f16363becd548dULL, + 0x00e187cc98e7f60fULL, 0x00127d9062f0ccabULL)}, + {FIELD_LITERAL(0x004ad71b31c29e40ULL, 0x00a5fcace12fae29ULL, + 0x004425b5597280edULL, 0x00e7ef5d716c3346ULL, + 0x0010b53ada410ac8ULL, 0x0092310226060c9bULL, + 0x0091c26128729c7eULL, 0x0088b42900f8ec3bULL)}, + }}, {{ + {FIELD_LITERAL(0x00f1e26e9762d4a8ULL, 0x00d9d74082183414ULL, + 0x00ffec9bd57a0282ULL, 0x000919e128fd497aULL, + 0x00ab7ae7d00fe5f8ULL, 0x0054dc442851ff68ULL, + 0x00c9ebeb3b861687ULL, 0x00507f7cab8b698fULL)}, + {FIELD_LITERAL(0x00c13c5aae3ae341ULL, 0x009c6c9ed98373e7ULL, + 0x00098f26864577a8ULL, 0x0015b886e9488b45ULL, + 0x0037692c42aadba5ULL, 0x00b83170b8e7791cULL, + 0x001670952ece1b44ULL, 0x00fd932a39276da2ULL)}, + {FIELD_LITERAL(0x0081a3259bef3398ULL, 0x005480fff416107bULL, + 0x00ce4f607d21be98ULL, 0x003ffc084b41df9bULL, + 0x0043d0bb100502d1ULL, 0x00ec35f575ba3261ULL, + 0x00ca18f677300ef3ULL, 0x00e8bb0a827d8548ULL)}, + }}, {{ + {FIELD_LITERAL(0x00df76b3328ada72ULL, 0x002e20621604a7c2ULL, + 0x00f910638a105b09ULL, 0x00ef4724d96ef2cdULL, + 0x00377d83d6b8a2f7ULL, 0x00b4f48805ade324ULL, + 0x001cd5da8b152018ULL, 0x0045af671a20ca7fULL)}, + {FIELD_LITERAL(0x009ae3b93a56c404ULL, 0x004a410b7a456699ULL, + 0x00023a619355e6b2ULL, 0x009cdc7297387257ULL, + 0x0055b94d4ae70d04ULL, 0x002cbd607f65b005ULL, + 0x003208b489697166ULL, 0x00ea2aa058867370ULL)}, + {FIELD_LITERAL(0x00f29d2598ee3f32ULL, 0x00b4ac5385d82adcULL, + 0x007633eaf04df19bULL, 0x00aa2d3d77ceab01ULL, + 0x004a2302fcbb778aULL, 0x00927f225d5afa34ULL, + 0x004a8e9d5047f237ULL, 0x008224ae9dbce530ULL)}, + }}, {{ + {FIELD_LITERAL(0x001cf640859b02f8ULL, 0x00758d1d5d5ce427ULL, + 0x00763c784ef4604cULL, 0x005fa81aee205270ULL, + 0x00ac537bfdfc44cbULL, 0x004b919bd342d670ULL, + 0x00238508d9bf4b7aULL, 0x00154888795644f3ULL)}, + {FIELD_LITERAL(0x00c845923c084294ULL, 0x00072419a201bc25ULL, + 0x0045f408b5f8e669ULL, 0x00e9d6a186b74dfeULL, + 0x00e19108c68fa075ULL, 0x0017b91d874177b7ULL, + 0x002f0ca2c7912c5aULL, 0x009400aa385a90a2ULL)}, + {FIELD_LITERAL(0x0071110b01482184ULL, 0x00cfed0044f2bef8ULL, + 0x0034f2901cf4662eULL, 0x003b4ae2a67f9834ULL, + 0x00cca9b96fe94810ULL, 0x00522507ae77abd0ULL, + 0x00bac7422721e73eULL, 0x0066622b0f3a62b0ULL)}, + }}, {{ + {FIELD_LITERAL(0x00f8ac5cf4705b6aULL, 0x00867d82dcb457e3ULL, + 0x007e13ab2ccc2ce9ULL, 0x009ee9a018d3930eULL, + 0x008370f8ecb42df8ULL, 0x002d9f019add263eULL, + 0x003302385b92d196ULL, 0x00a15654536e2c0cULL)}, + {FIELD_LITERAL(0x0026ef1614e160afULL, 0x00c023f9edfc9c76ULL, + 0x00cff090da5f57baULL, 0x0076db7a66643ae9ULL, + 0x0019462f8c646999ULL, 0x008fec00b3854b22ULL, + 0x00d55041692a0a1cULL, 0x0065db894215ca00ULL)}, + {FIELD_LITERAL(0x00a925036e0a451cULL, 0x002a0390c36b6cc1ULL, + 0x00f27020d90894f4ULL, 0x008d90d52cbd3d7fULL, + 0x00e1d0137392f3b8ULL, 0x00f017c158b51a8fULL, + 0x00cac313d3ed7dbcULL, 0x00b99a81e3eb42d3ULL)}, + }}, {{ + {FIELD_LITERAL(0x00b54850275fe626ULL, 0x0053a3fd1ec71140ULL, + 0x00e3d2d7dbe096faULL, 0x00e4ac7b595cce4cULL, + 0x0077bad449c0a494ULL, 0x00b7c98814afd5b3ULL, + 0x0057226f58486cf9ULL, 0x00b1557154f0cc57ULL)}, + {FIELD_LITERAL(0x008cc9cd236315c0ULL, 0x0031d9c5b39fda54ULL, + 0x00a5713ef37e1171ULL, 0x00293d5ae2886325ULL, + 0x00c4aba3e05015e1ULL, 0x0003f35ef78e4fc6ULL, + 0x0039d6bd3ac1527bULL, 0x0019d7c3afb77106ULL)}, + {FIELD_LITERAL(0x007b162931a985afULL, 0x00ad40a2e0daa713ULL, + 0x006df27c4009f118ULL, 0x00503e9f4e2e8becULL, + 0x00751a77c82c182dULL, 0x000298937769245bULL, + 0x00ffb1e8fabf9ee5ULL, 0x0008334706e09abeULL)}, + }}, {{ + {FIELD_LITERAL(0x00dbca4e98a7dcd9ULL, 0x00ee29cfc78bde99ULL, + 0x00e4a3b6995f52e9ULL, 0x0045d70189ae8096ULL, + 0x00fd2a8a3b9b0d1bULL, 0x00af1793b107d8e1ULL, + 0x00dbf92cbe4afa20ULL, 0x00da60f798e3681dULL)}, + {FIELD_LITERAL(0x004246bfcecc627aULL, 0x004ba431246c03a4ULL, + 0x00bd1d101872d497ULL, 0x003b73d3f185ee16ULL, + 0x001feb2e2678c0e3ULL, 0x00ff13c5a89dec76ULL, + 0x00ed06042e771d8fULL, 0x00a4fd2a897a83ddULL)}, + {FIELD_LITERAL(0x009a4a3be50d6597ULL, 0x00de3165fc5a1096ULL, + 0x004f3f56e345b0c7ULL, 0x00f7bf721d5ab8bcULL, + 0x004313e47b098c50ULL, 0x00e4c7d5c0e1adbbULL, + 0x002e3e3db365051eULL, 0x00a480c2cd6a96fbULL)}, + }}, {{ + {FIELD_LITERAL(0x00417fa30a7119edULL, 0x00af257758419751ULL, + 0x00d358a487b463d4ULL, 0x0089703cc720b00dULL, + 0x00ce56314ff7f271ULL, 0x0064db171ade62c1ULL, + 0x00640b36d4a22fedULL, 0x00424eb88696d23fULL)}, + {FIELD_LITERAL(0x004ede34af2813f3ULL, 0x00d4a8e11c9e8216ULL, + 0x004796d5041de8a5ULL, 0x00c4c6b4d21cc987ULL, + 0x00e8a433ee07fa1eULL, 0x0055720b5abcc5a1ULL, + 0x008873ea9c74b080ULL, 0x005b3fec1ab65d48ULL)}, + {FIELD_LITERAL(0x0047e5277db70ec5ULL, 0x000a096c66db7d6bULL, + 0x00b4164cc1730159ULL, 0x004a9f783fe720feULL, + 0x00a8177b94449dbcULL, 0x0095a24ff49a599fULL, + 0x0069c1c578250cbcULL, 0x00452019213debf4ULL)}, + }}, {{ + {FIELD_LITERAL(0x0021ce99e09ebda3ULL, 0x00fcbd9f91875ad0ULL, + 0x009bbf6b7b7a0b5fULL, 0x00388886a69b1940ULL, + 0x00926a56d0f81f12ULL, 0x00e12903c3358d46ULL, + 0x005dfce4e8e1ce9dULL, 0x0044cfa94e2f7e23ULL)}, + {FIELD_LITERAL(0x001bd59c09e982eaULL, 0x00f72daeb937b289ULL, + 0x0018b76dca908e0eULL, 0x00edb498512384adULL, + 0x00ce0243b6cc9538ULL, 0x00f96ff690cb4e70ULL, + 0x007c77bf9f673c8dULL, 0x005bf704c088a528ULL)}, + {FIELD_LITERAL(0x0093d4628dcb33beULL, 0x0095263d51d42582ULL, + 0x0049b3222458fe06ULL, 0x00e7fce73b653a7fULL, + 0x003ca2ebce60b369ULL, 0x00c5de239a32bea4ULL, + 0x0063b8b3d71fb6bfULL, 0x0039aeeb78a1a839ULL)}, + }}, {{ + {FIELD_LITERAL(0x007dc52da400336cULL, 0x001fded1e15b9457ULL, + 0x00902e00f5568e3aULL, 0x00219bef40456d2dULL, + 0x005684161fb3dbc9ULL, 0x004a4e9be49a76eaULL, + 0x006e685ae88b78ffULL, 0x0021c42f13042d3cULL)}, + {FIELD_LITERAL(0x00fb22bb5fd3ce50ULL, 0x0017b48aada7ae54ULL, + 0x00fd5c44ad19a536ULL, 0x000ccc4e4e55e45cULL, + 0x00fd637d45b4c3f5ULL, 0x0038914e023c37cfULL, + 0x00ac1881d6a8d898ULL, 0x00611ed8d3d943a8ULL)}, + {FIELD_LITERAL(0x0056e2259d113d2bULL, 0x00594819b284ec16ULL, + 0x00c7bf794bb36696ULL, 0x00721ee75097cdc6ULL, + 0x00f71be9047a2892ULL, 0x00df6ba142564edfULL, + 0x0069580b7a184e8dULL, 0x00f056e38fca0feeULL)}, + }}, {{ + {FIELD_LITERAL(0x009df98566a18c6dULL, 0x00cf3a200968f219ULL, + 0x0044ba60da6d9086ULL, 0x00dbc9c0e344da03ULL, + 0x000f9401c4466855ULL, 0x00d46a57c5b0a8d1ULL, + 0x00875a635d7ac7c6ULL, 0x00ef4a933b7e0ae6ULL)}, + {FIELD_LITERAL(0x005e8694077a1535ULL, 0x008bef75f71c8f1dULL, + 0x000a7c1316423511ULL, 0x00906e1d70604320ULL, + 0x003fc46c1a2ffbd6ULL, 0x00d1d5022e68f360ULL, + 0x002515fba37bbf46ULL, 0x00ca16234e023b44ULL)}, + {FIELD_LITERAL(0x00787c99561f4690ULL, 0x00a857a8c1561f27ULL, + 0x00a10df9223c09feULL, 0x00b98a9562e3b154ULL, + 0x004330b8744c3ed2ULL, 0x00e06812807ec5c4ULL, + 0x00e4cf6a7db9f1e3ULL, 0x00d95b089f132a34ULL)}, + }}, {{ + {FIELD_LITERAL(0x002922b39ca33eecULL, 0x0090d12a5f3ab194ULL, + 0x00ab60c02fb5f8edULL, 0x00188d292abba1cfULL, + 0x00e10edec9698f6eULL, 0x0069a4d9934133c8ULL, + 0x0024aac40e6d3d06ULL, 0x001702c2177661b0ULL)}, + {FIELD_LITERAL(0x00139078397030bdULL, 0x000e3c447e859a00ULL, + 0x0064a5b334c82393ULL, 0x00b8aabeb7358093ULL, + 0x00020778bb9ae73bULL, 0x0032ee94c7892a18ULL, + 0x008215253cb41bdaULL, 0x005e2797593517aeULL)}, + {FIELD_LITERAL(0x0083765a5f855d4aULL, 0x0051b6d1351b8ee2ULL, + 0x00116de548b0f7bbULL, 0x0087bd88703affa0ULL, + 0x0095b2cc34d7fdd2ULL, 0x0084cd81b53f0bc8ULL, + 0x008562fc995350edULL, 0x00a39abb193651e3ULL)}, + }}, {{ + {FIELD_LITERAL(0x0019e23f0474b114ULL, 0x00eb94c2ad3b437eULL, + 0x006ddb34683b75acULL, 0x00391f9209b564c6ULL, + 0x00083b3bb3bff7aaULL, 0x00eedcd0f6dceefcULL, + 0x00b50817f794fe01ULL, 0x0036474deaaa75c9ULL)}, + {FIELD_LITERAL(0x0091868594265aa2ULL, 0x00797accae98ca6dULL, + 0x0008d8c5f0f8a184ULL, 0x00d1f4f1c2b2fe6eULL, + 0x0036783dfb48a006ULL, 0x008c165120503527ULL, + 0x0025fd780058ce9bULL, 0x0068beb007be7d27ULL)}, + {FIELD_LITERAL(0x00d0ff88aa7c90c2ULL, 0x00b2c60dacf53394ULL, + 0x0094a7284d9666d6ULL, 0x00bed9022ce7a19dULL, + 0x00c51553f0cd7682ULL, 0x00c3fb870b124992ULL, + 0x008d0bc539956c9bULL, 0x00fc8cf258bb8885ULL)}, + }}, {{ + {FIELD_LITERAL(0x003667bf998406f8ULL, 0x0000115c43a12975ULL, + 0x001e662f3b20e8fdULL, 0x0019ffa534cb24ebULL, + 0x00016be0dc8efb45ULL, 0x00ff76a8b26243f5ULL, + 0x00ae20d241a541e3ULL, 0x0069bd6af13cd430ULL)}, + {FIELD_LITERAL(0x0045fdc16487cda3ULL, 0x00b2d8e844cf2ed7ULL, + 0x00612c50e88c1607ULL, 0x00a08aabc66c1672ULL, + 0x006031fdcbb24d97ULL, 0x001b639525744b93ULL, + 0x004409d62639ab17ULL, 0x00a1853d0347ab1dULL)}, + {FIELD_LITERAL(0x0075a1a56ebf5c21ULL, 0x00a3e72be9ac53edULL, + 0x00efcde1629170c2ULL, 0x0004225fe91ef535ULL, + 0x0088049fc73dfda7ULL, 0x004abc74857e1288ULL, + 0x0024e2434657317cULL, 0x00d98cb3d3e5543cULL)}, + }}, {{ + {FIELD_LITERAL(0x00b4b53eab6bdb19ULL, 0x009b22d8b43711d0ULL, + 0x00d948b9d961785dULL, 0x00cb167b6f279eadULL, + 0x00191de3a678e1c9ULL, 0x00d9dd9511095c2eULL, + 0x00f284324cd43067ULL, 0x00ed74fa535151ddULL)}, + {FIELD_LITERAL(0x007e32c049b5c477ULL, 0x009d2bfdbd9bcfd8ULL, + 0x00636e93045938c6ULL, 0x007fde4af7687298ULL, + 0x0046a5184fafa5d3ULL, 0x0079b1e7f13a359bULL, + 0x00875adf1fb927d6ULL, 0x00333e21c61bcad2ULL)}, + {FIELD_LITERAL(0x00048014f73d8b8dULL, 0x0075684aa0966388ULL, + 0x0092be7df06dc47cULL, 0x0097cebcd0f5568aULL, + 0x005a7004d9c4c6a9ULL, 0x00b0ecbb659924c7ULL, + 0x00d90332dd492a7cULL, 0x0057fc14df11493dULL)}, + }}, {{ + {FIELD_LITERAL(0x0008ed8ea0ad95beULL, 0x0041d324b9709645ULL, + 0x00e25412257a19b4ULL, 0x0058df9f3423d8d2ULL, + 0x00a9ab20def71304ULL, 0x009ae0dbf8ac4a81ULL, + 0x00c9565977e4392aULL, 0x003c9269444baf55ULL)}, + {FIELD_LITERAL(0x007df6cbb926830bULL, 0x00d336058ae37865ULL, + 0x007af47dac696423ULL, 0x0048d3011ec64ac8ULL, + 0x006b87666e40049fULL, 0x0036a2e0e51303d7ULL, + 0x00ba319bd79dbc55ULL, 0x003e2737ecc94f53ULL)}, + {FIELD_LITERAL(0x00d296ff726272d9ULL, 0x00f6d097928fcf57ULL, + 0x00e0e616a55d7013ULL, 0x00deaf454ed9eac7ULL, + 0x0073a56bedef4d92ULL, 0x006ccfdf6fc92e19ULL, + 0x009d1ee1371a7218ULL, 0x00ee3c2ee4462d80ULL)}, + }}, {{ + {FIELD_LITERAL(0x00437bce9bccdf9dULL, 0x00e0c8e2f85dc0a3ULL, + 0x00c91a7073995a19ULL, 0x00856ec9fe294559ULL, + 0x009e4b33394b156eULL, 0x00e245b0dc497e5cULL, + 0x006a54e687eeaeffULL, 0x00f1cd1cd00fdb7cULL)}, + {FIELD_LITERAL(0x008132ae5c5d8cd1ULL, 0x00121d68324a1d9fULL, + 0x00d6be9dafcb8c76ULL, 0x00684d9070edf745ULL, + 0x00519fbc96d7448eULL, 0x00388182fdc1f27eULL, + 0x000235baed41f158ULL, 0x00bf6cf6f1a1796aULL)}, + {FIELD_LITERAL(0x002adc4b4d148219ULL, 0x003084ada0d3a90aULL, + 0x0046de8aab0f2e4eULL, 0x00452d342a67b5fdULL, + 0x00d4b50f01d4de21ULL, 0x00db6d9fc0cefb79ULL, + 0x008c184c86a462cdULL, 0x00e17c83764d42daULL)}, + }}, {{ + {FIELD_LITERAL(0x007b2743b9a1e01aULL, 0x007847ffd42688c4ULL, + 0x006c7844d610a316ULL, 0x00f0cb8b250aa4b0ULL, + 0x00a19060143b3ae6ULL, 0x0014eb10b77cfd80ULL, + 0x000170905729dd06ULL, 0x00063b5b9cd72477ULL)}, + {FIELD_LITERAL(0x00ce382dc7993d92ULL, 0x00021153e938b4c8ULL, + 0x00096f7567f48f51ULL, 0x0058f81ddfe4b0d5ULL, + 0x00cc379a56b355c7ULL, 0x002c760770d3e819ULL, + 0x00ee22d1d26e5a40ULL, 0x00de6d93d5b082d7ULL)}, + {FIELD_LITERAL(0x000a91a42c52e056ULL, 0x00185f6b77fce7eaULL, + 0x000803c51962f6b5ULL, 0x0022528582ba563dULL, + 0x0043f8040e9856d6ULL, 0x0085a29ec81fb860ULL, + 0x005f9a611549f5ffULL, 0x00c1f974ecbd4b06ULL)}, + }}, {{ + {FIELD_LITERAL(0x005b64c6fd65ec97ULL, 0x00c1fdd7f877bc7fULL, + 0x000d9cc6c89f841cULL, 0x005c97b7f1aff9adULL, + 0x0075e3c61475d47eULL, 0x001ecb1ba8153011ULL, + 0x00fe7f1c8d71d40dULL, 0x003fa9757a229832ULL)}, + {FIELD_LITERAL(0x00ffc5c89d2b0cbaULL, 0x00d363d42e3e6fc3ULL, + 0x0019a1a0118e2e8aULL, 0x00f7baeff48882e1ULL, + 0x001bd5af28c6b514ULL, 0x0055476ca2253cb2ULL, + 0x00d8eb1977e2ddf3ULL, 0x00b173b1adb228a1ULL)}, + {FIELD_LITERAL(0x00f2cb99dd0ad707ULL, 0x00e1e08b6859ddd8ULL, + 0x000008f2d0650bccULL, 0x00d7ed392f8615c3ULL, + 0x00976750a94da27fULL, 0x003e83bb0ecb69baULL, + 0x00df8e8d15c14ac6ULL, 0x00f9f7174295d9c2ULL)}, + }}, {{ + {FIELD_LITERAL(0x00f11cc8e0e70bcbULL, 0x00e5dc689974e7ddULL, + 0x0014e409f9ee5870ULL, 0x00826e6689acbd63ULL, + 0x008a6f4e3d895d88ULL, 0x00b26a8da41fd4adULL, + 0x000fb7723f83efd7ULL, 0x009c749db0a5f6c3ULL)}, + {FIELD_LITERAL(0x002389319450f9baULL, 0x003677f31aa1250aULL, + 0x0092c3db642f38cbULL, 0x00f8b64c0dfc9773ULL, + 0x00cd49fe3505b795ULL, 0x0068105a4090a510ULL, + 0x00df0ba2072a8bb6ULL, 0x00eb396143afd8beULL)}, + {FIELD_LITERAL(0x00a0d4ecfb24cdffULL, 0x00ddaf8008ba6479ULL, + 0x00f0b3e36d4b0f44ULL, 0x003734bd3af1f146ULL, + 0x00b87e2efc75527eULL, 0x00d230df55ddab50ULL, + 0x002613257ae56c1dULL, 0x00bc0946d135934dULL)}, + }}, {{ + {FIELD_LITERAL(0x00468711bd994651ULL, 0x0033108fa67561bfULL, + 0x0089d760192a54b4ULL, 0x00adc433de9f1871ULL, + 0x000467d05f36e050ULL, 0x007847e0f0579f7fULL, + 0x00a2314ad320052dULL, 0x00b3a93649f0b243ULL)}, + {FIELD_LITERAL(0x0067f8f0c4fe26c9ULL, 0x0079c4a3cc8f67b9ULL, + 0x0082b1e62f23550dULL, 0x00f2d409caefd7f5ULL, + 0x0080e67dcdb26e81ULL, 0x0087ae993ea1f98aULL, + 0x00aa108becf61d03ULL, 0x001acf11efb608a3ULL)}, + {FIELD_LITERAL(0x008225febbab50d9ULL, 0x00f3b605e4dd2083ULL, + 0x00a32b28189e23d2ULL, 0x00d507e5e5eb4c97ULL, + 0x005a1a84e302821fULL, 0x0006f54c1c5f08c7ULL, + 0x00a347c8cb2843f0ULL, 0x0009f73e9544bfa5ULL)}, + }}, {{ + {FIELD_LITERAL(0x006c59c9ae744185ULL, 0x009fc32f1b4282cdULL, + 0x004d6348ca59b1acULL, 0x00105376881be067ULL, + 0x00af4096013147dcULL, 0x004abfb5a5cb3124ULL, + 0x000d2a7f8626c354ULL, 0x009c6ed568e07431ULL)}, + {FIELD_LITERAL(0x00e828333c297f8bULL, 0x009ef3cf8c3f7e1fULL, + 0x00ab45f8fff31cb9ULL, 0x00c8b4178cb0b013ULL, + 0x00d0c50dd3260a3fULL, 0x0097126ac257f5bcULL, + 0x0042376cc90c705aULL, 0x001d96fdb4a1071eULL)}, + {FIELD_LITERAL(0x00542d44d89ee1a8ULL, 0x00306642e0442d98ULL, + 0x0090853872b87338ULL, 0x002362cbf22dc044ULL, + 0x002c222adff663b8ULL, 0x0067c924495fcb79ULL, + 0x000e621d983c977cULL, 0x00df77a9eccb66fbULL)}, + }}, {{ + {FIELD_LITERAL(0x002809e4bbf1814aULL, 0x00b9e854f9fafb32ULL, + 0x00d35e67c10f7a67ULL, 0x008f1bcb76e748cfULL, + 0x004224d9515687d2ULL, 0x005ba0b774e620c4ULL, + 0x00b5e57db5d54119ULL, 0x00e15babe5683282ULL)}, + {FIELD_LITERAL(0x00832d02369b482cULL, 0x00cba52ff0d93450ULL, + 0x003fa9c908d554dbULL, 0x008d1e357b54122fULL, + 0x00abd91c2dc950c6ULL, 0x007eff1df4c0ec69ULL, + 0x003f6aeb13fb2d31ULL, 0x00002d6179fc5b2cULL)}, + {FIELD_LITERAL(0x0046c9eda81c9c89ULL, 0x00b60cb71c8f62fcULL, + 0x0022f5a683baa558ULL, 0x00f87319fccdf997ULL, + 0x009ca09b51ce6a22ULL, 0x005b12baf4af7d77ULL, + 0x008a46524a1e33e2ULL, 0x00035a77e988be0dULL)}, + }}, {{ + {FIELD_LITERAL(0x00a7efe46a7dbe2fULL, 0x002f66fd55014fe7ULL, + 0x006a428afa1ff026ULL, 0x0056caaa9604ab72ULL, + 0x0033f3bcd7fac8aeULL, 0x00ccb1aa01c86764ULL, + 0x00158d1edf13bf40ULL, 0x009848ee76fcf3b4ULL)}, + {FIELD_LITERAL(0x00a9e7730a819691ULL, 0x00d9cc73c4992b70ULL, + 0x00e299bde067de5aULL, 0x008c314eb705192aULL, + 0x00e7226f17e8a3ccULL, 0x0029dfd956e65a47ULL, + 0x0053a8e839073b12ULL, 0x006f942b2ab1597eULL)}, + {FIELD_LITERAL(0x001c3d780ecd5e39ULL, 0x0094f247fbdcc5feULL, + 0x00d5c786fd527764ULL, 0x00b6f4da74f0db2aULL, + 0x0080f1f8badcd5fcULL, 0x00f36a373ad2e23bULL, + 0x00f804f9f4343bf2ULL, 0x00d1af40ec623982ULL)}, + }}, {{ + {FIELD_LITERAL(0x0082aeace5f1b144ULL, 0x00f68b3108cf4dd3ULL, + 0x00634af01dde3020ULL, 0x000beab5df5c2355ULL, + 0x00e8b790d1b49b0bULL, 0x00e48d15854e36f4ULL, + 0x0040ab2d95f3db9fULL, 0x002711c4ed9e899aULL)}, + {FIELD_LITERAL(0x0039343746531ebeULL, 0x00c8509d835d429dULL, + 0x00e79eceff6b0018ULL, 0x004abfd31e8efce5ULL, + 0x007bbfaaa1e20210ULL, 0x00e3be89c193e179ULL, + 0x001c420f4c31d585ULL, 0x00f414a315bef5aeULL)}, + {FIELD_LITERAL(0x007c296a24990df8ULL, 0x00d5d07525a75588ULL, + 0x00dd8e113e94b7e7ULL, 0x007bbc58febe0cc8ULL, + 0x0029f51af9bfcad3ULL, 0x007e9311ec7ab6f3ULL, + 0x009a884de1676343ULL, 0x0050d5f2dce84be9ULL)}, + }}, {{ + {FIELD_LITERAL(0x005fa020cca2450aULL, 0x00491c29db6416d8ULL, + 0x0037cefe3f9f9a85ULL, 0x003d405230647066ULL, + 0x0049e835f0fdbe89ULL, 0x00feb78ac1a0815cULL, + 0x00828e4b32dc9724ULL, 0x00db84f2dc8d6fd4ULL)}, + {FIELD_LITERAL(0x0098cddc8b39549aULL, 0x006da37e3b05d22cULL, + 0x00ce633cfd4eb3cbULL, 0x00fda288ef526acdULL, + 0x0025338878c5d30aULL, 0x00f34438c4e5a1b4ULL, + 0x00584efea7c310f1ULL, 0x0041a551f1b660adULL)}, + {FIELD_LITERAL(0x00d7f7a8fbd6437aULL, 0x0062872413bf3753ULL, + 0x00ad4bbcb43c584bULL, 0x007fe49be601d7e3ULL, + 0x0077c659789babf4ULL, 0x00eb45fcb06a741bULL, + 0x005ce244913f9708ULL, 0x0088426401736326ULL)}, + }}, {{ + {FIELD_LITERAL(0x007bf562ca768d7cULL, 0x006c1f3a174e387cULL, + 0x00f024b447fee939ULL, 0x007e7af75f01143fULL, + 0x003adb70b4eed89dULL, 0x00e43544021ad79aULL, + 0x0091f7f7042011f6ULL, 0x0093c1a1ee3a0ddcULL)}, + {FIELD_LITERAL(0x00a0b68ec1eb72d2ULL, 0x002c03235c0d45a0ULL, + 0x00553627323fe8c5ULL, 0x006186e94b17af94ULL, + 0x00a9906196e29f14ULL, 0x0025b3aee6567733ULL, + 0x007e0dd840080517ULL, 0x0018eb5801a4ba93ULL)}, + {FIELD_LITERAL(0x00d7fe7017bf6a40ULL, 0x006e3f0624be0c42ULL, + 0x00ffbba205358245ULL, 0x00f9fc2cf8194239ULL, + 0x008d93b37bf15b4eULL, 0x006ddf2e38be8e95ULL, + 0x002b6e79bf5fcff9ULL, 0x00ab355da425e2deULL)}, + }}, {{ + {FIELD_LITERAL(0x00938f97e20be973ULL, 0x0099141a36aaf306ULL, + 0x0057b0ca29e545a1ULL, 0x0085db571f9fbc13ULL, + 0x008b333c554b4693ULL, 0x0043ab6ef3e241cbULL, + 0x0054fb20aa1e5c70ULL, 0x00be0ff852760adfULL)}, + {FIELD_LITERAL(0x003973d8938971d6ULL, 0x002aca26fa80c1f5ULL, + 0x00108af1faa6b513ULL, 0x00daae275d7924e6ULL, + 0x0053634ced721308ULL, 0x00d2355fe0bbd443ULL, + 0x00357612b2d22095ULL, 0x00f9bb9dd4136cf3ULL)}, + {FIELD_LITERAL(0x002bff12cf5e03a5ULL, 0x001bdb1fa8a19cf8ULL, + 0x00c91c6793f84d39ULL, 0x00f869f1b2eba9afULL, + 0x0059bc547dc3236bULL, 0x00d91611d6d38689ULL, + 0x00e062daaa2c0214ULL, 0x00ed3c047cc2bc82ULL)}, + }}, {{ + {FIELD_LITERAL(0x000050d70c32b31aULL, 0x001939d576d437b3ULL, + 0x00d709e598bf9fe6ULL, 0x00a885b34bd2ee9eULL, + 0x00dd4b5c08ab1a50ULL, 0x0091bebd50b55639ULL, + 0x00cf79ff64acdbc6ULL, 0x006067a39d826336ULL)}, + {FIELD_LITERAL(0x0062dd0fb31be374ULL, 0x00fcc96b84c8e727ULL, + 0x003f64f1375e6ae3ULL, 0x0057d9b6dd1af004ULL, + 0x00d6a167b1103c7bULL, 0x00dd28f3180fb537ULL, + 0x004ff27ad7167128ULL, 0x008934c33461f2acULL)}, + {FIELD_LITERAL(0x0065b472b7900043ULL, 0x00ba7efd2ff1064bULL, + 0x000b67d6c4c3020fULL, 0x0012d28469f4e46dULL, + 0x0031c32939703ec7ULL, 0x00b49f0bce133066ULL, + 0x00f7e10416181d47ULL, 0x005c90f51867eeccULL)}, + }}, {{ + {FIELD_LITERAL(0x0051207abd179101ULL, 0x00fc2a5c20d9c5daULL, + 0x00fb9d5f2701b6dfULL, 0x002dd040fdea82b8ULL, + 0x00f163b0738442ffULL, 0x00d9736bd68855b8ULL, + 0x00e0d8e93005e61cULL, 0x00df5a40b3988570ULL)}, + {FIELD_LITERAL(0x0006918f5dfce6dcULL, 0x00d4bf1c793c57fbULL, + 0x0069a3f649435364ULL, 0x00e89a50e5b0cd6eULL, + 0x00b9f6a237e973afULL, 0x006d4ed8b104e41dULL, + 0x00498946a3924cd2ULL, 0x00c136ec5ac9d4f7ULL)}, + {FIELD_LITERAL(0x0011a9c290ac5336ULL, 0x002b9a2d4a6a6533ULL, + 0x009a8a68c445d937ULL, 0x00361b27b07e5e5cULL, + 0x003c043b1755b974ULL, 0x00b7eb66cf1155eeULL, + 0x0077af5909eefff2ULL, 0x0098f609877cc806ULL)}, + }}, {{ + {FIELD_LITERAL(0x00ab13af436bf8f4ULL, 0x000bcf0a0dac8574ULL, + 0x00d50c864f705045ULL, 0x00c40e611debc842ULL, + 0x0085010489bd5caaULL, 0x007c5050acec026fULL, + 0x00f67d943c8da6d1ULL, 0x00de1da0278074c6ULL)}, + {FIELD_LITERAL(0x00b373076597455fULL, 0x00e83f1af53ac0f5ULL, + 0x0041f63c01dc6840ULL, 0x0097dea19b0c6f4bULL, + 0x007f9d63b4c1572cULL, 0x00e692d492d0f5f0ULL, + 0x00cbcb392e83b4adULL, 0x0069c0f39ed9b1a8ULL)}, + {FIELD_LITERAL(0x00861030012707c9ULL, 0x009fbbdc7fd4aafbULL, + 0x008f591d6b554822ULL, 0x00df08a41ea18adeULL, + 0x009d7d83e642abeaULL, 0x0098c71bda3b78ffULL, + 0x0022c89e7021f005ULL, 0x0044d29a3fe1e3c4ULL)}, + }}, {{ + {FIELD_LITERAL(0x00e748cd7b5c52f2ULL, 0x00ea9df883f89cc3ULL, + 0x0018970df156b6c7ULL, 0x00c5a46c2a33a847ULL, + 0x00cbde395e32aa09ULL, 0x0072474ebb423140ULL, + 0x00fb00053086a23dULL, 0x001dafcfe22d4e1fULL)}, + {FIELD_LITERAL(0x00c903ee6d825540ULL, 0x00add6c4cf98473eULL, + 0x007636efed4227f1ULL, 0x00905124ae55e772ULL, + 0x00e6b38fab12ed53ULL, 0x0045e132b863fe55ULL, + 0x003974662edb366aULL, 0x00b1787052be8208ULL)}, + {FIELD_LITERAL(0x00a614b00d775c7cULL, 0x00d7c78941cc7754ULL, + 0x00422dd68b5dabc4ULL, 0x00a6110f0167d28bULL, + 0x00685a309c252886ULL, 0x00b439ffd5143660ULL, + 0x003656e29ee7396fULL, 0x00c7c9b9ed5ad854ULL)}, + }}, {{ + {FIELD_LITERAL(0x0040f7e7c5b37bf2ULL, 0x0064e4dc81181bbaULL, + 0x00a8767ae2a366b6ULL, 0x001496b4f90546f2ULL, + 0x002a28493f860441ULL, 0x0021f59513049a3aULL, + 0x00852d369a8b7ee3ULL, 0x00dd2e7d8b7d30a9ULL)}, + {FIELD_LITERAL(0x00006e34a35d9fbcULL, 0x00eee4e48b2f019aULL, + 0x006b344743003a5fULL, 0x00541d514f04a7e3ULL, + 0x00e81f9ee7647455ULL, 0x005e2b916c438f81ULL, + 0x00116f8137b7eff0ULL, 0x009bd3decc7039d1ULL)}, + {FIELD_LITERAL(0x0005d226f434110dULL, 0x00af8288b8ef21d5ULL, + 0x004a7a52ef181c8cULL, 0x00be0b781b4b06deULL, + 0x00e6e3627ded07e1ULL, 0x00e43aa342272b8bULL, + 0x00e86ab424577d84ULL, 0x00fb292c566e35bbULL)}, + }}, {{ + {FIELD_LITERAL(0x00334f5303ea1222ULL, 0x00dfb3dbeb0a5d3eULL, + 0x002940d9592335c1ULL, 0x00706a7a63e8938aULL, + 0x005a533558bc4cafULL, 0x00558e33192022a9ULL, + 0x00970d9faf74c133ULL, 0x002979fcb63493caULL)}, + {FIELD_LITERAL(0x00e38abece3c82abULL, 0x005a51f18a2c7a86ULL, + 0x009dafa2e86d592eULL, 0x00495a62eb688678ULL, + 0x00b79df74c0eb212ULL, 0x0023e8cc78b75982ULL, + 0x005998cb91075e13ULL, 0x00735aa9ba61bc76ULL)}, + {FIELD_LITERAL(0x00d9f7a82ddbe628ULL, 0x00a1fc782889ae0fULL, + 0x0071ffda12d14b66ULL, 0x0037cf4eca7fb3d5ULL, + 0x00c80bc242c58808ULL, 0x0075bf8c2d08c863ULL, + 0x008d41f31afc52a7ULL, 0x00197962ecf38741ULL)}, + }}, {{ + {FIELD_LITERAL(0x006e9f475cccf2eeULL, 0x00454b9cd506430cULL, + 0x00224a4fb79ee479ULL, 0x0062e3347ef0b5e2ULL, + 0x0034fd2a3512232aULL, 0x00b8b3cb0f457046ULL, + 0x00eb20165daa38ecULL, 0x00128eebc2d9c0f7ULL)}, + {FIELD_LITERAL(0x00bfc5fa1e4ea21fULL, 0x00c21d7b6bb892e6ULL, + 0x00cf043f3acf0291ULL, 0x00c13f2f849b3c90ULL, + 0x00d1a97ebef10891ULL, 0x0061e130a445e7feULL, + 0x0019513fdedbf22bULL, 0x001d60c813bff841ULL)}, + {FIELD_LITERAL(0x0019561c7fcf0213ULL, 0x00e3dca6843ebd77ULL, + 0x0068ea95b9ca920eULL, 0x009bdfb70f253595ULL, + 0x00c68f59186aa02aULL, 0x005aee1cca1c3039ULL, + 0x00ab79a8a937a1ceULL, 0x00b9a0e549959e6fULL)}, + }}, {{ + {FIELD_LITERAL(0x00c79e0b6d97dfbdULL, 0x00917c71fd2bc6e8ULL, + 0x00db7529ccfb63d8ULL, 0x00be5be957f17866ULL, + 0x00a9e11fdc2cdac1ULL, 0x007b91a8e1f44443ULL, + 0x00a3065e4057d80fULL, 0x004825f5b8d5f6d4ULL)}, + {FIELD_LITERAL(0x003e4964fa8a8fc8ULL, 0x00f6a1cdbcf41689ULL, + 0x00943cb18fe7fda7ULL, 0x00606dafbf34440aULL, + 0x005d37a86399c789ULL, 0x00e79a2a69417403ULL, + 0x00fe34f7e68b8866ULL, 0x0011f448ed2df10eULL)}, + {FIELD_LITERAL(0x00f1f57efcc1fcc4ULL, 0x00513679117de154ULL, + 0x002e5b5b7c86d8c3ULL, 0x009f6486561f9cfbULL, + 0x00169e74b0170cf7ULL, 0x00900205af4af696ULL, + 0x006acfddb77853f3ULL, 0x00df184c90f31068ULL)}, + }}, {{ + {FIELD_LITERAL(0x00b37396c3320791ULL, 0x00fc7b67175c5783ULL, + 0x00c36d2cd73ecc38ULL, 0x0080ebcc0b328fc5ULL, + 0x0043a5b22b35d35dULL, 0x00466c9f1713c9daULL, + 0x0026ad346dcaa8daULL, 0x007c684e701183a6ULL)}, + {FIELD_LITERAL(0x00fd579ffb691713ULL, 0x00b76af4f81c412dULL, + 0x00f239de96110f82ULL, 0x00e965fb437f0306ULL, + 0x00ca7e9436900921ULL, 0x00e487f1325fa24aULL, + 0x00633907de476380ULL, 0x00721c62ac5b8ea0ULL)}, + {FIELD_LITERAL(0x00c0d54e542eb4f9ULL, 0x004ed657171c8dcfULL, + 0x00b743a4f7c2a39bULL, 0x00fd9f93ed6cc567ULL, + 0x00307fae3113e58bULL, 0x0058aa577c93c319ULL, + 0x00d254556f35b346ULL, 0x00491aada2203f0dULL)}, + }}, {{ + {FIELD_LITERAL(0x00dff3103786ff34ULL, 0x000144553b1f20c3ULL, + 0x0095613baeb930e4ULL, 0x00098058275ea5d4ULL, + 0x007cd1402b046756ULL, 0x0074d74e4d58aee3ULL, + 0x005f93fc343ff69bULL, 0x00873df17296b3b0ULL)}, + {FIELD_LITERAL(0x00c4a1fb48635413ULL, 0x00b5dd54423ad59fULL, + 0x009ff5d53fd24a88ULL, 0x003c98d267fc06a7ULL, + 0x002db7cb20013641ULL, 0x00bd1d6716e191f2ULL, + 0x006dbc8b29094241ULL, 0x0044bbf233dafa2cULL)}, + {FIELD_LITERAL(0x0055838d41f531e6ULL, 0x00bf6a2dd03c81b2ULL, + 0x005827a061c4839eULL, 0x0000de2cbb36aac3ULL, + 0x002efa29d9717478ULL, 0x00f9e928cc8a77baULL, + 0x00c134b458def9efULL, 0x00958a182223fc48ULL)}, + }}, {{ + {FIELD_LITERAL(0x000a9ee23c06881fULL, 0x002c727d3d871945ULL, + 0x00f47d971512d24aULL, 0x00671e816f9ef31aULL, + 0x00883af2cfaad673ULL, 0x00601f98583d6c9aULL, + 0x00b435f5adc79655ULL, 0x00ad87b71c04bff2ULL)}, + {FIELD_LITERAL(0x007860d99db787cfULL, 0x00fda8983018f4a8ULL, + 0x008c8866bac4743cULL, 0x00ef471f84c82a3fULL, + 0x00abea5976d3b8e7ULL, 0x00714882896cd015ULL, + 0x00b49fae584ddac5ULL, 0x008e33a1a0b69c81ULL)}, + {FIELD_LITERAL(0x007b6ee2c9e8a9ecULL, 0x002455dbbd89d622ULL, + 0x006490cf4eaab038ULL, 0x00d925f6c3081561ULL, + 0x00153b3047de7382ULL, 0x003b421f8bdceb6fULL, + 0x00761a4a5049da78ULL, 0x00980348c5202433ULL)}, + }}, {{ + {FIELD_LITERAL(0x007f8a43da97dd5cULL, 0x00058539c800fc7bULL, + 0x0040f3cf5a28414aULL, 0x00d68dd0d95283d6ULL, + 0x004adce9da90146eULL, 0x00befa41c7d4f908ULL, + 0x007603bc2e3c3060ULL, 0x00bdf360ab3545dbULL)}, + {FIELD_LITERAL(0x00eebfd4e2312cc3ULL, 0x00474b2564e4fc8cULL, + 0x003303ef14b1da9bULL, 0x003c93e0e66beb1dULL, + 0x0013619b0566925aULL, 0x008817c24d901bf3ULL, + 0x00b62bd8898d218bULL, 0x0075a7716f1e88a2ULL)}, + {FIELD_LITERAL(0x0009218da1e6890fULL, 0x0026907f5fd02575ULL, + 0x004dabed5f19d605ULL, 0x003abf181870249dULL, + 0x00b52fd048cc92c4ULL, 0x00b6dd51e415a5c5ULL, + 0x00d9eb82bd2b4014ULL, 0x002c865a43b46b43ULL)}, + }}, {{ + {FIELD_LITERAL(0x0070047189452f4cULL, 0x00f7ad12e1ce78d5ULL, + 0x00af1ba51ec44a8bULL, 0x005f39f63e667cd6ULL, + 0x00058eac4648425eULL, 0x00d7fdab42bea03bULL, + 0x0028576a5688de15ULL, 0x00af973209e77c10ULL)}, + {FIELD_LITERAL(0x00c338b915d8fef0ULL, 0x00a893292045c39aULL, + 0x0028ab4f2eba6887ULL, 0x0060743cb519fd61ULL, + 0x0006213964093ac0ULL, 0x007c0b7a43f6266dULL, + 0x008e3557c4fa5bdaULL, 0x002da976de7b8d9dULL)}, + {FIELD_LITERAL(0x0048729f8a8b6dcdULL, 0x00fe23b85cc4d323ULL, + 0x00e7384d16e4db0eULL, 0x004a423970678942ULL, + 0x00ec0b763345d4baULL, 0x00c477b9f99ed721ULL, + 0x00c29dad3777b230ULL, 0x001c517b466f7df6ULL)}, + }}, {{ + {FIELD_LITERAL(0x006366c380f7b574ULL, 0x001c7d1f09ff0438ULL, + 0x003e20a7301f5b22ULL, 0x00d3efb1916d28f6ULL, + 0x0049f4f81060ce83ULL, 0x00c69d91ea43ced1ULL, + 0x002b6f3e5cd269edULL, 0x005b0fb22ce9ec65ULL)}, + {FIELD_LITERAL(0x00aa2261022d883fULL, 0x00ebcca4548010acULL, + 0x002528512e28a437ULL, 0x0070ca7676b66082ULL, + 0x0084bda170f7c6d3ULL, 0x00581b4747c9b8bbULL, + 0x005c96a01061c7e2ULL, 0x00fb7c4a362b5273ULL)}, + {FIELD_LITERAL(0x00c30020eb512d02ULL, 0x0060f288283a4d26ULL, + 0x00b7ed13becde260ULL, 0x0075ebb74220f6e9ULL, + 0x00701079fcfe8a1fULL, 0x001c28fcdff58938ULL, + 0x002e4544b8f4df6bULL, 0x0060c5bc4f1a7d73ULL)}, + }}, {{ + {FIELD_LITERAL(0x00ae307cf069f701ULL, 0x005859f222dd618bULL, + 0x00212d6c46ec0b0dULL, 0x00a0fe4642afb62dULL, + 0x00420d8e4a0a8903ULL, 0x00a80ff639bdf7b0ULL, + 0x0019bee1490b5d8eULL, 0x007439e4b9c27a86ULL)}, + {FIELD_LITERAL(0x00a94700032a093fULL, 0x0076e96c225216e7ULL, + 0x00a63a4316e45f91ULL, 0x007d8bbb4645d3b2ULL, + 0x00340a6ff22793ebULL, 0x006f935d4572aeb7ULL, + 0x00b1fb69f00afa28ULL, 0x009e8f3423161ed3ULL)}, + {FIELD_LITERAL(0x009ef49c6b5ced17ULL, 0x00a555e6269e9f0aULL, + 0x007e6f1d79ec73b5ULL, 0x009ac78695a32ac4ULL, + 0x0001d77fbbcd5682ULL, 0x008cea1fee0aaeedULL, + 0x00f42bea82a53462ULL, 0x002e46ab96cafcc9ULL)}, + }}, {{ + {FIELD_LITERAL(0x0051cfcc5885377aULL, 0x00dce566cb1803caULL, + 0x00430c7643f2c7d4ULL, 0x00dce1a1337bdcc0ULL, + 0x0010d5bd7283c128ULL, 0x003b1b547f9b46feULL, + 0x000f245e37e770abULL, 0x007b72511f022b37ULL)}, + {FIELD_LITERAL(0x0060db815bc4786cULL, 0x006fab25beedc434ULL, + 0x00c610d06084797cULL, 0x000c48f08537bec0ULL, + 0x0031aba51c5b93daULL, 0x007968fa6e01f347ULL, + 0x0030070da52840c6ULL, 0x00c043c225a4837fULL)}, + {FIELD_LITERAL(0x001bcfd00649ee93ULL, 0x006dceb47e2a0fd5ULL, + 0x00f2cebda0cf8fd0ULL, 0x00b6b9d9d1fbdec3ULL, + 0x00815262e6490611ULL, 0x00ef7f5ce3176760ULL, + 0x00e49cd0c998d58bULL, 0x005fc6cc269ba57cULL)}, + }}, {{ + {FIELD_LITERAL(0x008940211aa0d633ULL, 0x00addae28136571dULL, + 0x00d68fdbba20d673ULL, 0x003bc6129bc9e21aULL, + 0x000346cf184ebe9aULL, 0x0068774d741ebc7fULL, + 0x0019d5e9e6966557ULL, 0x0003cbd7f981b651ULL)}, + {FIELD_LITERAL(0x004a2902926f8d3fULL, 0x00ad79b42637ab75ULL, + 0x0088f60b90f2d4e8ULL, 0x0030f54ef0e398c4ULL, + 0x00021dc9bf99681eULL, 0x007ebf66fde74ee3ULL, + 0x004ade654386e9a4ULL, 0x00e7485066be4c27ULL)}, + {FIELD_LITERAL(0x00445f1263983be0ULL, 0x004cf371dda45e6aULL, + 0x00744a89d5a310e7ULL, 0x001f20ce4f904833ULL, + 0x00e746edebe66e29ULL, 0x000912ab1f6c153dULL, + 0x00f61d77d9b2444cULL, 0x0001499cd6647610ULL)}, }} } }; @@ -345,133 +1065,421 @@ const struct curve448_precomputed_s *curve448_precomputed_base static const niels_t curve448_wnaf_base_table[32] = { {{ - {FIELD_LITERAL(0x00303cda6feea532,0x00860f1d5a3850e4,0x00226b9fa4728ccd,0x00e822938a0a0c0c,0x00263a61c9ea9216,0x001204029321b828,0x006a468360983c65,0x0002846f0a782143)}, - {FIELD_LITERAL(0x00303cda6feea532,0x00860f1d5a3850e4,0x00226b9fa4728ccd,0x006822938a0a0c0c,0x00263a61c9ea9215,0x001204029321b828,0x006a468360983c65,0x0082846f0a782143)}, - {FIELD_LITERAL(0x00ef8e22b275198d,0x00b0eb141a0b0e8b,0x001f6789da3cb38c,0x006d2ff8ed39073e,0x00610bdb69a167f3,0x00571f306c9689b4,0x00f557e6f84b2df8,0x002affd38b2c86db)}, + {FIELD_LITERAL(0x00303cda6feea532ULL, 0x00860f1d5a3850e4ULL, + 0x00226b9fa4728ccdULL, 0x00e822938a0a0c0cULL, + 0x00263a61c9ea9216ULL, 0x001204029321b828ULL, + 0x006a468360983c65ULL, 0x0002846f0a782143ULL)}, + {FIELD_LITERAL(0x00303cda6feea532ULL, 0x00860f1d5a3850e4ULL, + 0x00226b9fa4728ccdULL, 0x006822938a0a0c0cULL, + 0x00263a61c9ea9215ULL, 0x001204029321b828ULL, + 0x006a468360983c65ULL, 0x0082846f0a782143ULL)}, + {FIELD_LITERAL(0x00ef8e22b275198dULL, 0x00b0eb141a0b0e8bULL, + 0x001f6789da3cb38cULL, 0x006d2ff8ed39073eULL, + 0x00610bdb69a167f3ULL, 0x00571f306c9689b4ULL, + 0x00f557e6f84b2df8ULL, 0x002affd38b2c86dbULL)}, }}, {{ - {FIELD_LITERAL(0x00cea0fc8d2e88b5,0x00821612d69f1862,0x0074c283b3e67522,0x005a195ba05a876d,0x000cddfe557feea4,0x008046c795bcc5e5,0x00540969f4d6e119,0x00d27f96d6b143d5)}, - {FIELD_LITERAL(0x000c3b1019d474e8,0x00e19533e4952284,0x00cc9810ba7c920a,0x00f103d2785945ac,0x00bfa5696cc69b34,0x00a8d3d51e9ca839,0x005623cb459586b9,0x00eae7ce1cd52e9e)}, - {FIELD_LITERAL(0x0005a178751dd7d8,0x002cc3844c69c42f,0x00acbfe5efe10539,0x009c20f43431a65a,0x008435d96374a7b3,0x009ee57566877bd3,0x0044691725ed4757,0x001e87bb2fe2c6b2)}, + {FIELD_LITERAL(0x00cea0fc8d2e88b5ULL, 0x00821612d69f1862ULL, + 0x0074c283b3e67522ULL, 0x005a195ba05a876dULL, + 0x000cddfe557feea4ULL, 0x008046c795bcc5e5ULL, + 0x00540969f4d6e119ULL, 0x00d27f96d6b143d5ULL)}, + {FIELD_LITERAL(0x000c3b1019d474e8ULL, 0x00e19533e4952284ULL, + 0x00cc9810ba7c920aULL, 0x00f103d2785945acULL, + 0x00bfa5696cc69b34ULL, 0x00a8d3d51e9ca839ULL, + 0x005623cb459586b9ULL, 0x00eae7ce1cd52e9eULL)}, + {FIELD_LITERAL(0x0005a178751dd7d8ULL, 0x002cc3844c69c42fULL, + 0x00acbfe5efe10539ULL, 0x009c20f43431a65aULL, + 0x008435d96374a7b3ULL, 0x009ee57566877bd3ULL, + 0x0044691725ed4757ULL, 0x001e87bb2fe2c6b2ULL)}, }}, {{ - {FIELD_LITERAL(0x000cedc4debf7a04,0x002ffa45000470ac,0x002e9f9678201915,0x0017da1208c4fe72,0x007d558cc7d656cb,0x0037a827287cf289,0x00142472d3441819,0x009c21f166cf8dd1)}, - {FIELD_LITERAL(0x003ef83af164b2f2,0x000949a5a0525d0d,0x00f4498186cac051,0x00e77ac09ef126d2,0x0073ae0b2c9296e9,0x001c163f6922e3ed,0x0062946159321bea,0x00cfb79b22990b39)}, - {FIELD_LITERAL(0x00b001431ca9e654,0x002d7e5eabcc9a3a,0x0052e8114c2f6747,0x0079ac4f94487f92,0x00bffd919b5d749c,0x00261f92ad15e620,0x00718397b7a97895,0x00c1443e6ebbc0c4)}, + {FIELD_LITERAL(0x000cedc4debf7a04ULL, 0x002ffa45000470acULL, + 0x002e9f9678201915ULL, 0x0017da1208c4fe72ULL, + 0x007d558cc7d656cbULL, 0x0037a827287cf289ULL, + 0x00142472d3441819ULL, 0x009c21f166cf8dd1ULL)}, + {FIELD_LITERAL(0x003ef83af164b2f2ULL, 0x000949a5a0525d0dULL, + 0x00f4498186cac051ULL, 0x00e77ac09ef126d2ULL, + 0x0073ae0b2c9296e9ULL, 0x001c163f6922e3edULL, + 0x0062946159321beaULL, 0x00cfb79b22990b39ULL)}, + {FIELD_LITERAL(0x00b001431ca9e654ULL, 0x002d7e5eabcc9a3aULL, + 0x0052e8114c2f6747ULL, 0x0079ac4f94487f92ULL, + 0x00bffd919b5d749cULL, 0x00261f92ad15e620ULL, + 0x00718397b7a97895ULL, 0x00c1443e6ebbc0c4ULL)}, }}, {{ - {FIELD_LITERAL(0x00eacd90c1e0a049,0x008977935b149fbe,0x0004cb9ba11c93dc,0x009fbd5b3470844d,0x004bc18c9bfc22cf,0x0057679a991839f3,0x00ef15b76fb4092e,0x0074a5173a225041)}, - {FIELD_LITERAL(0x003f5f9d7ec4777b,0x00ab2e733c919c94,0x001bb6c035245ae5,0x00a325a49a883630,0x0033e9a9ea3cea2f,0x00e442a1eaa0e844,0x00b2116d5b0e71b8,0x00c16abed6d64047)}, - {FIELD_LITERAL(0x00c560b5ed051165,0x001945adc5d65094,0x00e221865710f910,0x00cc12bc9e9b8ceb,0x004faa9518914e35,0x0017476d89d42f6d,0x00b8f637c8fa1c8b,0x0088c7d2790864b8)}, + {FIELD_LITERAL(0x00eacd90c1e0a049ULL, 0x008977935b149fbeULL, + 0x0004cb9ba11c93dcULL, 0x009fbd5b3470844dULL, + 0x004bc18c9bfc22cfULL, 0x0057679a991839f3ULL, + 0x00ef15b76fb4092eULL, 0x0074a5173a225041ULL)}, + {FIELD_LITERAL(0x003f5f9d7ec4777bULL, 0x00ab2e733c919c94ULL, + 0x001bb6c035245ae5ULL, 0x00a325a49a883630ULL, + 0x0033e9a9ea3cea2fULL, 0x00e442a1eaa0e844ULL, + 0x00b2116d5b0e71b8ULL, 0x00c16abed6d64047ULL)}, + {FIELD_LITERAL(0x00c560b5ed051165ULL, 0x001945adc5d65094ULL, + 0x00e221865710f910ULL, 0x00cc12bc9e9b8cebULL, + 0x004faa9518914e35ULL, 0x0017476d89d42f6dULL, + 0x00b8f637c8fa1c8bULL, 0x0088c7d2790864b8ULL)}, }}, {{ - {FIELD_LITERAL(0x00ef7eafc1c69be6,0x0085d3855778fbea,0x002c8d5b450cb6f5,0x004e77de5e1e7fec,0x0047c057893abded,0x001b430b85d51e16,0x00965c7b45640c3c,0x00487b2bb1162b97)}, - {FIELD_LITERAL(0x0099c73a311beec2,0x00a3eff38d8912ad,0x002efa9d1d7e8972,0x00f717ae1e14d126,0x002833f795850c8b,0x0066c12ad71486bd,0x00ae9889da4820eb,0x00d6044309555c08)}, - {FIELD_LITERAL(0x004b1c5283d15e41,0x00669d8ea308ff75,0x0004390233f762a1,0x00e1d67b83cb6cec,0x003eebaa964c78b1,0x006b0aff965eb664,0x00b313d4470bdc37,0x008814ffcb3cb9d8)}, + {FIELD_LITERAL(0x00ef7eafc1c69be6ULL, 0x0085d3855778fbeaULL, + 0x002c8d5b450cb6f5ULL, 0x004e77de5e1e7fecULL, + 0x0047c057893abdedULL, 0x001b430b85d51e16ULL, + 0x00965c7b45640c3cULL, 0x00487b2bb1162b97ULL)}, + {FIELD_LITERAL(0x0099c73a311beec2ULL, 0x00a3eff38d8912adULL, + 0x002efa9d1d7e8972ULL, 0x00f717ae1e14d126ULL, + 0x002833f795850c8bULL, 0x0066c12ad71486bdULL, + 0x00ae9889da4820ebULL, 0x00d6044309555c08ULL)}, + {FIELD_LITERAL(0x004b1c5283d15e41ULL, 0x00669d8ea308ff75ULL, + 0x0004390233f762a1ULL, 0x00e1d67b83cb6cecULL, + 0x003eebaa964c78b1ULL, 0x006b0aff965eb664ULL, + 0x00b313d4470bdc37ULL, 0x008814ffcb3cb9d8ULL)}, }}, {{ - {FIELD_LITERAL(0x009724b8ce68db70,0x007678b5ed006f3d,0x00bdf4b89c0abd73,0x00299748e04c7c6d,0x00ddd86492c3c977,0x00c5a7febfa30a99,0x00ed84715b4b02bb,0x00319568adf70486)}, - {FIELD_LITERAL(0x0070ff2d864de5bb,0x005a37eeb637ee95,0x0033741c258de160,0x00e6ca5cb1988f46,0x001ceabd92a24661,0x0030957bd500fe40,0x001c3362afe912c5,0x005187889f678bd2)}, - {FIELD_LITERAL(0x0086835fc62bbdc7,0x009c3516ca4910a1,0x00956c71f8d00783,0x0095c78fcf63235f,0x00fc7ff6ba05c222,0x00cdd8b3f8d74a52,0x00ac5ae16de8256e,0x00e9d4be8ed48624)}, + {FIELD_LITERAL(0x009724b8ce68db70ULL, 0x007678b5ed006f3dULL, + 0x00bdf4b89c0abd73ULL, 0x00299748e04c7c6dULL, + 0x00ddd86492c3c977ULL, 0x00c5a7febfa30a99ULL, + 0x00ed84715b4b02bbULL, 0x00319568adf70486ULL)}, + {FIELD_LITERAL(0x0070ff2d864de5bbULL, 0x005a37eeb637ee95ULL, + 0x0033741c258de160ULL, 0x00e6ca5cb1988f46ULL, + 0x001ceabd92a24661ULL, 0x0030957bd500fe40ULL, + 0x001c3362afe912c5ULL, 0x005187889f678bd2ULL)}, + {FIELD_LITERAL(0x0086835fc62bbdc7ULL, 0x009c3516ca4910a1ULL, + 0x00956c71f8d00783ULL, 0x0095c78fcf63235fULL, + 0x00fc7ff6ba05c222ULL, 0x00cdd8b3f8d74a52ULL, + 0x00ac5ae16de8256eULL, 0x00e9d4be8ed48624ULL)}, }}, {{ - {FIELD_LITERAL(0x00c0ce11405df2d8,0x004e3f37b293d7b6,0x002410172e1ac6db,0x00b8dbff4bf8143d,0x003a7b409d56eb66,0x003e0f6a0dfef9af,0x0081c4e4d3645be1,0x00ce76076b127623)}, - {FIELD_LITERAL(0x00f6ee0f98974239,0x0042d89af07d3a4f,0x00846b7fe84346b5,0x006a21fc6a8d39a1,0x00ac8bc2541ff2d9,0x006d4e2a77732732,0x009a39b694cc3f2f,0x0085c0aa2a404c8f)}, - {FIELD_LITERAL(0x00b261101a218548,0x00c1cae96424277b,0x00869da0a77dd268,0x00bc0b09f8ec83ea,0x00d61027f8e82ba9,0x00aa4c85999dce67,0x00eac3132b9f3fe1,0x00fb9b0cf1c695d2)}, + {FIELD_LITERAL(0x00c0ce11405df2d8ULL, 0x004e3f37b293d7b6ULL, + 0x002410172e1ac6dbULL, 0x00b8dbff4bf8143dULL, + 0x003a7b409d56eb66ULL, 0x003e0f6a0dfef9afULL, + 0x0081c4e4d3645be1ULL, 0x00ce76076b127623ULL)}, + {FIELD_LITERAL(0x00f6ee0f98974239ULL, 0x0042d89af07d3a4fULL, + 0x00846b7fe84346b5ULL, 0x006a21fc6a8d39a1ULL, + 0x00ac8bc2541ff2d9ULL, 0x006d4e2a77732732ULL, + 0x009a39b694cc3f2fULL, 0x0085c0aa2a404c8fULL)}, + {FIELD_LITERAL(0x00b261101a218548ULL, 0x00c1cae96424277bULL, + 0x00869da0a77dd268ULL, 0x00bc0b09f8ec83eaULL, + 0x00d61027f8e82ba9ULL, 0x00aa4c85999dce67ULL, + 0x00eac3132b9f3fe1ULL, 0x00fb9b0cf1c695d2ULL)}, }}, {{ - {FIELD_LITERAL(0x0043079295512f0d,0x0046a009861758e0,0x003ee2842a807378,0x0034cc9d1298e4fa,0x009744eb4d31b3ee,0x00afacec96650cd0,0x00ac891b313761ae,0x00e864d6d26e708a)}, - {FIELD_LITERAL(0x00a84d7c8a23b491,0x0088e19aa868b27f,0x0005986d43e78ce9,0x00f28012f0606d28,0x0017ded7e10249b3,0x005ed4084b23af9b,0x00b9b0a940564472,0x00ad9056cceeb1f4)}, - {FIELD_LITERAL(0x00db91b357fe755e,0x00a1aa544b15359c,0x00af4931a0195574,0x007686124fe11aef,0x00d1ead3c7b9ef7e,0x00aaf5fc580f8c15,0x00e727be147ee1ec,0x003c61c1e1577b86)}, + {FIELD_LITERAL(0x0043079295512f0dULL, 0x0046a009861758e0ULL, + 0x003ee2842a807378ULL, 0x0034cc9d1298e4faULL, + 0x009744eb4d31b3eeULL, 0x00afacec96650cd0ULL, + 0x00ac891b313761aeULL, 0x00e864d6d26e708aULL)}, + {FIELD_LITERAL(0x00a84d7c8a23b491ULL, 0x0088e19aa868b27fULL, + 0x0005986d43e78ce9ULL, 0x00f28012f0606d28ULL, + 0x0017ded7e10249b3ULL, 0x005ed4084b23af9bULL, + 0x00b9b0a940564472ULL, 0x00ad9056cceeb1f4ULL)}, + {FIELD_LITERAL(0x00db91b357fe755eULL, 0x00a1aa544b15359cULL, + 0x00af4931a0195574ULL, 0x007686124fe11aefULL, + 0x00d1ead3c7b9ef7eULL, 0x00aaf5fc580f8c15ULL, + 0x00e727be147ee1ecULL, 0x003c61c1e1577b86ULL)}, }}, {{ - {FIELD_LITERAL(0x009d3fca983220cf,0x00cd11acbc853dc4,0x0017590409d27f1d,0x00d2176698082802,0x00fa01251b2838c8,0x00dd297a0d9b51c6,0x00d76c92c045820a,0x00534bc7c46c9033)}, - {FIELD_LITERAL(0x0080ed9bc9b07338,0x00fceac7745d2652,0x008a9d55f5f2cc69,0x0096ce72df301ac5,0x00f53232e7974d87,0x0071728c7ae73947,0x0090507602570778,0x00cb81cfd883b1b2)}, - {FIELD_LITERAL(0x005011aadea373da,0x003a8578ec896034,0x00f20a6535fa6d71,0x005152d31e5a87cf,0x002bac1c8e68ca31,0x00b0e323db4c1381,0x00f1d596b7d5ae25,0x00eae458097cb4e0)}, + {FIELD_LITERAL(0x009d3fca983220cfULL, 0x00cd11acbc853dc4ULL, + 0x0017590409d27f1dULL, 0x00d2176698082802ULL, + 0x00fa01251b2838c8ULL, 0x00dd297a0d9b51c6ULL, + 0x00d76c92c045820aULL, 0x00534bc7c46c9033ULL)}, + {FIELD_LITERAL(0x0080ed9bc9b07338ULL, 0x00fceac7745d2652ULL, + 0x008a9d55f5f2cc69ULL, 0x0096ce72df301ac5ULL, + 0x00f53232e7974d87ULL, 0x0071728c7ae73947ULL, + 0x0090507602570778ULL, 0x00cb81cfd883b1b2ULL)}, + {FIELD_LITERAL(0x005011aadea373daULL, 0x003a8578ec896034ULL, + 0x00f20a6535fa6d71ULL, 0x005152d31e5a87cfULL, + 0x002bac1c8e68ca31ULL, 0x00b0e323db4c1381ULL, + 0x00f1d596b7d5ae25ULL, 0x00eae458097cb4e0ULL)}, }}, {{ - {FIELD_LITERAL(0x00920ac80f9b0d21,0x00f80f7f73401246,0x0086d37849b557d6,0x0002bd4b317b752e,0x00b26463993a42bb,0x002070422a73b129,0x00341acaa0380cb3,0x00541914dd66a1b2)}, - {FIELD_LITERAL(0x00c1513cd66abe8c,0x000139e01118944d,0x0064abbcb8080bbb,0x00b3b08202473142,0x00c629ef25da2403,0x00f0aec3310d9b7f,0x0050b2227472d8cd,0x00f6c8a922d41fb4)}, - {FIELD_LITERAL(0x001075ccf26b7b1f,0x00bb6bb213170433,0x00e9491ad262da79,0x009ef4f48d2d384c,0x008992770766f09d,0x001584396b6b1101,0x00af3f8676c9feef,0x0024603c40269118)}, + {FIELD_LITERAL(0x00920ac80f9b0d21ULL, 0x00f80f7f73401246ULL, + 0x0086d37849b557d6ULL, 0x0002bd4b317b752eULL, + 0x00b26463993a42bbULL, 0x002070422a73b129ULL, + 0x00341acaa0380cb3ULL, 0x00541914dd66a1b2ULL)}, + {FIELD_LITERAL(0x00c1513cd66abe8cULL, 0x000139e01118944dULL, + 0x0064abbcb8080bbbULL, 0x00b3b08202473142ULL, + 0x00c629ef25da2403ULL, 0x00f0aec3310d9b7fULL, + 0x0050b2227472d8cdULL, 0x00f6c8a922d41fb4ULL)}, + {FIELD_LITERAL(0x001075ccf26b7b1fULL, 0x00bb6bb213170433ULL, + 0x00e9491ad262da79ULL, 0x009ef4f48d2d384cULL, + 0x008992770766f09dULL, 0x001584396b6b1101ULL, + 0x00af3f8676c9feefULL, 0x0024603c40269118ULL)}, }}, {{ - {FIELD_LITERAL(0x009dd7b31319527c,0x001e7ac948d873a9,0x00fa54b46ef9673a,0x0066efb8d5b02fe6,0x00754b1d3928aeae,0x0004262ac72a6f6b,0x0079b7d49a6eb026,0x003126a753540102)}, - {FIELD_LITERAL(0x009666e24f693947,0x00f714311269d45f,0x0010ffac1d0c851c,0x0066e80c37363497,0x00f1f4ad010c60b0,0x0015c87408470ff7,0x00651d5e9c7766a4,0x008138819d7116de)}, - {FIELD_LITERAL(0x003934b11c57253b,0x00ef308edf21f46e,0x00e54e99c7a16198,0x0080d57135764e63,0x00751c27b946bc24,0x00dd389ce4e9e129,0x00a1a2bfd1cd84dc,0x002fae73e5149b32)}, + {FIELD_LITERAL(0x009dd7b31319527cULL, 0x001e7ac948d873a9ULL, + 0x00fa54b46ef9673aULL, 0x0066efb8d5b02fe6ULL, + 0x00754b1d3928aeaeULL, 0x0004262ac72a6f6bULL, + 0x0079b7d49a6eb026ULL, 0x003126a753540102ULL)}, + {FIELD_LITERAL(0x009666e24f693947ULL, 0x00f714311269d45fULL, + 0x0010ffac1d0c851cULL, 0x0066e80c37363497ULL, + 0x00f1f4ad010c60b0ULL, 0x0015c87408470ff7ULL, + 0x00651d5e9c7766a4ULL, 0x008138819d7116deULL)}, + {FIELD_LITERAL(0x003934b11c57253bULL, 0x00ef308edf21f46eULL, + 0x00e54e99c7a16198ULL, 0x0080d57135764e63ULL, + 0x00751c27b946bc24ULL, 0x00dd389ce4e9e129ULL, + 0x00a1a2bfd1cd84dcULL, 0x002fae73e5149b32ULL)}, }}, {{ - {FIELD_LITERAL(0x00911657dffb4cdd,0x00c100b7cc553d06,0x00449d075ec467cc,0x007062100bc64e70,0x0043cf86f7bd21e7,0x00f401dc4b797dea,0x005224afb2f62e65,0x00d1ede3fb5a42be)}, - {FIELD_LITERAL(0x00f2ba36a41aa144,0x00a0c22d946ee18f,0x008aae8ef9a14f99,0x00eef4d79b19bb36,0x008e75ce3d27b1fc,0x00a65daa03b29a27,0x00d9cc83684eb145,0x009e1ed80cc2ed74)}, - {FIELD_LITERAL(0x00bed953d1997988,0x00b93ed175a24128,0x00871c5963fb6365,0x00ca2df20014a787,0x00f5d9c1d0b34322,0x00f6f5942818db0a,0x004cc091f49c9906,0x00e8a188a60bff9f)}, + {FIELD_LITERAL(0x00911657dffb4cddULL, 0x00c100b7cc553d06ULL, + 0x00449d075ec467ccULL, 0x007062100bc64e70ULL, + 0x0043cf86f7bd21e7ULL, 0x00f401dc4b797deaULL, + 0x005224afb2f62e65ULL, 0x00d1ede3fb5a42beULL)}, + {FIELD_LITERAL(0x00f2ba36a41aa144ULL, 0x00a0c22d946ee18fULL, + 0x008aae8ef9a14f99ULL, 0x00eef4d79b19bb36ULL, + 0x008e75ce3d27b1fcULL, 0x00a65daa03b29a27ULL, + 0x00d9cc83684eb145ULL, 0x009e1ed80cc2ed74ULL)}, + {FIELD_LITERAL(0x00bed953d1997988ULL, 0x00b93ed175a24128ULL, + 0x00871c5963fb6365ULL, 0x00ca2df20014a787ULL, + 0x00f5d9c1d0b34322ULL, 0x00f6f5942818db0aULL, + 0x004cc091f49c9906ULL, 0x00e8a188a60bff9fULL)}, }}, {{ - {FIELD_LITERAL(0x0032c7762032fae8,0x00e4087232e0bc21,0x00f767344b6e8d85,0x00bbf369b76c2aa2,0x008a1f46c6e1570c,0x001368cd9780369f,0x007359a39d079430,0x0003646512921434)}, - {FIELD_LITERAL(0x007c4b47ca7c73e7,0x005396221039734b,0x008b64ddf0e45d7e,0x00bfad5af285e6c2,0x008ec711c5b1a1a8,0x00cf663301237f98,0x00917ee3f1655126,0x004152f337efedd8)}, - {FIELD_LITERAL(0x0007c7edc9305daa,0x000a6664f273701c,0x00f6e78795e200b1,0x005d05b9ecd2473e,0x0014f5f17c865786,0x00c7fd2d166fa995,0x004939a2d8eb80e0,0x002244ba0942c199)}, + {FIELD_LITERAL(0x0032c7762032fae8ULL, 0x00e4087232e0bc21ULL, + 0x00f767344b6e8d85ULL, 0x00bbf369b76c2aa2ULL, + 0x008a1f46c6e1570cULL, 0x001368cd9780369fULL, + 0x007359a39d079430ULL, 0x0003646512921434ULL)}, + {FIELD_LITERAL(0x007c4b47ca7c73e7ULL, 0x005396221039734bULL, + 0x008b64ddf0e45d7eULL, 0x00bfad5af285e6c2ULL, + 0x008ec711c5b1a1a8ULL, 0x00cf663301237f98ULL, + 0x00917ee3f1655126ULL, 0x004152f337efedd8ULL)}, + {FIELD_LITERAL(0x0007c7edc9305daaULL, 0x000a6664f273701cULL, + 0x00f6e78795e200b1ULL, 0x005d05b9ecd2473eULL, + 0x0014f5f17c865786ULL, 0x00c7fd2d166fa995ULL, + 0x004939a2d8eb80e0ULL, 0x002244ba0942c199ULL)}, }}, {{ - {FIELD_LITERAL(0x00321e767f0262cf,0x002e57d776caf68e,0x00bf2c94814f0437,0x00c339196acd622f,0x001db4cce71e2770,0x001ded5ddba6eee2,0x0078608ab1554c8d,0x00067fe0ab76365b)}, - {FIELD_LITERAL(0x00f09758e11e3985,0x00169efdbd64fad3,0x00e8889b7d6dacd6,0x0035cdd58ea88209,0x00bcda47586d7f49,0x003cdddcb2879088,0x0016da70187e954b,0x009556ea2e92aacd)}, - {FIELD_LITERAL(0x008cab16bd1ff897,0x00b389972cdf753f,0x00ea8ed1e46dfdc0,0x004fe7ef94c589f4,0x002b8ae9b805ecf3,0x0025c08d892874a5,0x0023938e98d44c4c,0x00f759134cabf69c)}, + {FIELD_LITERAL(0x00321e767f0262cfULL, 0x002e57d776caf68eULL, + 0x00bf2c94814f0437ULL, 0x00c339196acd622fULL, + 0x001db4cce71e2770ULL, 0x001ded5ddba6eee2ULL, + 0x0078608ab1554c8dULL, 0x00067fe0ab76365bULL)}, + {FIELD_LITERAL(0x00f09758e11e3985ULL, 0x00169efdbd64fad3ULL, + 0x00e8889b7d6dacd6ULL, 0x0035cdd58ea88209ULL, + 0x00bcda47586d7f49ULL, 0x003cdddcb2879088ULL, + 0x0016da70187e954bULL, 0x009556ea2e92aacdULL)}, + {FIELD_LITERAL(0x008cab16bd1ff897ULL, 0x00b389972cdf753fULL, + 0x00ea8ed1e46dfdc0ULL, 0x004fe7ef94c589f4ULL, + 0x002b8ae9b805ecf3ULL, 0x0025c08d892874a5ULL, + 0x0023938e98d44c4cULL, 0x00f759134cabf69cULL)}, }}, {{ - {FIELD_LITERAL(0x006c2a84678e4b3b,0x007a194aacd1868f,0x00ed0225af424761,0x00da0a6f293c64b8,0x001062ac5c6a7a18,0x0030f5775a8aeef4,0x0002acaad76b7af0,0x00410b8fd63a579f)}, - {FIELD_LITERAL(0x001ec59db3d9590e,0x001e9e3f1c3f182d,0x0045a9c3ec2cab14,0x0008198572aeb673,0x00773b74068bd167,0x0012535eaa395434,0x0044dba9e3bbb74a,0x002fba4d3c74bd0e)}, - {FIELD_LITERAL(0x0042bf08fe66922c,0x003318b8fbb49e8c,0x00d75946004aa14c,0x00f601586b42bf1c,0x00c74cf1d912fe66,0x00abcb36974b30ad,0x007eb78720c9d2b8,0x009f54ab7bd4df85)}, + {FIELD_LITERAL(0x006c2a84678e4b3bULL, 0x007a194aacd1868fULL, + 0x00ed0225af424761ULL, 0x00da0a6f293c64b8ULL, + 0x001062ac5c6a7a18ULL, 0x0030f5775a8aeef4ULL, + 0x0002acaad76b7af0ULL, 0x00410b8fd63a579fULL)}, + {FIELD_LITERAL(0x001ec59db3d9590eULL, 0x001e9e3f1c3f182dULL, + 0x0045a9c3ec2cab14ULL, 0x0008198572aeb673ULL, + 0x00773b74068bd167ULL, 0x0012535eaa395434ULL, + 0x0044dba9e3bbb74aULL, 0x002fba4d3c74bd0eULL)}, + {FIELD_LITERAL(0x0042bf08fe66922cULL, 0x003318b8fbb49e8cULL, + 0x00d75946004aa14cULL, 0x00f601586b42bf1cULL, + 0x00c74cf1d912fe66ULL, 0x00abcb36974b30adULL, + 0x007eb78720c9d2b8ULL, 0x009f54ab7bd4df85ULL)}, }}, {{ - {FIELD_LITERAL(0x00db9fc948f73826,0x00fa8b3746ed8ee9,0x00132cb65aafbeb2,0x00c36ff3fe7925b8,0x00837daed353d2fe,0x00ec661be0667cf4,0x005beb8ed2e90204,0x00d77dd69e564967)}, - {FIELD_LITERAL(0x0042e6268b861751,0x0008dd0469500c16,0x00b51b57c338a3fd,0x00cc4497d85cff6b,0x002f13d6b57c34a4,0x0083652eaf301105,0x00cc344294cc93a8,0x0060f4d02810e270)}, - {FIELD_LITERAL(0x00a8954363cd518b,0x00ad171124bccb7b,0x0065f46a4adaae00,0x001b1a5b2a96e500,0x0043fe24f8233285,0x0066996d8ae1f2c3,0x00c530f3264169f9,0x00c0f92d07cf6a57)}, + {FIELD_LITERAL(0x00db9fc948f73826ULL, 0x00fa8b3746ed8ee9ULL, + 0x00132cb65aafbeb2ULL, 0x00c36ff3fe7925b8ULL, + 0x00837daed353d2feULL, 0x00ec661be0667cf4ULL, + 0x005beb8ed2e90204ULL, 0x00d77dd69e564967ULL)}, + {FIELD_LITERAL(0x0042e6268b861751ULL, 0x0008dd0469500c16ULL, + 0x00b51b57c338a3fdULL, 0x00cc4497d85cff6bULL, + 0x002f13d6b57c34a4ULL, 0x0083652eaf301105ULL, + 0x00cc344294cc93a8ULL, 0x0060f4d02810e270ULL)}, + {FIELD_LITERAL(0x00a8954363cd518bULL, 0x00ad171124bccb7bULL, + 0x0065f46a4adaae00ULL, 0x001b1a5b2a96e500ULL, + 0x0043fe24f8233285ULL, 0x0066996d8ae1f2c3ULL, + 0x00c530f3264169f9ULL, 0x00c0f92d07cf6a57ULL)}, }}, {{ - {FIELD_LITERAL(0x0036a55c6815d943,0x008c8d1def993db3,0x002e0e1e8ff7318f,0x00d883a4b92db00a,0x002f5e781ae33906,0x001a72adb235c06d,0x00f2e59e736e9caa,0x001a4b58e3031914)}, - {FIELD_LITERAL(0x00d73bfae5e00844,0x00bf459766fb5f52,0x0061b4f5a5313cde,0x004392d4c3b95514,0x000d3551b1077523,0x0000998840ee5d71,0x006de6e340448b7b,0x00251aa504875d6e)}, - {FIELD_LITERAL(0x003bf343427ac342,0x00adc0a78642b8c5,0x0003b893175a8314,0x0061a34ade5703bc,0x00ea3ea8bb71d632,0x00be0df9a1f198c2,0x0046dd8e7c1635fb,0x00f1523fdd25d5e5)}, + {FIELD_LITERAL(0x0036a55c6815d943ULL, 0x008c8d1def993db3ULL, + 0x002e0e1e8ff7318fULL, 0x00d883a4b92db00aULL, + 0x002f5e781ae33906ULL, 0x001a72adb235c06dULL, + 0x00f2e59e736e9caaULL, 0x001a4b58e3031914ULL)}, + {FIELD_LITERAL(0x00d73bfae5e00844ULL, 0x00bf459766fb5f52ULL, + 0x0061b4f5a5313cdeULL, 0x004392d4c3b95514ULL, + 0x000d3551b1077523ULL, 0x0000998840ee5d71ULL, + 0x006de6e340448b7bULL, 0x00251aa504875d6eULL)}, + {FIELD_LITERAL(0x003bf343427ac342ULL, 0x00adc0a78642b8c5ULL, + 0x0003b893175a8314ULL, 0x0061a34ade5703bcULL, + 0x00ea3ea8bb71d632ULL, 0x00be0df9a1f198c2ULL, + 0x0046dd8e7c1635fbULL, 0x00f1523fdd25d5e5ULL)}, }}, {{ - {FIELD_LITERAL(0x00633f63fc9dd406,0x00e713ff80e04a43,0x0060c6e970f2d621,0x00a57cd7f0df1891,0x00f2406a550650bb,0x00b064290efdc684,0x001eab0144d17916,0x00cd15f863c293ab)}, - {FIELD_LITERAL(0x0029cec55273f70d,0x007044ee275c6340,0x0040f637a93015e2,0x00338bb78db5aae9,0x001491b2a6132147,0x00a125d6cfe6bde3,0x005f7ac561ba8669,0x001d5eaea3fbaacf)}, - {FIELD_LITERAL(0x00054e9635e3be31,0x000e43f31e2872be,0x00d05b1c9e339841,0x006fac50bd81fd98,0x00cdc7852eaebb09,0x004ff519b061991b,0x009099e8107d4c85,0x00273e24c36a4a61)}, + {FIELD_LITERAL(0x00633f63fc9dd406ULL, 0x00e713ff80e04a43ULL, + 0x0060c6e970f2d621ULL, 0x00a57cd7f0df1891ULL, + 0x00f2406a550650bbULL, 0x00b064290efdc684ULL, + 0x001eab0144d17916ULL, 0x00cd15f863c293abULL)}, + {FIELD_LITERAL(0x0029cec55273f70dULL, 0x007044ee275c6340ULL, + 0x0040f637a93015e2ULL, 0x00338bb78db5aae9ULL, + 0x001491b2a6132147ULL, 0x00a125d6cfe6bde3ULL, + 0x005f7ac561ba8669ULL, 0x001d5eaea3fbaacfULL)}, + {FIELD_LITERAL(0x00054e9635e3be31ULL, 0x000e43f31e2872beULL, + 0x00d05b1c9e339841ULL, 0x006fac50bd81fd98ULL, + 0x00cdc7852eaebb09ULL, 0x004ff519b061991bULL, + 0x009099e8107d4c85ULL, 0x00273e24c36a4a61ULL)}, }}, {{ - {FIELD_LITERAL(0x00070b4441ef2c46,0x00efa5b02801a109,0x00bf0b8c3ee64adf,0x008a67e0b3452e98,0x001916b1f2fa7a74,0x00d781a78ff6cdc3,0x008682ce57e5c919,0x00cc1109dd210da3)}, - {FIELD_LITERAL(0x00cae8aaff388663,0x005e983a35dda1c7,0x007ab1030d8e37f4,0x00e48940f5d032fe,0x006a36f9ef30b331,0x009be6f03958c757,0x0086231ceba91400,0x008bd0f7b823e7aa)}, - {FIELD_LITERAL(0x00cf881ebef5a45a,0x004ebea78e7c6f2c,0x0090da9209cf26a0,0x00de2b2e4c775b84,0x0071d6031c3c15ae,0x00d9e927ef177d70,0x00894ee8c23896fd,0x00e3b3b401e41aad)}, + {FIELD_LITERAL(0x00070b4441ef2c46ULL, 0x00efa5b02801a109ULL, + 0x00bf0b8c3ee64adfULL, 0x008a67e0b3452e98ULL, + 0x001916b1f2fa7a74ULL, 0x00d781a78ff6cdc3ULL, + 0x008682ce57e5c919ULL, 0x00cc1109dd210da3ULL)}, + {FIELD_LITERAL(0x00cae8aaff388663ULL, 0x005e983a35dda1c7ULL, + 0x007ab1030d8e37f4ULL, 0x00e48940f5d032feULL, + 0x006a36f9ef30b331ULL, 0x009be6f03958c757ULL, + 0x0086231ceba91400ULL, 0x008bd0f7b823e7aaULL)}, + {FIELD_LITERAL(0x00cf881ebef5a45aULL, 0x004ebea78e7c6f2cULL, + 0x0090da9209cf26a0ULL, 0x00de2b2e4c775b84ULL, + 0x0071d6031c3c15aeULL, 0x00d9e927ef177d70ULL, + 0x00894ee8c23896fdULL, 0x00e3b3b401e41aadULL)}, }}, {{ - {FIELD_LITERAL(0x00204fef26864170,0x00819269c5dee0f8,0x00bfb4713ec97966,0x0026339a6f34df78,0x001f26e64c761dc2,0x00effe3af313cb60,0x00e17b70138f601b,0x00f16e1ccd9ede5e)}, - {FIELD_LITERAL(0x005d9a8353fdb2db,0x0055cc2048c698f0,0x00f6c4ac89657218,0x00525034d73faeb2,0x00435776fbda3c7d,0x0070ea5312323cbc,0x007a105d44d069fb,0x006dbc8d6dc786aa)}, - {FIELD_LITERAL(0x0017cff19cd394ec,0x00fef7b810922587,0x00e6483970dff548,0x00ddf36ad6874264,0x00e61778523fcce2,0x0093a66c0c93b24a,0x00fd367114db7f86,0x007652d7ddce26dd)}, + {FIELD_LITERAL(0x00204fef26864170ULL, 0x00819269c5dee0f8ULL, + 0x00bfb4713ec97966ULL, 0x0026339a6f34df78ULL, + 0x001f26e64c761dc2ULL, 0x00effe3af313cb60ULL, + 0x00e17b70138f601bULL, 0x00f16e1ccd9ede5eULL)}, + {FIELD_LITERAL(0x005d9a8353fdb2dbULL, 0x0055cc2048c698f0ULL, + 0x00f6c4ac89657218ULL, 0x00525034d73faeb2ULL, + 0x00435776fbda3c7dULL, 0x0070ea5312323cbcULL, + 0x007a105d44d069fbULL, 0x006dbc8d6dc786aaULL)}, + {FIELD_LITERAL(0x0017cff19cd394ecULL, 0x00fef7b810922587ULL, + 0x00e6483970dff548ULL, 0x00ddf36ad6874264ULL, + 0x00e61778523fcce2ULL, 0x0093a66c0c93b24aULL, + 0x00fd367114db7f86ULL, 0x007652d7ddce26ddULL)}, }}, {{ - {FIELD_LITERAL(0x00d92ced7ba12843,0x00aea9c7771e86e7,0x0046639693354f7b,0x00a628dbb6a80c47,0x003a0b0507372953,0x00421113ab45c0d9,0x00e545f08362ab7a,0x0028ce087b4d6d96)}, - {FIELD_LITERAL(0x00a67ee7cf9f99eb,0x005713b275f2ff68,0x00f1d536a841513d,0x00823b59b024712e,0x009c46b9d0d38cec,0x00cdb1595aa2d7d4,0x008375b3423d9af8,0x000ab0b516d978f7)}, - {FIELD_LITERAL(0x00428dcb3c510b0f,0x00585607ea24bb4e,0x003736bf1603687a,0x00c47e568c4fe3c7,0x003cd00282848605,0x0043a487c3b91939,0x004ffc04e1095a06,0x00a4c989a3d4b918)}, + {FIELD_LITERAL(0x00d92ced7ba12843ULL, 0x00aea9c7771e86e7ULL, + 0x0046639693354f7bULL, 0x00a628dbb6a80c47ULL, + 0x003a0b0507372953ULL, 0x00421113ab45c0d9ULL, + 0x00e545f08362ab7aULL, 0x0028ce087b4d6d96ULL)}, + {FIELD_LITERAL(0x00a67ee7cf9f99ebULL, 0x005713b275f2ff68ULL, + 0x00f1d536a841513dULL, 0x00823b59b024712eULL, + 0x009c46b9d0d38cecULL, 0x00cdb1595aa2d7d4ULL, + 0x008375b3423d9af8ULL, 0x000ab0b516d978f7ULL)}, + {FIELD_LITERAL(0x00428dcb3c510b0fULL, 0x00585607ea24bb4eULL, + 0x003736bf1603687aULL, 0x00c47e568c4fe3c7ULL, + 0x003cd00282848605ULL, 0x0043a487c3b91939ULL, + 0x004ffc04e1095a06ULL, 0x00a4c989a3d4b918ULL)}, }}, {{ - {FIELD_LITERAL(0x00a8778d0e429f7a,0x004c02b059105a68,0x0016653b609da3ff,0x00d5107bd1a12d27,0x00b4708f9a771cab,0x00bb63b662033f69,0x0072f322240e7215,0x0019445b59c69222)}, - {FIELD_LITERAL(0x00cf4f6069a658e6,0x0053ca52859436a6,0x0064b994d7e3e117,0x00cb469b9a07f534,0x00cfb68f399e9d47,0x00f0dcb8dac1c6e7,0x00f2ab67f538b3a5,0x0055544f178ab975)}, - {FIELD_LITERAL(0x0099b7a2685d538c,0x00e2f1897b7c0018,0x003adac8ce48dae3,0x00089276d5c50c0c,0x00172fca07ad6717,0x00cb1a72f54069e5,0x004ee42f133545b3,0x00785f8651362f16)}, + {FIELD_LITERAL(0x00a8778d0e429f7aULL, 0x004c02b059105a68ULL, + 0x0016653b609da3ffULL, 0x00d5107bd1a12d27ULL, + 0x00b4708f9a771cabULL, 0x00bb63b662033f69ULL, + 0x0072f322240e7215ULL, 0x0019445b59c69222ULL)}, + {FIELD_LITERAL(0x00cf4f6069a658e6ULL, 0x0053ca52859436a6ULL, + 0x0064b994d7e3e117ULL, 0x00cb469b9a07f534ULL, + 0x00cfb68f399e9d47ULL, 0x00f0dcb8dac1c6e7ULL, + 0x00f2ab67f538b3a5ULL, 0x0055544f178ab975ULL)}, + {FIELD_LITERAL(0x0099b7a2685d538cULL, 0x00e2f1897b7c0018ULL, + 0x003adac8ce48dae3ULL, 0x00089276d5c50c0cULL, + 0x00172fca07ad6717ULL, 0x00cb1a72f54069e5ULL, + 0x004ee42f133545b3ULL, 0x00785f8651362f16ULL)}, }}, {{ - {FIELD_LITERAL(0x0049cbac38509e11,0x0015234505d42cdf,0x00794fb0b5840f1c,0x00496437344045a5,0x0031b6d944e4f9b0,0x00b207318ac1f5d8,0x0000c840da7f5c5d,0x00526f373a5c8814)}, - {FIELD_LITERAL(0x002c7b7742d1dfd9,0x002cabeb18623c01,0x00055f5e3e044446,0x006c20f3b4ef54ba,0x00c600141ec6b35f,0x00354f437f1a32a3,0x00bac4624a3520f9,0x00c483f734a90691)}, - {FIELD_LITERAL(0x0053a737d422918d,0x00f7fca1d8758625,0x00c360336dadb04c,0x00f38e3d9158a1b8,0x0069ce3b418e84c6,0x005d1697eca16ead,0x00f8bd6a35ece13d,0x007885dfc2b5afea)}, + {FIELD_LITERAL(0x0049cbac38509e11ULL, 0x0015234505d42cdfULL, + 0x00794fb0b5840f1cULL, 0x00496437344045a5ULL, + 0x0031b6d944e4f9b0ULL, 0x00b207318ac1f5d8ULL, + 0x0000c840da7f5c5dULL, 0x00526f373a5c8814ULL)}, + {FIELD_LITERAL(0x002c7b7742d1dfd9ULL, 0x002cabeb18623c01ULL, + 0x00055f5e3e044446ULL, 0x006c20f3b4ef54baULL, + 0x00c600141ec6b35fULL, 0x00354f437f1a32a3ULL, + 0x00bac4624a3520f9ULL, 0x00c483f734a90691ULL)}, + {FIELD_LITERAL(0x0053a737d422918dULL, 0x00f7fca1d8758625ULL, + 0x00c360336dadb04cULL, 0x00f38e3d9158a1b8ULL, + 0x0069ce3b418e84c6ULL, 0x005d1697eca16eadULL, + 0x00f8bd6a35ece13dULL, 0x007885dfc2b5afeaULL)}, }}, {{ - {FIELD_LITERAL(0x00c3617ae260776c,0x00b20dc3e96922d7,0x00a1a7802246706a,0x00ca6505a5240244,0x002246b62d919782,0x001439102d7aa9b3,0x00e8af1139e6422c,0x00c888d1b52f2b05)}, - {FIELD_LITERAL(0x005b67690ffd41d9,0x005294f28df516f9,0x00a879272412fcb9,0x00098b629a6d1c8d,0x00fabd3c8050865a,0x00cd7e5b0a3879c5,0x00153238210f3423,0x00357cac101e9f42)}, - {FIELD_LITERAL(0x008917b454444fb7,0x00f59247c97e441b,0x00a6200a6815152d,0x0009a4228601d254,0x001c0360559bd374,0x007563362039cb36,0x00bd75b48d74e32b,0x0017f515ac3499e8)}, + {FIELD_LITERAL(0x00c3617ae260776cULL, 0x00b20dc3e96922d7ULL, + 0x00a1a7802246706aULL, 0x00ca6505a5240244ULL, + 0x002246b62d919782ULL, 0x001439102d7aa9b3ULL, + 0x00e8af1139e6422cULL, 0x00c888d1b52f2b05ULL)}, + {FIELD_LITERAL(0x005b67690ffd41d9ULL, 0x005294f28df516f9ULL, + 0x00a879272412fcb9ULL, 0x00098b629a6d1c8dULL, + 0x00fabd3c8050865aULL, 0x00cd7e5b0a3879c5ULL, + 0x00153238210f3423ULL, 0x00357cac101e9f42ULL)}, + {FIELD_LITERAL(0x008917b454444fb7ULL, 0x00f59247c97e441bULL, + 0x00a6200a6815152dULL, 0x0009a4228601d254ULL, + 0x001c0360559bd374ULL, 0x007563362039cb36ULL, + 0x00bd75b48d74e32bULL, 0x0017f515ac3499e8ULL)}, }}, {{ - {FIELD_LITERAL(0x001532a7ffe41c5a,0x00eb1edce358d6bf,0x00ddbacc7b678a7b,0x008a7b70f3c841a3,0x00f1923bf27d3f4c,0x000b2713ed8f7873,0x00aaf67e29047902,0x0044994a70b3976d)}, - {FIELD_LITERAL(0x00d54e802082d42c,0x00a55aa0dce7cc6c,0x006477b96073f146,0x0082efe4ceb43594,0x00a922bcba026845,0x0077f19d1ab75182,0x00c2bb2737846e59,0x0004d7eec791dd33)}, - {FIELD_LITERAL(0x0044588d1a81d680,0x00b0a9097208e4f8,0x00212605350dc57e,0x0028717cd2871123,0x00fb083c100fd979,0x0045a056ce063fdf,0x00a5d604b4dd6a41,0x001dabc08ba4e236)}, + {FIELD_LITERAL(0x001532a7ffe41c5aULL, 0x00eb1edce358d6bfULL, + 0x00ddbacc7b678a7bULL, 0x008a7b70f3c841a3ULL, + 0x00f1923bf27d3f4cULL, 0x000b2713ed8f7873ULL, + 0x00aaf67e29047902ULL, 0x0044994a70b3976dULL)}, + {FIELD_LITERAL(0x00d54e802082d42cULL, 0x00a55aa0dce7cc6cULL, + 0x006477b96073f146ULL, 0x0082efe4ceb43594ULL, + 0x00a922bcba026845ULL, 0x0077f19d1ab75182ULL, + 0x00c2bb2737846e59ULL, 0x0004d7eec791dd33ULL)}, + {FIELD_LITERAL(0x0044588d1a81d680ULL, 0x00b0a9097208e4f8ULL, + 0x00212605350dc57eULL, 0x0028717cd2871123ULL, + 0x00fb083c100fd979ULL, 0x0045a056ce063fdfULL, + 0x00a5d604b4dd6a41ULL, 0x001dabc08ba4e236ULL)}, }}, {{ - {FIELD_LITERAL(0x00c4887198d7a7fa,0x00244f98fb45784a,0x0045911e15a15d01,0x001d323d374c0966,0x00967c3915196562,0x0039373abd2f3c67,0x000d2c5614312423,0x0041cf2215442ce3)}, - {FIELD_LITERAL(0x008ede889ada7f06,0x001611e91de2e135,0x00fdb9a458a471b9,0x00563484e03710d1,0x0031cc81925e3070,0x0062c97b3af80005,0x00fa733eea28edeb,0x00e82457e1ebbc88)}, - {FIELD_LITERAL(0x006a0df5fe9b6f59,0x00a0d4ff46040d92,0x004a7cedb6f93250,0x00d1df8855b8c357,0x00e73a46086fd058,0x0048fb0add6dfe59,0x001e03a28f1b4e3d,0x00a871c993308d76)}, + {FIELD_LITERAL(0x00c4887198d7a7faULL, 0x00244f98fb45784aULL, + 0x0045911e15a15d01ULL, 0x001d323d374c0966ULL, + 0x00967c3915196562ULL, 0x0039373abd2f3c67ULL, + 0x000d2c5614312423ULL, 0x0041cf2215442ce3ULL)}, + {FIELD_LITERAL(0x008ede889ada7f06ULL, 0x001611e91de2e135ULL, + 0x00fdb9a458a471b9ULL, 0x00563484e03710d1ULL, + 0x0031cc81925e3070ULL, 0x0062c97b3af80005ULL, + 0x00fa733eea28edebULL, 0x00e82457e1ebbc88ULL)}, + {FIELD_LITERAL(0x006a0df5fe9b6f59ULL, 0x00a0d4ff46040d92ULL, + 0x004a7cedb6f93250ULL, 0x00d1df8855b8c357ULL, + 0x00e73a46086fd058ULL, 0x0048fb0add6dfe59ULL, + 0x001e03a28f1b4e3dULL, 0x00a871c993308d76ULL)}, }}, {{ - {FIELD_LITERAL(0x0030dbb2d1766ec8,0x00586c0ad138555e,0x00d1a34f9e91c77c,0x0063408ad0e89014,0x00d61231b05f6f5b,0x0009abf569f5fd8a,0x00aec67a110f1c43,0x0031d1a790938dd7)}, - {FIELD_LITERAL(0x006cded841e2a862,0x00198d60af0ab6fb,0x0018f09db809e750,0x004e6ac676016263,0x00eafcd1620969cb,0x002c9784ca34917d,0x0054f00079796de7,0x00d9fab5c5972204)}, - {FIELD_LITERAL(0x004bd0fee2438a83,0x00b571e62b0f83bd,0x0059287d7ce74800,0x00fb3631b645c3f0,0x00a018e977f78494,0x0091e27065c27b12,0x007696c1817165e0,0x008c40be7c45ba3a)}, + {FIELD_LITERAL(0x0030dbb2d1766ec8ULL, 0x00586c0ad138555eULL, + 0x00d1a34f9e91c77cULL, 0x0063408ad0e89014ULL, + 0x00d61231b05f6f5bULL, 0x0009abf569f5fd8aULL, + 0x00aec67a110f1c43ULL, 0x0031d1a790938dd7ULL)}, + {FIELD_LITERAL(0x006cded841e2a862ULL, 0x00198d60af0ab6fbULL, + 0x0018f09db809e750ULL, 0x004e6ac676016263ULL, + 0x00eafcd1620969cbULL, 0x002c9784ca34917dULL, + 0x0054f00079796de7ULL, 0x00d9fab5c5972204ULL)}, + {FIELD_LITERAL(0x004bd0fee2438a83ULL, 0x00b571e62b0f83bdULL, + 0x0059287d7ce74800ULL, 0x00fb3631b645c3f0ULL, + 0x00a018e977f78494ULL, 0x0091e27065c27b12ULL, + 0x007696c1817165e0ULL, 0x008c40be7c45ba3aULL)}, }}, {{ - {FIELD_LITERAL(0x00a0f326327cb684,0x001c7d0f672680ff,0x008c1c81ffb112d1,0x00f8f801674eddc8,0x00e926d5d48c2a9d,0x005bd6d954c6fe9a,0x004c6b24b4e33703,0x00d05eb5c09105cc)}, - {FIELD_LITERAL(0x00d61731caacf2cf,0x002df0c7609e01c5,0x00306172208b1e2b,0x00b413fe4fb2b686,0x00826d360902a221,0x003f8d056e67e7f7,0x0065025b0175e989,0x00369add117865eb)}, - {FIELD_LITERAL(0x00aaf895aec2fa11,0x000f892bc313eb52,0x005b1c794dad050b,0x003f8ec4864cec14,0x00af81058d0b90e5,0x00ebe43e183997bb,0x00a9d610f9f3e615,0x007acd8eec2e88d3)}, + {FIELD_LITERAL(0x00a0f326327cb684ULL, 0x001c7d0f672680ffULL, + 0x008c1c81ffb112d1ULL, 0x00f8f801674eddc8ULL, + 0x00e926d5d48c2a9dULL, 0x005bd6d954c6fe9aULL, + 0x004c6b24b4e33703ULL, 0x00d05eb5c09105ccULL)}, + {FIELD_LITERAL(0x00d61731caacf2cfULL, 0x002df0c7609e01c5ULL, + 0x00306172208b1e2bULL, 0x00b413fe4fb2b686ULL, + 0x00826d360902a221ULL, 0x003f8d056e67e7f7ULL, + 0x0065025b0175e989ULL, 0x00369add117865ebULL)}, + {FIELD_LITERAL(0x00aaf895aec2fa11ULL, 0x000f892bc313eb52ULL, + 0x005b1c794dad050bULL, 0x003f8ec4864cec14ULL, + 0x00af81058d0b90e5ULL, 0x00ebe43e183997bbULL, + 0x00a9d610f9f3e615ULL, 0x007acd8eec2e88d3ULL)}, }}, {{ - {FIELD_LITERAL(0x0049b2fab13812a3,0x00846db32cd60431,0x000177fa578c8d6c,0x00047d0e2ad4bc51,0x00b158ba38d1e588,0x006a45daad79e3f3,0x000997b93cab887b,0x00c47ea42fa23dc3)}, - {FIELD_LITERAL(0x0012b6fef7aeb1ca,0x009412768194b6a7,0x00ff0d351f23ab93,0x007e8a14c1aff71b,0x006c1c0170c512bc,0x0016243ea02ab2e5,0x007bb6865b303f3e,0x0015ce6b29b159f4)}, - {FIELD_LITERAL(0x009961cd02e68108,0x00e2035d3a1d0836,0x005d51f69b5e1a1d,0x004bccb4ea36edcd,0x0069be6a7aeef268,0x0063f4dd9de8d5a7,0x006283783092ca35,0x0075a31af2c35409)}, + {FIELD_LITERAL(0x0049b2fab13812a3ULL, 0x00846db32cd60431ULL, + 0x000177fa578c8d6cULL, 0x00047d0e2ad4bc51ULL, + 0x00b158ba38d1e588ULL, 0x006a45daad79e3f3ULL, + 0x000997b93cab887bULL, 0x00c47ea42fa23dc3ULL)}, + {FIELD_LITERAL(0x0012b6fef7aeb1caULL, 0x009412768194b6a7ULL, + 0x00ff0d351f23ab93ULL, 0x007e8a14c1aff71bULL, + 0x006c1c0170c512bcULL, 0x0016243ea02ab2e5ULL, + 0x007bb6865b303f3eULL, 0x0015ce6b29b159f4ULL)}, + {FIELD_LITERAL(0x009961cd02e68108ULL, 0x00e2035d3a1d0836ULL, + 0x005d51f69b5e1a1dULL, 0x004bccb4ea36edcdULL, + 0x0069be6a7aeef268ULL, 0x0063f4dd9de8d5a7ULL, + 0x006283783092ca35ULL, 0x0075a31af2c35409ULL)}, }}, {{ - {FIELD_LITERAL(0x00c412365162e8cf,0x00012283fb34388a,0x003e6543babf39e2,0x00eead6b3a804978,0x0099c0314e8b326f,0x00e98e0a8d477a4f,0x00d2eb96b127a687,0x00ed8d7df87571bb)}, - {FIELD_LITERAL(0x00777463e308cacf,0x00c8acb93950132d,0x00ebddbf4ca48b2c,0x0026ad7ca0795a0a,0x00f99a3d9a715064,0x000d60bcf9d4dfcc,0x005e65a73a437a06,0x0019d536a8db56c8)}, - {FIELD_LITERAL(0x00192d7dd558d135,0x0027cd6a8323ffa7,0x00239f1a412dc1e7,0x0046b4b3be74fc5c,0x0020c47a2bef5bce,0x00aa17e48f43862b,0x00f7e26c96342e5f,0x0008011c530f39a9)}, + {FIELD_LITERAL(0x00c412365162e8cfULL, 0x00012283fb34388aULL, + 0x003e6543babf39e2ULL, 0x00eead6b3a804978ULL, + 0x0099c0314e8b326fULL, 0x00e98e0a8d477a4fULL, + 0x00d2eb96b127a687ULL, 0x00ed8d7df87571bbULL)}, + {FIELD_LITERAL(0x00777463e308cacfULL, 0x00c8acb93950132dULL, + 0x00ebddbf4ca48b2cULL, 0x0026ad7ca0795a0aULL, + 0x00f99a3d9a715064ULL, 0x000d60bcf9d4dfccULL, + 0x005e65a73a437a06ULL, 0x0019d536a8db56c8ULL)}, + {FIELD_LITERAL(0x00192d7dd558d135ULL, 0x0027cd6a8323ffa7ULL, + 0x00239f1a412dc1e7ULL, 0x0046b4b3be74fc5cULL, + 0x0020c47a2bef5bceULL, 0x00aa17e48f43862bULL, + 0x00f7e26c96342e5fULL, 0x0008011c530f39a9ULL)}, }}, {{ - {FIELD_LITERAL(0x00aad4ac569bf0f1,0x00a67adc90b27740,0x0048551369a5751a,0x0031252584a3306a,0x0084e15df770e6fc,0x00d7bba1c74b5805,0x00a80ef223af1012,0x0089c85ceb843a34)}, - {FIELD_LITERAL(0x00c4545be4a54004,0x0099e11f60357e6c,0x001f3936d19515a6,0x007793df84341a6e,0x0051061886717ffa,0x00e9b0a660b28f85,0x0044ea685892de0d,0x000257d2a1fda9d9)}, - {FIELD_LITERAL(0x007e8b01b24ac8a8,0x006cf3b0b5ca1337,0x00f1607d3e36a570,0x0039b7fab82991a1,0x00231777065840c5,0x00998e5afdd346f9,0x00b7dc3e64acc85f,0x00baacc748013ad6)}, + {FIELD_LITERAL(0x00aad4ac569bf0f1ULL, 0x00a67adc90b27740ULL, + 0x0048551369a5751aULL, 0x0031252584a3306aULL, + 0x0084e15df770e6fcULL, 0x00d7bba1c74b5805ULL, + 0x00a80ef223af1012ULL, 0x0089c85ceb843a34ULL)}, + {FIELD_LITERAL(0x00c4545be4a54004ULL, 0x0099e11f60357e6cULL, + 0x001f3936d19515a6ULL, 0x007793df84341a6eULL, + 0x0051061886717ffaULL, 0x00e9b0a660b28f85ULL, + 0x0044ea685892de0dULL, 0x000257d2a1fda9d9ULL)}, + {FIELD_LITERAL(0x007e8b01b24ac8a8ULL, 0x006cf3b0b5ca1337ULL, + 0x00f1607d3e36a570ULL, 0x0039b7fab82991a1ULL, + 0x00231777065840c5ULL, 0x00998e5afdd346f9ULL, + 0x00b7dc3e64acc85fULL, 0x00baacc748013ad6ULL)}, }}, {{ - {FIELD_LITERAL(0x008ea6a4177580bf,0x005fa1953e3f0378,0x005fe409ac74d614,0x00452327f477e047,0x00a4018507fb6073,0x007b6e71951caac8,0x0012b42ab8a6ce91,0x0080eca677294ab7)}, - {FIELD_LITERAL(0x00a53edc023ba69b,0x00c6afa83ddde2e8,0x00c3f638b307b14e,0x004a357a64414062,0x00e4d94d8b582dc9,0x001739caf71695b7,0x0012431b2ae28de1,0x003b6bc98682907c)}, - {FIELD_LITERAL(0x008a9a93be1f99d6,0x0079fa627cc699c8,0x00b0cfb134ba84c8,0x001c4b778249419a,0x00df4ab3d9c44f40,0x009f596e6c1a9e3c,0x001979c0df237316,0x00501e953a919b87)}, + {FIELD_LITERAL(0x008ea6a4177580bfULL, 0x005fa1953e3f0378ULL, + 0x005fe409ac74d614ULL, 0x00452327f477e047ULL, + 0x00a4018507fb6073ULL, 0x007b6e71951caac8ULL, + 0x0012b42ab8a6ce91ULL, 0x0080eca677294ab7ULL)}, + {FIELD_LITERAL(0x00a53edc023ba69bULL, 0x00c6afa83ddde2e8ULL, + 0x00c3f638b307b14eULL, 0x004a357a64414062ULL, + 0x00e4d94d8b582dc9ULL, 0x001739caf71695b7ULL, + 0x0012431b2ae28de1ULL, 0x003b6bc98682907cULL)}, + {FIELD_LITERAL(0x008a9a93be1f99d6ULL, 0x0079fa627cc699c8ULL, + 0x00b0cfb134ba84c8ULL, 0x001c4b778249419aULL, + 0x00df4ab3d9c44f40ULL, 0x009f596e6c1a9e3cULL, + 0x001979c0df237316ULL, 0x00501e953a919b87ULL)}, }} }; const niels_t *curve448_wnaf_base = curve448_wnaf_base_table; diff --git a/freebsd/crypto/openssl/crypto/ec/curve448/curve448utils.h b/freebsd/crypto/openssl/crypto/ec/curve448/curve448utils.h index 9bf83799..9032bb4f 100644 --- a/freebsd/crypto/openssl/crypto/ec/curve448/curve448utils.h +++ b/freebsd/crypto/openssl/crypto/ec/curve448/curve448utils.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved. * Copyright 2015 Cryptography Research, Inc. * * Licensed under the OpenSSL license (the "License"). You may not use @@ -24,7 +24,9 @@ */ # ifndef C448_WORD_BITS # if (defined(__SIZEOF_INT128__) && (__SIZEOF_INT128__ == 16)) \ - && !defined(__sparc__) + && !defined(__sparc__) \ + && (!defined(__SIZEOF_LONG__) || (__SIZEOF_LONG__ == 8)) + # define C448_WORD_BITS 64 /* The number of bits in a word */ # else # define C448_WORD_BITS 32 /* The number of bits in a word */ diff --git a/freebsd/crypto/openssl/crypto/ec/curve448/f_generic.c b/freebsd/crypto/openssl/crypto/ec/curve448/f_generic.c index c505543c..f357dc2a 100644 --- a/freebsd/crypto/openssl/crypto/ec/curve448/f_generic.c +++ b/freebsd/crypto/openssl/crypto/ec/curve448/f_generic.c @@ -1,7 +1,7 @@ #include <machine/rtems-bsd-user-space.h> /* - * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved. * Copyright 2015-2016 Cryptography Research, Inc. * * Licensed under the OpenSSL license (the "License"). You may not use @@ -14,9 +14,9 @@ #include "field.h" static const gf MODULUS = { - FIELD_LITERAL(0xffffffffffffff, 0xffffffffffffff, 0xffffffffffffff, - 0xffffffffffffff, 0xfffffffffffffe, 0xffffffffffffff, - 0xffffffffffffff, 0xffffffffffffff) + FIELD_LITERAL(0xffffffffffffffULL, 0xffffffffffffffULL, 0xffffffffffffffULL, + 0xffffffffffffffULL, 0xfffffffffffffeULL, 0xffffffffffffffULL, + 0xffffffffffffffULL, 0xffffffffffffffULL) }; /* Serialize to wire format. */ diff --git a/freebsd/crypto/openssl/crypto/ec/curve448/scalar.c b/freebsd/crypto/openssl/crypto/ec/curve448/scalar.c index efde5a99..df50a30c 100644 --- a/freebsd/crypto/openssl/crypto/ec/curve448/scalar.c +++ b/freebsd/crypto/openssl/crypto/ec/curve448/scalar.c @@ -1,7 +1,7 @@ #include <machine/rtems-bsd-user-space.h> /* - * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved. * Copyright 2015-2016 Cryptography Research, Inc. * * Licensed under the OpenSSL license (the "License"). You may not use @@ -16,24 +16,24 @@ #include "word.h" #include "point_448.h" -static const c448_word_t MONTGOMERY_FACTOR = (c448_word_t) 0x3bd440fae918bc5; +static const c448_word_t MONTGOMERY_FACTOR = (c448_word_t) 0x3bd440fae918bc5ULL; static const curve448_scalar_t sc_p = { { { - SC_LIMB(0x2378c292ab5844f3), SC_LIMB(0x216cc2728dc58f55), - SC_LIMB(0xc44edb49aed63690), SC_LIMB(0xffffffff7cca23e9), - SC_LIMB(0xffffffffffffffff), SC_LIMB(0xffffffffffffffff), - SC_LIMB(0x3fffffffffffffff) + SC_LIMB(0x2378c292ab5844f3ULL), SC_LIMB(0x216cc2728dc58f55ULL), + SC_LIMB(0xc44edb49aed63690ULL), SC_LIMB(0xffffffff7cca23e9ULL), + SC_LIMB(0xffffffffffffffffULL), SC_LIMB(0xffffffffffffffffULL), + SC_LIMB(0x3fffffffffffffffULL) } } }, sc_r2 = { { { - SC_LIMB(0xe3539257049b9b60), SC_LIMB(0x7af32c4bc1b195d9), - SC_LIMB(0x0d66de2388ea1859), SC_LIMB(0xae17cf725ee4d838), - SC_LIMB(0x1a9cc14ba3c47c44), SC_LIMB(0x2052bcb7e4d070af), - SC_LIMB(0x3402a939f823b729) + SC_LIMB(0xe3539257049b9b60ULL), SC_LIMB(0x7af32c4bc1b195d9ULL), + SC_LIMB(0x0d66de2388ea1859ULL), SC_LIMB(0xae17cf725ee4d838ULL), + SC_LIMB(0x1a9cc14ba3c47c44ULL), SC_LIMB(0x2052bcb7e4d070afULL), + SC_LIMB(0x3402a939f823b729ULL) } } }; diff --git a/freebsd/crypto/openssl/crypto/ec/ec2_oct.c b/freebsd/crypto/openssl/crypto/ec/ec2_oct.c index fe0f9eb2..4dc5ede8 100644 --- a/freebsd/crypto/openssl/crypto/ec/ec2_oct.c +++ b/freebsd/crypto/openssl/crypto/ec/ec2_oct.c @@ -1,7 +1,7 @@ #include <machine/rtems-bsd-user-space.h> /* - * Copyright 2011-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2011-2019 The OpenSSL Project Authors. All Rights Reserved. * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved * * Licensed under the OpenSSL license (the "License"). You may not use @@ -239,7 +239,7 @@ int ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx) { point_conversion_form_t form; - int y_bit; + int y_bit, m; BN_CTX *new_ctx = NULL; BIGNUM *x, *y, *yxi; size_t field_len, enc_len; @@ -272,7 +272,8 @@ int ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point, return EC_POINT_set_to_infinity(group, point); } - field_len = (EC_GROUP_get_degree(group) + 7) / 8; + m = EC_GROUP_get_degree(group); + field_len = (m + 7) / 8; enc_len = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2 * field_len; @@ -297,7 +298,7 @@ int ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point, if (!BN_bin2bn(buf + 1, field_len, x)) goto err; - if (BN_ucmp(x, group->field) >= 0) { + if (BN_num_bits(x) > m) { ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); goto err; } @@ -308,7 +309,7 @@ int ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point, } else { if (!BN_bin2bn(buf + 1 + field_len, field_len, y)) goto err; - if (BN_ucmp(y, group->field) >= 0) { + if (BN_num_bits(y) > m) { ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING); goto err; } diff --git a/freebsd/crypto/openssl/crypto/ec/ec2_smpl.c b/freebsd/crypto/openssl/crypto/ec/ec2_smpl.c index af351a80..9003f42d 100644 --- a/freebsd/crypto/openssl/crypto/ec/ec2_smpl.c +++ b/freebsd/crypto/openssl/crypto/ec/ec2_smpl.c @@ -206,8 +206,7 @@ int ec_GF2m_simple_group_check_discriminant(const EC_GROUP *group, ret = 1; err: - if (ctx != NULL) - BN_CTX_end(ctx); + BN_CTX_end(ctx); BN_CTX_free(new_ctx); return ret; } diff --git a/freebsd/crypto/openssl/crypto/ec/ec_ameth.c b/freebsd/crypto/openssl/crypto/ec/ec_ameth.c index 5dbc6f46..604a0e35 100644 --- a/freebsd/crypto/openssl/crypto/ec/ec_ameth.c +++ b/freebsd/crypto/openssl/crypto/ec/ec_ameth.c @@ -1,7 +1,7 @@ #include <machine/rtems-bsd-user-space.h> /* - * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2006-2019 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -506,7 +506,12 @@ static int ec_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2) #endif case ASN1_PKEY_CTRL_DEFAULT_MD_NID: - *(int *)arg2 = NID_sha256; + if (EVP_PKEY_id(pkey) == EVP_PKEY_SM2) { + /* For SM2, the only valid digest-alg is SM3 */ + *(int *)arg2 = NID_sm3; + } else { + *(int *)arg2 = NID_sha256; + } return 1; case ASN1_PKEY_CTRL_SET1_TLS_ENCPT: diff --git a/freebsd/crypto/openssl/crypto/ec/ec_lib.c b/freebsd/crypto/openssl/crypto/ec/ec_lib.c index 7f365de3..6da3f8b7 100644 --- a/freebsd/crypto/openssl/crypto/ec/ec_lib.c +++ b/freebsd/crypto/openssl/crypto/ec/ec_lib.c @@ -1,7 +1,7 @@ #include <machine/rtems-bsd-user-space.h> /* - * Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved. * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved * * Licensed under the OpenSSL license (the "License"). You may not use @@ -1076,8 +1076,7 @@ static int ec_field_inverse_mod_ord(const EC_GROUP *group, BIGNUM *r, ret = 1; err: - if (ctx != NULL) - BN_CTX_end(ctx); + BN_CTX_end(ctx); BN_CTX_free(new_ctx); return ret; } diff --git a/freebsd/crypto/openssl/crypto/ec/ec_mult.c b/freebsd/crypto/openssl/crypto/ec/ec_mult.c index 5bfa3868..169f8e18 100644 --- a/freebsd/crypto/openssl/crypto/ec/ec_mult.c +++ b/freebsd/crypto/openssl/crypto/ec/ec_mult.c @@ -1,7 +1,7 @@ #include <machine/rtems-bsd-user-space.h> /* - * Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved. * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved * * Licensed under the OpenSSL license (the "License"). You may not use @@ -380,7 +380,7 @@ int ec_scalar_mul_ladder(const EC_GROUP *group, EC_POINT *r, err: EC_POINT_free(p); - EC_POINT_free(s); + EC_POINT_clear_free(s); BN_CTX_end(ctx); return ret; @@ -443,7 +443,7 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, * scalar multiplication implementation based on a Montgomery ladder, * with various timing attack defenses. */ - if ((scalar != NULL) && (num == 0)) { + if ((scalar != group->order) && (scalar != NULL) && (num == 0)) { /*- * In this case we want to compute scalar * GeneratorPoint: this * codepath is reached most prominently by (ephemeral) key @@ -454,7 +454,7 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, */ return ec_scalar_mul_ladder(group, r, scalar, NULL, ctx); } - if ((scalar == NULL) && (num == 1)) { + if ((scalar == NULL) && (num == 1) && (scalars[0] != group->order)) { /*- * In this case we want to compute scalar * VariablePoint: this * codepath is reached most prominently by the second half of ECDH, @@ -950,8 +950,7 @@ int ec_wNAF_precompute_mult(EC_GROUP *group, BN_CTX *ctx) ret = 1; err: - if (ctx != NULL) - BN_CTX_end(ctx); + BN_CTX_end(ctx); BN_CTX_free(new_ctx); EC_ec_pre_comp_free(pre_comp); if (points) { diff --git a/freebsd/crypto/openssl/crypto/ec/ec_pmeth.c b/freebsd/crypto/openssl/crypto/ec/ec_pmeth.c index 41ca7813..ff38664e 100644 --- a/freebsd/crypto/openssl/crypto/ec/ec_pmeth.c +++ b/freebsd/crypto/openssl/crypto/ec/ec_pmeth.c @@ -1,7 +1,7 @@ #include <machine/rtems-bsd-user-space.h> /* - * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2006-2019 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -325,7 +325,11 @@ static int pkey_ec_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) EVP_MD_type((const EVP_MD *)p2) != NID_sha224 && EVP_MD_type((const EVP_MD *)p2) != NID_sha256 && EVP_MD_type((const EVP_MD *)p2) != NID_sha384 && - EVP_MD_type((const EVP_MD *)p2) != NID_sha512) { + EVP_MD_type((const EVP_MD *)p2) != NID_sha512 && + EVP_MD_type((const EVP_MD *)p2) != NID_sha3_224 && + EVP_MD_type((const EVP_MD *)p2) != NID_sha3_256 && + EVP_MD_type((const EVP_MD *)p2) != NID_sha3_384 && + EVP_MD_type((const EVP_MD *)p2) != NID_sha3_512) { ECerr(EC_F_PKEY_EC_CTRL, EC_R_INVALID_DIGEST_TYPE); return 0; } diff --git a/freebsd/crypto/openssl/crypto/ec/ecdh_ossl.c b/freebsd/crypto/openssl/crypto/ec/ecdh_ossl.c index 74d1b73e..6d641991 100644 --- a/freebsd/crypto/openssl/crypto/ec/ecdh_ossl.c +++ b/freebsd/crypto/openssl/crypto/ec/ecdh_ossl.c @@ -1,7 +1,7 @@ #include <machine/rtems-bsd-user-space.h> /* - * Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2002-2019 The OpenSSL Project Authors. All Rights Reserved. * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved * * Licensed under the OpenSSL license (the "License"). You may not use @@ -114,9 +114,8 @@ int ecdh_simple_compute_key(unsigned char **pout, size_t *poutlen, ret = 1; err: - EC_POINT_free(tmp); - if (ctx) - BN_CTX_end(ctx); + EC_POINT_clear_free(tmp); + BN_CTX_end(ctx); BN_CTX_free(ctx); OPENSSL_free(buf); return ret; diff --git a/freebsd/crypto/openssl/crypto/ec/ecp_nistp521.c b/freebsd/crypto/openssl/crypto/ec/ecp_nistp521.c index 96e0d661..2fd19dd0 100644 --- a/freebsd/crypto/openssl/crypto/ec/ecp_nistp521.c +++ b/freebsd/crypto/openssl/crypto/ec/ecp_nistp521.c @@ -359,10 +359,15 @@ static void felem_diff64(felem out, const felem in) static void felem_diff_128_64(largefelem out, const felem in) { /* - * In order to prevent underflow, we add 0 mod p before subtracting. + * In order to prevent underflow, we add 64p mod p (which is equivalent + * to 0 mod p) before subtracting. p is 2^521 - 1, i.e. in binary a 521 + * digit number with all bits set to 1. See "The representation of field + * elements" comment above for a description of how limbs are used to + * represent a number. 64p is represented with 8 limbs containing a number + * with 58 bits set and one limb with a number with 57 bits set. */ - static const limb two63m6 = (((limb) 1) << 62) - (((limb) 1) << 5); - static const limb two63m5 = (((limb) 1) << 62) - (((limb) 1) << 4); + static const limb two63m6 = (((limb) 1) << 63) - (((limb) 1) << 6); + static const limb two63m5 = (((limb) 1) << 63) - (((limb) 1) << 5); out[0] += two63m6 - in[0]; out[1] += two63m5 - in[1]; diff --git a/freebsd/crypto/openssl/crypto/ec/ecp_nistz256.c b/freebsd/crypto/openssl/crypto/ec/ecp_nistz256.c index 9a370643..e6ed24ab 100644 --- a/freebsd/crypto/openssl/crypto/ec/ecp_nistz256.c +++ b/freebsd/crypto/openssl/crypto/ec/ecp_nistz256.c @@ -890,8 +890,7 @@ __owur static int ecp_nistz256_mult_precompute(EC_GROUP *group, BN_CTX *ctx) ret = 1; err: - if (ctx != NULL) - BN_CTX_end(ctx); + BN_CTX_end(ctx); BN_CTX_free(new_ctx); EC_nistz256_pre_comp_free(pre_comp); diff --git a/freebsd/crypto/openssl/crypto/ec/ecp_smpl.c b/freebsd/crypto/openssl/crypto/ec/ecp_smpl.c index c1f456fe..1b8d298f 100644 --- a/freebsd/crypto/openssl/crypto/ec/ecp_smpl.c +++ b/freebsd/crypto/openssl/crypto/ec/ecp_smpl.c @@ -309,8 +309,7 @@ int ec_GFp_simple_group_check_discriminant(const EC_GROUP *group, BN_CTX *ctx) ret = 1; err: - if (ctx != NULL) - BN_CTX_end(ctx); + BN_CTX_end(ctx); BN_CTX_free(new_ctx); return ret; } @@ -789,8 +788,7 @@ int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, ret = 1; end: - if (ctx) /* otherwise we already called BN_CTX_end */ - BN_CTX_end(ctx); + BN_CTX_end(ctx); BN_CTX_free(new_ctx); return ret; } diff --git a/freebsd/crypto/openssl/crypto/err/err.c b/freebsd/crypto/openssl/crypto/err/err.c index 36f9579c..806dae3f 100644 --- a/freebsd/crypto/openssl/crypto/err/err.c +++ b/freebsd/crypto/openssl/crypto/err/err.c @@ -525,8 +525,24 @@ static unsigned long get_error_values(int inc, int top, const char **file, return ERR_R_INTERNAL_ERROR; } + while (es->bottom != es->top) { + if (es->err_flags[es->top] & ERR_FLAG_CLEAR) { + err_clear(es, es->top); + es->top = es->top > 0 ? es->top - 1 : ERR_NUM_ERRORS - 1; + continue; + } + i = (es->bottom + 1) % ERR_NUM_ERRORS; + if (es->err_flags[i] & ERR_FLAG_CLEAR) { + es->bottom = i; + err_clear(es, es->bottom); + continue; + } + break; + } + if (es->bottom == es->top) return 0; + if (top) i = es->top; /* last error */ else @@ -915,25 +931,6 @@ int ERR_clear_last_mark(void) return 1; } -#ifdef UINTPTR_T -# undef UINTPTR_T -#endif -/* - * uintptr_t is the answer, but unfortunately C89, current "least common - * denominator" doesn't define it. Most legacy platforms typedef it anyway, - * so that attempt to fill the gaps means that one would have to identify - * that track these gaps, which would be undesirable. Macro it is... - */ -#if defined(__VMS) && __INITIAL_POINTER_SIZE==64 -/* - * But we can't use size_t on VMS, because it adheres to sizeof(size_t)==4 - * even in 64-bit builds, which means that it won't work as mask. - */ -# define UINTPTR_T unsigned long long -#else -# define UINTPTR_T size_t -#endif - void err_clear_last_constant_time(int clear) { ERR_STATE *es; @@ -945,11 +942,11 @@ void err_clear_last_constant_time(int clear) top = es->top; - es->err_flags[top] &= ~(0 - clear); - es->err_buffer[top] &= ~(0UL - clear); - es->err_file[top] = (const char *)((UINTPTR_T)es->err_file[top] & - ~((UINTPTR_T)0 - clear)); - es->err_line[top] |= 0 - clear; - - es->top = (top + ERR_NUM_ERRORS - clear) % ERR_NUM_ERRORS; + /* + * Flag error as cleared but remove it elsewhere to avoid two errors + * accessing the same error stack location, revealing timing information. + */ + clear = constant_time_select_int(constant_time_eq_int(clear, 0), + 0, ERR_FLAG_CLEAR); + es->err_flags[top] |= clear; } diff --git a/freebsd/crypto/openssl/crypto/evp/digest.c b/freebsd/crypto/openssl/crypto/evp/digest.c index 9111c19a..82e7bac8 100644 --- a/freebsd/crypto/openssl/crypto/evp/digest.c +++ b/freebsd/crypto/openssl/crypto/evp/digest.c @@ -1,7 +1,7 @@ #include <machine/rtems-bsd-user-space.h> /* - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -152,6 +152,9 @@ int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl) int EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *data, size_t count) { + if (count == 0) + return 1; + return ctx->update(ctx, data, count); } diff --git a/freebsd/crypto/openssl/crypto/evp/e_aes.c b/freebsd/crypto/openssl/crypto/evp/e_aes.c index 1c86559f..1d025fe1 100644 --- a/freebsd/crypto/openssl/crypto/evp/e_aes.c +++ b/freebsd/crypto/openssl/crypto/evp/e_aes.c @@ -1,7 +1,7 @@ #include <machine/rtems-bsd-user-space.h> /* - * Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -2218,9 +2218,6 @@ static int s390x_aes_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, if (!cctx->aes.ccm.iv_set) return -1; - if (!enc && !cctx->aes.ccm.tag_set) - return -1; - if (out == NULL) { /* Update(): Pass message length. */ if (in == NULL) { @@ -2239,6 +2236,10 @@ static int s390x_aes_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, return len; } + /* The tag must be set before actually decrypting data */ + if (!enc && !cctx->aes.ccm.tag_set) + return -1; + /* Update(): Process message. */ if (!cctx->aes.ccm.len_set) { @@ -3645,8 +3646,6 @@ static int aes_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, if (!cctx->iv_set) return -1; - if (!EVP_CIPHER_CTX_encrypting(ctx) && !cctx->tag_set) - return -1; if (!out) { if (!in) { if (CRYPTO_ccm128_setiv(ccm, EVP_CIPHER_CTX_iv_noconst(ctx), @@ -3661,6 +3660,11 @@ static int aes_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, CRYPTO_ccm128_aad(ccm, in, len); return len; } + + /* The tag must be set before actually decrypting data */ + if (!EVP_CIPHER_CTX_encrypting(ctx) && !cctx->tag_set) + return -1; + /* If not set length yet do it */ if (!cctx->len_set) { if (CRYPTO_ccm128_setiv(ccm, EVP_CIPHER_CTX_iv_noconst(ctx), diff --git a/freebsd/crypto/openssl/crypto/evp/e_aria.c b/freebsd/crypto/openssl/crypto/evp/e_aria.c index 33ff1186..6a9d5dee 100644 --- a/freebsd/crypto/openssl/crypto/evp/e_aria.c +++ b/freebsd/crypto/openssl/crypto/evp/e_aria.c @@ -1,7 +1,7 @@ #include <machine/rtems-bsd-user-space.h> /* - * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved. * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. * * Licensed under the OpenSSL license (the "License"). You may not use @@ -488,6 +488,16 @@ static int aria_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, return 0; } +static int aria_gcm_cleanup(EVP_CIPHER_CTX *ctx) +{ + EVP_ARIA_GCM_CTX *gctx = EVP_C_DATA(EVP_ARIA_GCM_CTX, ctx); + + if (gctx->iv != EVP_CIPHER_CTX_iv_noconst(ctx)) + OPENSSL_free(gctx->iv); + + return 1; +} + static int aria_ccm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc) { @@ -729,6 +739,8 @@ static int aria_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, } } +#define aria_ccm_cleanup NULL + #define ARIA_AUTH_FLAGS (EVP_CIPH_FLAG_DEFAULT_ASN1 \ | EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER \ | EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT \ @@ -741,7 +753,7 @@ static const EVP_CIPHER aria_##keylen##_##mode = { \ ARIA_AUTH_FLAGS|EVP_CIPH_##MODE##_MODE, \ aria_##mode##_init_key, \ aria_##mode##_cipher, \ - NULL, \ + aria_##mode##_cleanup, \ sizeof(EVP_ARIA_##MODE##_CTX), \ NULL,NULL,aria_##mode##_ctrl,NULL }; \ const EVP_CIPHER *EVP_aria_##keylen##_##mode(void) \ diff --git a/freebsd/crypto/openssl/crypto/evp/e_chacha20_poly1305.c b/freebsd/crypto/openssl/crypto/evp/e_chacha20_poly1305.c index 3f73fd19..4eeb7bc3 100644 --- a/freebsd/crypto/openssl/crypto/evp/e_chacha20_poly1305.c +++ b/freebsd/crypto/openssl/crypto/evp/e_chacha20_poly1305.c @@ -1,7 +1,7 @@ #include <machine/rtems-bsd-user-space.h> /* - * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2015-2019 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -32,6 +32,8 @@ typedef struct { #define data(ctx) ((EVP_CHACHA_KEY *)(ctx)->cipher_data) +#define CHACHA20_POLY1305_MAX_IVLEN 12 + static int chacha_init_key(EVP_CIPHER_CTX *ctx, const unsigned char user_key[CHACHA_KEY_SIZE], const unsigned char iv[CHACHA_CTR_SIZE], int enc) @@ -535,7 +537,7 @@ static int chacha20_poly1305_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, return 1; case EVP_CTRL_AEAD_SET_IVLEN: - if (arg <= 0 || arg > CHACHA_CTR_SIZE) + if (arg <= 0 || arg > CHACHA20_POLY1305_MAX_IVLEN) return 0; actx->nonce_len = arg; return 1; diff --git a/freebsd/crypto/openssl/crypto/evp/p_lib.c b/freebsd/crypto/openssl/crypto/evp/p_lib.c index 47135f0d..57c9ddf0 100644 --- a/freebsd/crypto/openssl/crypto/evp/p_lib.c +++ b/freebsd/crypto/openssl/crypto/evp/p_lib.c @@ -1,7 +1,7 @@ #include <machine/rtems-bsd-user-space.h> /* - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -396,6 +396,11 @@ int EVP_PKEY_set1_engine(EVP_PKEY *pkey, ENGINE *e) pkey->pmeth_engine = e; return 1; } + +ENGINE *EVP_PKEY_get0_engine(const EVP_PKEY *pkey) +{ + return pkey->engine; +} #endif int EVP_PKEY_assign(EVP_PKEY *pkey, int type, void *key) { diff --git a/freebsd/crypto/openssl/crypto/evp/p_open.c b/freebsd/crypto/openssl/crypto/evp/p_open.c index 8d558e9a..4bf70034 100644 --- a/freebsd/crypto/openssl/crypto/evp/p_open.c +++ b/freebsd/crypto/openssl/crypto/evp/p_open.c @@ -1,7 +1,7 @@ #include <machine/rtems-bsd-user-space.h> /* - * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -42,7 +42,7 @@ int EVP_OpenInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, } size = EVP_PKEY_size(priv); - key = OPENSSL_malloc(size + 2); + key = OPENSSL_malloc(size); if (key == NULL) { /* ERROR */ EVPerr(EVP_F_EVP_OPENINIT, ERR_R_MALLOC_FAILURE); diff --git a/freebsd/crypto/openssl/crypto/hmac/hmac.c b/freebsd/crypto/openssl/crypto/hmac/hmac.c index 8d1fd286..29978df2 100644 --- a/freebsd/crypto/openssl/crypto/hmac/hmac.c +++ b/freebsd/crypto/openssl/crypto/hmac/hmac.c @@ -1,7 +1,7 @@ #include <machine/rtems-bsd-user-space.h> /* - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -37,6 +37,13 @@ int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len, return 0; } + /* + * The HMAC construction is not allowed to be used with the + * extendable-output functions (XOF) shake128 and shake256. + */ + if ((EVP_MD_meth_get_flags(md) & EVP_MD_FLAG_XOF) != 0) + return 0; + if (key != NULL) { reset = 1; j = EVP_MD_block_size(md); diff --git a/freebsd/crypto/openssl/crypto/include/internal/dso_conf.h b/freebsd/crypto/openssl/crypto/include/internal/dso_conf.h index 5bef4afd..61985cac 100644 --- a/freebsd/crypto/openssl/crypto/include/internal/dso_conf.h +++ b/freebsd/crypto/openssl/crypto/include/internal/dso_conf.h @@ -2,7 +2,7 @@ /* WARNING: do not edit! */ /* Generated by Makefile from crypto/include/internal/dso_conf.h.in */ /* - * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -12,9 +12,7 @@ #ifndef HEADER_DSO_CONF_H # define HEADER_DSO_CONF_H - # define DSO_DLFCN # define HAVE_DLFCN_H # define DSO_EXTENSION ".so" - #endif diff --git a/freebsd/crypto/openssl/crypto/init.c b/freebsd/crypto/openssl/crypto/init.c index e409911d..e1d27815 100644 --- a/freebsd/crypto/openssl/crypto/init.c +++ b/freebsd/crypto/openssl/crypto/init.c @@ -167,10 +167,9 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_load_crypto_nodelete) #ifdef OPENSSL_INIT_DEBUG fprintf(stderr, "OPENSSL_INIT: ossl_init_load_crypto_nodelete()\n"); #endif -#if !defined(OPENSSL_NO_DSO) \ - && !defined(OPENSSL_USE_NODELETE) \ +#if !defined(OPENSSL_USE_NODELETE) \ && !defined(OPENSSL_NO_PINSHARED) -# ifdef DSO_WIN32 +# if defined(DSO_WIN32) && !defined(_WIN32_WCE) { HMODULE handle = NULL; BOOL ret; @@ -186,7 +185,7 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_load_crypto_nodelete) # endif return (ret == TRUE) ? 1 : 0; } -# else +# elif !defined(DSO_NONE) && !defined(__rtems__) /* * Deliberately leak a reference to ourselves. This will force the library * to remain loaded until the atexit() handler is run at process exit. @@ -714,7 +713,7 @@ int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings) ret = RUN_ONCE(&config, ossl_init_config); conf_settings = NULL; CRYPTO_THREAD_unlock(init_lock); - if (!ret) + if (ret <= 0) return 0; } @@ -779,8 +778,7 @@ int OPENSSL_atexit(void (*handler)(void)) { OPENSSL_INIT_STOP *newhand; -#if !defined(OPENSSL_NO_DSO) \ - && !defined(OPENSSL_USE_NODELETE)\ +#if !defined(OPENSSL_USE_NODELETE)\ && !defined(OPENSSL_NO_PINSHARED) { union { @@ -789,7 +787,7 @@ int OPENSSL_atexit(void (*handler)(void)) } handlersym; handlersym.func = handler; -# ifdef DSO_WIN32 +# if defined(DSO_WIN32) && !defined(_WIN32_WCE) { HMODULE handle = NULL; BOOL ret; @@ -805,7 +803,7 @@ int OPENSSL_atexit(void (*handler)(void)) if (!ret) return 0; } -# else +# elif !defined(DSO_NONE) /* * Deliberately leak a reference to the handler. This will force the * library/code containing the handler to remain loaded until we run the diff --git a/freebsd/crypto/openssl/crypto/mips_arch.h b/freebsd/crypto/openssl/crypto/mips_arch.h index 75043e79..e18ac072 100644 --- a/freebsd/crypto/openssl/crypto/mips_arch.h +++ b/freebsd/crypto/openssl/crypto/mips_arch.h @@ -1,5 +1,5 @@ /* - * Copyright 2011-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2011-2019 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -11,7 +11,7 @@ # define __MIPS_ARCH_H__ # if (defined(__mips_smartmips) || defined(_MIPS_ARCH_MIPS32R3) || \ - defined(_MIPS_ARCH_MIPS32R5) || defined(_MIPS_ARCH_MIPS32R6)) + defined(_MIPS_ARCH_MIPS32R5) || defined(_MIPS_ARCH_MIPS32R6)) \ && !defined(_MIPS_ARCH_MIPS32R2) # define _MIPS_ARCH_MIPS32R2 # endif diff --git a/freebsd/crypto/openssl/crypto/modes/ccm128.c b/freebsd/crypto/openssl/crypto/modes/ccm128.c index 96a35313..d96dd45a 100644 --- a/freebsd/crypto/openssl/crypto/modes/ccm128.c +++ b/freebsd/crypto/openssl/crypto/modes/ccm128.c @@ -1,7 +1,7 @@ #include <machine/rtems-bsd-user-space.h> /* - * Copyright 2011-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2011-2019 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -427,7 +427,7 @@ size_t CRYPTO_ccm128_tag(CCM128_CONTEXT *ctx, unsigned char *tag, size_t len) M *= 2; M += 2; - if (len < M) + if (len != M) return 0; memcpy(tag, ctx->cmac.c, M); return M; diff --git a/freebsd/crypto/openssl/crypto/o_str.c b/freebsd/crypto/openssl/crypto/o_str.c index f02ef56c..79d72a2c 100644 --- a/freebsd/crypto/openssl/crypto/o_str.c +++ b/freebsd/crypto/openssl/crypto/o_str.c @@ -1,7 +1,7 @@ #include <machine/rtems-bsd-user-space.h> /* - * Copyright 2003-2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2003-2019 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -225,7 +225,26 @@ int openssl_strerror_r(int errnum, char *buf, size_t buflen) #if defined(_MSC_VER) && _MSC_VER>=1400 return !strerror_s(buf, buflen, errnum); #elif defined(_GNU_SOURCE) - return strerror_r(errnum, buf, buflen) != NULL; + char *err; + + /* + * GNU strerror_r may not actually set buf. + * It can return a pointer to some (immutable) static string in which case + * buf is left unused. + */ + err = strerror_r(errnum, buf, buflen); + if (err == NULL) + return 0; + /* + * If err is statically allocated, err != buf and we need to copy the data. + * If err points somewhere inside buf, OPENSSL_strlcpy can handle this, + * since src and dest are not annotated with __restrict and the function + * reads src byte for byte and writes to dest. + * If err == buf we do not have to copy anything. + */ + if (err != buf) + OPENSSL_strlcpy(buf, err, buflen); + return 1; #elif (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L) || \ (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE >= 600) /* @@ -236,6 +255,7 @@ int openssl_strerror_r(int errnum, char *buf, size_t buflen) return !strerror_r(errnum, buf, buflen); #else char *err; + /* Fall back to non-thread safe strerror()...its all we can do */ if (buflen < 2) return 0; @@ -243,8 +263,7 @@ int openssl_strerror_r(int errnum, char *buf, size_t buflen) /* Can this ever happen? */ if (err == NULL) return 0; - strncpy(buf, err, buflen - 1); - buf[buflen - 1] = '\0'; + OPENSSL_strlcpy(buf, err, buflen); return 1; #endif } diff --git a/freebsd/crypto/openssl/crypto/objects/obj_dat.h b/freebsd/crypto/openssl/crypto/objects/obj_dat.h index 9ab1a14b..ea91db66 100644 --- a/freebsd/crypto/openssl/crypto/objects/obj_dat.h +++ b/freebsd/crypto/openssl/crypto/objects/obj_dat.h @@ -1070,7 +1070,7 @@ static const unsigned char so[7762] = { 0x2A,0x85,0x03,0x07,0x01,0x01,0x07,0x01, /* [ 7684] OBJ_id_tc26_wrap_gostr3412_2015_magma */ 0x2A,0x85,0x03,0x07,0x01,0x01,0x07,0x01,0x01, /* [ 7692] OBJ_id_tc26_wrap_gostr3412_2015_magma_kexp15 */ 0x2A,0x85,0x03,0x07,0x01,0x01,0x07,0x02, /* [ 7701] OBJ_id_tc26_wrap_gostr3412_2015_kuznyechik */ - 0x2A,0x85,0x03,0x07,0x01,0x01,0x07,0x01,0x01, /* [ 7709] OBJ_id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15 */ + 0x2A,0x85,0x03,0x07,0x01,0x01,0x07,0x02,0x01, /* [ 7709] OBJ_id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15 */ 0x2A,0x85,0x03,0x07,0x01,0x02,0x01,0x01,0x02, /* [ 7718] OBJ_id_tc26_gost_3410_2012_256_paramSetB */ 0x2A,0x85,0x03,0x07,0x01,0x02,0x01,0x01,0x03, /* [ 7727] OBJ_id_tc26_gost_3410_2012_256_paramSetC */ 0x2A,0x85,0x03,0x07,0x01,0x02,0x01,0x01,0x04, /* [ 7736] OBJ_id_tc26_gost_3410_2012_256_paramSetD */ @@ -5364,7 +5364,7 @@ static const unsigned int obj_objs[NUM_OBJ] = { 1177, /* OBJ_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm 1 2 643 7 1 1 5 2 1 */ 1178, /* OBJ_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm_omac 1 2 643 7 1 1 5 2 2 */ 1181, /* OBJ_id_tc26_wrap_gostr3412_2015_magma_kexp15 1 2 643 7 1 1 7 1 1 */ - 1183, /* OBJ_id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15 1 2 643 7 1 1 7 1 1 */ + 1183, /* OBJ_id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15 1 2 643 7 1 1 7 2 1 */ 1148, /* OBJ_id_tc26_gost_3410_2012_256_paramSetA 1 2 643 7 1 2 1 1 1 */ 1184, /* OBJ_id_tc26_gost_3410_2012_256_paramSetB 1 2 643 7 1 2 1 1 2 */ 1185, /* OBJ_id_tc26_gost_3410_2012_256_paramSetC 1 2 643 7 1 2 1 1 3 */ diff --git a/freebsd/crypto/openssl/crypto/ocsp/ocsp_ext.c b/freebsd/crypto/openssl/crypto/ocsp/ocsp_ext.c index d4efda7c..ea2f6289 100644 --- a/freebsd/crypto/openssl/crypto/ocsp/ocsp_ext.c +++ b/freebsd/crypto/openssl/crypto/ocsp/ocsp_ext.c @@ -1,7 +1,7 @@ #include <machine/rtems-bsd-user-space.h> /* - * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -441,6 +441,7 @@ X509_EXTENSION *OCSP_url_svcloc_new(X509_NAME *issuer, const char **urls) if ((sloc = OCSP_SERVICELOC_new()) == NULL) goto err; + X509_NAME_free(sloc->issuer); if ((sloc->issuer = X509_NAME_dup(issuer)) == NULL) goto err; if (urls && *urls @@ -451,12 +452,11 @@ X509_EXTENSION *OCSP_url_svcloc_new(X509_NAME *issuer, const char **urls) goto err; if ((ad->method = OBJ_nid2obj(NID_ad_OCSP)) == NULL) goto err; - if ((ad->location = GENERAL_NAME_new()) == NULL) - goto err; if ((ia5 = ASN1_IA5STRING_new()) == NULL) goto err; if (!ASN1_STRING_set((ASN1_STRING *)ia5, *urls, -1)) goto err; + /* ad->location is allocated inside ACCESS_DESCRIPTION_new */ ad->location->type = GEN_URI; ad->location->d.ia5 = ia5; ia5 = NULL; diff --git a/freebsd/crypto/openssl/crypto/ocsp/ocsp_lib.c b/freebsd/crypto/openssl/crypto/ocsp/ocsp_lib.c index a9c05dd3..e4331eb9 100644 --- a/freebsd/crypto/openssl/crypto/ocsp/ocsp_lib.c +++ b/freebsd/crypto/openssl/crypto/ocsp/ocsp_lib.c @@ -1,7 +1,7 @@ #include <machine/rtems-bsd-user-space.h> /* - * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -90,7 +90,7 @@ OCSP_CERTID *OCSP_cert_id_new(const EVP_MD *dgst, return NULL; } -int OCSP_id_issuer_cmp(OCSP_CERTID *a, OCSP_CERTID *b) +int OCSP_id_issuer_cmp(const OCSP_CERTID *a, const OCSP_CERTID *b) { int ret; ret = OBJ_cmp(a->hashAlgorithm.algorithm, b->hashAlgorithm.algorithm); @@ -102,7 +102,7 @@ int OCSP_id_issuer_cmp(OCSP_CERTID *a, OCSP_CERTID *b) return ASN1_OCTET_STRING_cmp(&a->issuerKeyHash, &b->issuerKeyHash); } -int OCSP_id_cmp(OCSP_CERTID *a, OCSP_CERTID *b) +int OCSP_id_cmp(const OCSP_CERTID *a, const OCSP_CERTID *b) { int ret; ret = OCSP_id_issuer_cmp(a, b); diff --git a/freebsd/crypto/openssl/crypto/pem/pem_sign.c b/freebsd/crypto/openssl/crypto/pem/pem_sign.c index 5f35af05..6bf4c39c 100644 --- a/freebsd/crypto/openssl/crypto/pem/pem_sign.c +++ b/freebsd/crypto/openssl/crypto/pem/pem_sign.c @@ -1,7 +1,7 @@ #include <machine/rtems-bsd-user-space.h> /* - * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -33,7 +33,7 @@ int PEM_SignFinal(EVP_MD_CTX *ctx, unsigned char *sigret, int i, ret = 0; unsigned int m_len; - m = OPENSSL_malloc(EVP_PKEY_size(pkey) + 2); + m = OPENSSL_malloc(EVP_PKEY_size(pkey)); if (m == NULL) { PEMerr(PEM_F_PEM_SIGNFINAL, ERR_R_MALLOC_FAILURE); goto err; diff --git a/freebsd/crypto/openssl/crypto/rand/drbg_lib.c b/freebsd/crypto/openssl/crypto/rand/drbg_lib.c index 86dd1166..48f941ba 100644 --- a/freebsd/crypto/openssl/crypto/rand/drbg_lib.c +++ b/freebsd/crypto/openssl/crypto/rand/drbg_lib.c @@ -1,7 +1,7 @@ #include <machine/rtems-bsd-user-space.h> /* - * Copyright 2011-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2011-2019 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -190,8 +190,8 @@ static RAND_DRBG *rand_drbg_new(int secure, unsigned int flags, RAND_DRBG *parent) { - RAND_DRBG *drbg = secure ? - OPENSSL_secure_zalloc(sizeof(*drbg)) : OPENSSL_zalloc(sizeof(*drbg)); + RAND_DRBG *drbg = secure ? OPENSSL_secure_zalloc(sizeof(*drbg)) + : OPENSSL_zalloc(sizeof(*drbg)); if (drbg == NULL) { RANDerr(RAND_F_RAND_DRBG_NEW, ERR_R_MALLOC_FAILURE); diff --git a/freebsd/crypto/openssl/crypto/rand/rand_lib.c b/freebsd/crypto/openssl/crypto/rand/rand_lib.c index a6553d78..ea07ac6c 100644 --- a/freebsd/crypto/openssl/crypto/rand/rand_lib.c +++ b/freebsd/crypto/openssl/crypto/rand/rand_lib.c @@ -1,7 +1,7 @@ #include <machine/rtems-bsd-user-space.h> /* - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -139,7 +139,7 @@ size_t rand_drbg_get_entropy(RAND_DRBG *drbg, size_t entropy_available = 0; RAND_POOL *pool; - if (drbg->parent && drbg->strength > drbg->parent->strength) { + if (drbg->parent != NULL && drbg->strength > drbg->parent->strength) { /* * We currently don't support the algorithm from NIST SP 800-90C * 10.1.2 to use a weaker DRBG as source @@ -157,7 +157,7 @@ size_t rand_drbg_get_entropy(RAND_DRBG *drbg, return 0; } - if (drbg->parent) { + if (drbg->parent != NULL) { size_t bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/); unsigned char *buffer = rand_pool_add_begin(pool, bytes_needed); @@ -237,7 +237,7 @@ size_t rand_drbg_get_nonce(RAND_DRBG *drbg, struct { void * instance; int count; - } data = { 0 }; + } data = { NULL, 0 }; pool = rand_pool_new(0, min_len, max_len); if (pool == NULL) @@ -404,7 +404,7 @@ int RAND_poll(void) } else { /* fill random pool and seed the current legacy RNG */ pool = rand_pool_new(RAND_DRBG_STRENGTH, - RAND_DRBG_STRENGTH / 8, + (RAND_DRBG_STRENGTH + 7) / 8, RAND_POOL_MAX_LENGTH); if (pool == NULL) return 0; @@ -691,7 +691,7 @@ unsigned char *rand_pool_add_begin(RAND_POOL *pool, size_t len) if (pool->buffer == NULL) { RANDerr(RAND_F_RAND_POOL_ADD_BEGIN, ERR_R_INTERNAL_ERROR); - return 0; + return NULL; } return pool->buffer + pool->len; diff --git a/freebsd/crypto/openssl/crypto/rand/rand_unix.c b/freebsd/crypto/openssl/crypto/rand/rand_unix.c index d6eae343..a5d658e0 100644 --- a/freebsd/crypto/openssl/crypto/rand/rand_unix.c +++ b/freebsd/crypto/openssl/crypto/rand/rand_unix.c @@ -21,7 +21,7 @@ #include <stdio.h> #include "internal/dso.h" #if defined(__linux) -# include <sys/syscall.h> +# include <asm/unistd.h> #endif #if defined(__FreeBSD__) # include <sys/types.h> @@ -326,8 +326,8 @@ static ssize_t syscall_random(void *buf, size_t buflen) # endif /* Linux supports this since version 3.17 */ -# if defined(__linux) && defined(SYS_getrandom) - return syscall(SYS_getrandom, buf, buflen, 0); +# if defined(__linux) && defined(__NR_getrandom) + return syscall(__NR_getrandom, buf, buflen, 0); # elif (defined(__FreeBSD__) || defined(__NetBSD__)) && defined(KERN_ARND) return sysctl_random(buf, buflen); # else @@ -512,6 +512,29 @@ size_t rand_pool_acquire_entropy(RAND_POOL *pool) bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/); { size_t i; +#ifdef DEVRANDOM_WAIT + static int wait_done = 0; + + /* + * On some implementations reading from /dev/urandom is possible + * before it is initialized. Therefore we wait for /dev/random + * to be readable to make sure /dev/urandom is initialized. + */ + if (!wait_done && bytes_needed > 0) { + int f = open(DEVRANDOM_WAIT, O_RDONLY); + + if (f >= 0) { + fd_set fds; + + FD_ZERO(&fds); + FD_SET(f, &fds); + while (select(f+1, &fds, NULL, NULL, NULL) < 0 + && errno == EINTR); + close(f); + } + wait_done = 1; + } +#endif for (i = 0; bytes_needed > 0 && i < OSSL_NELEM(random_device_paths); i++) { ssize_t bytes = 0; diff --git a/freebsd/crypto/openssl/crypto/rand/randfile.c b/freebsd/crypto/openssl/crypto/rand/randfile.c index de3c15dc..44db456f 100644 --- a/freebsd/crypto/openssl/crypto/rand/randfile.c +++ b/freebsd/crypto/openssl/crypto/rand/randfile.c @@ -1,7 +1,7 @@ #include <machine/rtems-bsd-user-space.h> /* - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -256,7 +256,7 @@ const char *RAND_file_name(char *buf, size_t size) size_t len; int use_randfile = 1; -#if defined(_WIN32) && defined(CP_UTF8) +#if defined(_WIN32) && defined(CP_UTF8) && !defined(_WIN32_WCE) DWORD envlen; WCHAR *var; diff --git a/freebsd/crypto/openssl/crypto/rsa/rsa_ameth.c b/freebsd/crypto/openssl/crypto/rsa/rsa_ameth.c index ce3d0eee..a23e2483 100644 --- a/freebsd/crypto/openssl/crypto/rsa/rsa_ameth.c +++ b/freebsd/crypto/openssl/crypto/rsa/rsa_ameth.c @@ -1,7 +1,7 @@ #include <machine/rtems-bsd-user-space.h> /* - * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2006-2019 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -585,10 +585,12 @@ static RSA_PSS_PARAMS *rsa_ctx_to_pss(EVP_PKEY_CTX *pkctx) return NULL; if (saltlen == -1) { saltlen = EVP_MD_size(sigmd); - } else if (saltlen == -2) { + } else if (saltlen == -2 || saltlen == -3) { saltlen = EVP_PKEY_size(pk) - EVP_MD_size(sigmd) - 2; if ((EVP_PKEY_bits(pk) & 0x7) == 1) saltlen--; + if (saltlen < 0) + return NULL; } return rsa_pss_params_create(sigmd, mgf1md, saltlen); diff --git a/freebsd/crypto/openssl/crypto/rsa/rsa_gen.c b/freebsd/crypto/openssl/crypto/rsa/rsa_gen.c index 8143555e..22d99bb4 100644 --- a/freebsd/crypto/openssl/crypto/rsa/rsa_gen.c +++ b/freebsd/crypto/openssl/crypto/rsa/rsa_gen.c @@ -1,7 +1,7 @@ #include <machine/rtems-bsd-user-space.h> /* - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -389,8 +389,7 @@ static int rsa_builtin_keygen(RSA *rsa, int bits, int primes, BIGNUM *e_value, RSAerr(RSA_F_RSA_BUILTIN_KEYGEN, ERR_LIB_BN); ok = 0; } - if (ctx != NULL) - BN_CTX_end(ctx); + BN_CTX_end(ctx); BN_CTX_free(ctx); return ok; } diff --git a/freebsd/crypto/openssl/crypto/rsa/rsa_oaep.c b/freebsd/crypto/openssl/crypto/rsa/rsa_oaep.c index ca0314ff..a5e97506 100644 --- a/freebsd/crypto/openssl/crypto/rsa/rsa_oaep.c +++ b/freebsd/crypto/openssl/crypto/rsa/rsa_oaep.c @@ -1,7 +1,7 @@ #include <machine/rtems-bsd-user-space.h> /* - * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1999-2019 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -145,7 +145,7 @@ int RSA_padding_check_PKCS1_OAEP_mgf1(unsigned char *to, int tlen, * |num| is the length of the modulus; |flen| is the length of the * encoded message. Therefore, for any |from| that was obtained by * decrypting a ciphertext, we must have |flen| <= |num|. Similarly, - * num < 2 * mdlen + 2 must hold for the modulus irrespective of + * |num| >= 2 * |mdlen| + 2 must hold for the modulus irrespective of * the ciphertext, see PKCS #1 v2.2, section 7.1.2. * This does not leak any side-channel information. */ @@ -181,17 +181,16 @@ int RSA_padding_check_PKCS1_OAEP_mgf1(unsigned char *to, int tlen, from -= 1 & mask; *--em = *from & mask; } - from = em; /* * The first byte must be zero, however we must not leak if this is * true. See James H. Manger, "A Chosen Ciphertext Attack on RSA * Optimal Asymmetric Encryption Padding (OAEP) [...]", CRYPTO 2001). */ - good = constant_time_is_zero(from[0]); + good = constant_time_is_zero(em[0]); - maskedseed = from + 1; - maskeddb = from + 1 + mdlen; + maskedseed = em + 1; + maskeddb = em + 1 + mdlen; if (PKCS1_MGF1(seed, mdlen, maskeddb, dblen, mgf1md)) goto cleanup; @@ -232,29 +231,30 @@ int RSA_padding_check_PKCS1_OAEP_mgf1(unsigned char *to, int tlen, mlen = dblen - msg_index; /* - * For good measure, do this check in constant tine as well. + * For good measure, do this check in constant time as well. */ good &= constant_time_ge(tlen, mlen); /* - * Even though we can't fake result's length, we can pretend copying - * |tlen| bytes where |mlen| bytes would be real. Last |tlen| of |dblen| - * bytes are viewed as circular buffer with start at |tlen|-|mlen'|, - * where |mlen'| is "saturated" |mlen| value. Deducing information - * about failure or |mlen| would take attacker's ability to observe - * memory access pattern with byte granularity *as it occurs*. It - * should be noted that failure is indistinguishable from normal - * operation if |tlen| is fixed by protocol. + * Move the result in-place by |dblen|-|mdlen|-1-|mlen| bytes to the left. + * Then if |good| move |mlen| bytes from |db|+|mdlen|+1 to |to|. + * Otherwise leave |to| unchanged. + * Copy the memory back in a way that does not reveal the size of + * the data being copied via a timing side channel. This requires copying + * parts of the buffer multiple times based on the bits set in the real + * length. Clear bits do a non-copy with identical access pattern. + * The loop below has overall complexity of O(N*log(N)). */ - tlen = constant_time_select_int(constant_time_lt(dblen, tlen), dblen, tlen); - msg_index = constant_time_select_int(good, msg_index, dblen - tlen); - mlen = dblen - msg_index; - for (from = db + msg_index, mask = good, i = 0; i < tlen; i++) { - unsigned int equals = constant_time_eq(i, mlen); - - from -= dblen & equals; /* if (i == dblen) rewind */ - mask &= mask ^ equals; /* if (i == dblen) mask = 0 */ - to[i] = constant_time_select_8(mask, from[i], to[i]); + tlen = constant_time_select_int(constant_time_lt(dblen - mdlen - 1, tlen), + dblen - mdlen - 1, tlen); + for (msg_index = 1; msg_index < dblen - mdlen - 1; msg_index <<= 1) { + mask = ~constant_time_eq(msg_index & (dblen - mdlen - 1 - mlen), 0); + for (i = mdlen + 1; i < dblen - msg_index; i++) + db[i] = constant_time_select_8(mask, db[i + msg_index], db[i]); + } + for (i = 0; i < tlen; i++) { + mask = good & constant_time_lt(i, mlen); + to[i] = constant_time_select_8(mask, db[i + mdlen + 1], to[i]); } /* diff --git a/freebsd/crypto/openssl/crypto/rsa/rsa_ossl.c b/freebsd/crypto/openssl/crypto/rsa/rsa_ossl.c index 2257ba18..2c9ded71 100644 --- a/freebsd/crypto/openssl/crypto/rsa/rsa_ossl.c +++ b/freebsd/crypto/openssl/crypto/rsa/rsa_ossl.c @@ -1,7 +1,7 @@ #include <machine/rtems-bsd-user-space.h> /* - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -150,8 +150,7 @@ static int rsa_ossl_public_encrypt(int flen, const unsigned char *from, */ r = BN_bn2binpad(ret, to, num); err: - if (ctx != NULL) - BN_CTX_end(ctx); + BN_CTX_end(ctx); BN_CTX_free(ctx); OPENSSL_clear_free(buf, num); return r; @@ -356,8 +355,7 @@ static int rsa_ossl_private_encrypt(int flen, const unsigned char *from, */ r = BN_bn2binpad(res, to, num); err: - if (ctx != NULL) - BN_CTX_end(ctx); + BN_CTX_end(ctx); BN_CTX_free(ctx); OPENSSL_clear_free(buf, num); return r; @@ -483,11 +481,10 @@ static int rsa_ossl_private_decrypt(int flen, const unsigned char *from, goto err; } RSAerr(RSA_F_RSA_OSSL_PRIVATE_DECRYPT, RSA_R_PADDING_CHECK_FAILED); - err_clear_last_constant_time(r >= 0); + err_clear_last_constant_time(1 & ~constant_time_msb(r)); err: - if (ctx != NULL) - BN_CTX_end(ctx); + BN_CTX_end(ctx); BN_CTX_free(ctx); OPENSSL_clear_free(buf, num); return r; @@ -583,8 +580,7 @@ static int rsa_ossl_public_decrypt(int flen, const unsigned char *from, RSAerr(RSA_F_RSA_OSSL_PUBLIC_DECRYPT, RSA_R_PADDING_CHECK_FAILED); err: - if (ctx != NULL) - BN_CTX_end(ctx); + BN_CTX_end(ctx); BN_CTX_free(ctx); OPENSSL_clear_free(buf, num); return r; diff --git a/freebsd/crypto/openssl/crypto/rsa/rsa_pk1.c b/freebsd/crypto/openssl/crypto/rsa/rsa_pk1.c index 09b47e59..429be508 100644 --- a/freebsd/crypto/openssl/crypto/rsa/rsa_pk1.c +++ b/freebsd/crypto/openssl/crypto/rsa/rsa_pk1.c @@ -1,7 +1,7 @@ #include <machine/rtems-bsd-user-space.h> /* - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -194,15 +194,14 @@ int RSA_padding_check_PKCS1_type_2(unsigned char *to, int tlen, from -= 1 & mask; *--em = *from & mask; } - from = em; - good = constant_time_is_zero(from[0]); - good &= constant_time_eq(from[1], 2); + good = constant_time_is_zero(em[0]); + good &= constant_time_eq(em[1], 2); /* scan over padding data */ found_zero_byte = 0; for (i = 2; i < num; i++) { - unsigned int equals0 = constant_time_is_zero(from[i]); + unsigned int equals0 = constant_time_is_zero(em[i]); zero_index = constant_time_select_int(~found_zero_byte & equals0, i, zero_index); @@ -210,7 +209,7 @@ int RSA_padding_check_PKCS1_type_2(unsigned char *to, int tlen, } /* - * PS must be at least 8 bytes long, and it starts two bytes into |from|. + * PS must be at least 8 bytes long, and it starts two bytes into |em|. * If we never found a 0-byte, then |zero_index| is 0 and the check * also fails. */ @@ -229,24 +228,25 @@ int RSA_padding_check_PKCS1_type_2(unsigned char *to, int tlen, good &= constant_time_ge(tlen, mlen); /* - * Even though we can't fake result's length, we can pretend copying - * |tlen| bytes where |mlen| bytes would be real. Last |tlen| of |num| - * bytes are viewed as circular buffer with start at |tlen|-|mlen'|, - * where |mlen'| is "saturated" |mlen| value. Deducing information - * about failure or |mlen| would take attacker's ability to observe - * memory access pattern with byte granularity *as it occurs*. It - * should be noted that failure is indistinguishable from normal - * operation if |tlen| is fixed by protocol. + * Move the result in-place by |num|-11-|mlen| bytes to the left. + * Then if |good| move |mlen| bytes from |em|+11 to |to|. + * Otherwise leave |to| unchanged. + * Copy the memory back in a way that does not reveal the size of + * the data being copied via a timing side channel. This requires copying + * parts of the buffer multiple times based on the bits set in the real + * length. Clear bits do a non-copy with identical access pattern. + * The loop below has overall complexity of O(N*log(N)). */ - tlen = constant_time_select_int(constant_time_lt(num, tlen), num, tlen); - msg_index = constant_time_select_int(good, msg_index, num - tlen); - mlen = num - msg_index; - for (from += msg_index, mask = good, i = 0; i < tlen; i++) { - unsigned int equals = constant_time_eq(i, mlen); - - from -= tlen & equals; /* if (i == mlen) rewind */ - mask &= mask ^ equals; /* if (i == mlen) mask = 0 */ - to[i] = constant_time_select_8(mask, from[i], to[i]); + tlen = constant_time_select_int(constant_time_lt(num - 11, tlen), + num - 11, tlen); + for (msg_index = 1; msg_index < num - 11; msg_index <<= 1) { + mask = ~constant_time_eq(msg_index & (num - 11 - mlen), 0); + for (i = 11; i < num - msg_index; i++) + em[i] = constant_time_select_8(mask, em[i + msg_index], em[i]); + } + for (i = 0; i < tlen; i++) { + mask = good & constant_time_lt(i, mlen); + to[i] = constant_time_select_8(mask, em[i + 11], to[i]); } OPENSSL_clear_free(em, num); diff --git a/freebsd/crypto/openssl/crypto/rsa/rsa_pmeth.c b/freebsd/crypto/openssl/crypto/rsa/rsa_pmeth.c index d0992e90..0c305e84 100644 --- a/freebsd/crypto/openssl/crypto/rsa/rsa_pmeth.c +++ b/freebsd/crypto/openssl/crypto/rsa/rsa_pmeth.c @@ -1,7 +1,7 @@ #include <machine/rtems-bsd-user-space.h> /* - * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2006-2019 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -9,6 +9,8 @@ * https://www.openssl.org/source/license.html */ +#include "internal/constant_time_locl.h" + #include <stdio.h> #include "internal/cryptlib.h" #include <openssl/asn1t.h> @@ -56,7 +58,7 @@ static int pkey_rsa_init(EVP_PKEY_CTX *ctx) if (rctx == NULL) return 0; - rctx->nbits = 1024; + rctx->nbits = 2048; rctx->primes = RSA_DEFAULT_PRIME_NUM; if (pkey_ctx_is_pss(ctx)) rctx->pad_mode = RSA_PKCS1_PSS_PADDING; @@ -342,10 +344,9 @@ static int pkey_rsa_decrypt(EVP_PKEY_CTX *ctx, ret = RSA_private_decrypt(inlen, in, out, ctx->pkey->pkey.rsa, rctx->pad_mode); } - if (ret < 0) - return ret; - *outlen = ret; - return 1; + *outlen = constant_time_select_s(constant_time_msb_s(ret), *outlen, ret); + ret = constant_time_select_int(constant_time_msb(ret), ret, 1); + return ret; } static int check_padding_md(const EVP_MD *md, int padding) diff --git a/freebsd/crypto/openssl/crypto/rsa/rsa_ssl.c b/freebsd/crypto/openssl/crypto/rsa/rsa_ssl.c index 9b0edb3f..b5d91c90 100644 --- a/freebsd/crypto/openssl/crypto/rsa/rsa_ssl.c +++ b/freebsd/crypto/openssl/crypto/rsa/rsa_ssl.c @@ -1,7 +1,7 @@ #include <machine/rtems-bsd-user-space.h> /* - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -57,7 +57,7 @@ int RSA_padding_add_SSLv23(unsigned char *to, int tlen, /* * Copy of RSA_padding_check_PKCS1_type_2 with a twist that rejects padding - * if nul delimiter is preceded by 8 consecutive 0x03 bytes. It also + * if nul delimiter is not preceded by 8 consecutive 0x03 bytes. It also * preserves error code reporting for backward compatibility. */ int RSA_padding_check_SSLv23(unsigned char *to, int tlen, @@ -69,7 +69,10 @@ int RSA_padding_check_SSLv23(unsigned char *to, int tlen, unsigned int good, found_zero_byte, mask, threes_in_row; int zero_index = 0, msg_index, mlen = -1, err; - if (flen < 10) { + if (tlen <= 0 || flen <= 0) + return -1; + + if (flen > num || num < 11) { RSAerr(RSA_F_RSA_PADDING_CHECK_SSLV23, RSA_R_DATA_TOO_SMALL); return -1; } @@ -91,10 +94,9 @@ int RSA_padding_check_SSLv23(unsigned char *to, int tlen, from -= 1 & mask; *--em = *from & mask; } - from = em; - good = constant_time_is_zero(from[0]); - good &= constant_time_eq(from[1], 2); + good = constant_time_is_zero(em[0]); + good &= constant_time_eq(em[1], 2); err = constant_time_select_int(good, 0, RSA_R_BLOCK_TYPE_IS_NOT_02); mask = ~good; @@ -102,18 +104,18 @@ int RSA_padding_check_SSLv23(unsigned char *to, int tlen, found_zero_byte = 0; threes_in_row = 0; for (i = 2; i < num; i++) { - unsigned int equals0 = constant_time_is_zero(from[i]); + unsigned int equals0 = constant_time_is_zero(em[i]); zero_index = constant_time_select_int(~found_zero_byte & equals0, i, zero_index); found_zero_byte |= equals0; threes_in_row += 1 & ~found_zero_byte; - threes_in_row &= found_zero_byte | constant_time_eq(from[i], 3); + threes_in_row &= found_zero_byte | constant_time_eq(em[i], 3); } /* - * PS must be at least 8 bytes long, and it starts two bytes into |from|. + * PS must be at least 8 bytes long, and it starts two bytes into |em|. * If we never found a 0-byte, then |zero_index| is 0 and the check * also fails. */ @@ -122,7 +124,7 @@ int RSA_padding_check_SSLv23(unsigned char *to, int tlen, RSA_R_NULL_BEFORE_BLOCK_MISSING); mask = ~good; - good &= constant_time_lt(threes_in_row, 8); + good &= constant_time_ge(threes_in_row, 8); err = constant_time_select_int(mask | good, err, RSA_R_SSLV3_ROLLBACK_ATTACK); mask = ~good; @@ -141,24 +143,25 @@ int RSA_padding_check_SSLv23(unsigned char *to, int tlen, err = constant_time_select_int(mask | good, err, RSA_R_DATA_TOO_LARGE); /* - * Even though we can't fake result's length, we can pretend copying - * |tlen| bytes where |mlen| bytes would be real. Last |tlen| of |num| - * bytes are viewed as circular buffer with start at |tlen|-|mlen'|, - * where |mlen'| is "saturated" |mlen| value. Deducing information - * about failure or |mlen| would take attacker's ability to observe - * memory access pattern with byte granularity *as it occurs*. It - * should be noted that failure is indistinguishable from normal - * operation if |tlen| is fixed by protocol. + * Move the result in-place by |num|-11-|mlen| bytes to the left. + * Then if |good| move |mlen| bytes from |em|+11 to |to|. + * Otherwise leave |to| unchanged. + * Copy the memory back in a way that does not reveal the size of + * the data being copied via a timing side channel. This requires copying + * parts of the buffer multiple times based on the bits set in the real + * length. Clear bits do a non-copy with identical access pattern. + * The loop below has overall complexity of O(N*log(N)). */ - tlen = constant_time_select_int(constant_time_lt(num, tlen), num, tlen); - msg_index = constant_time_select_int(good, msg_index, num - tlen); - mlen = num - msg_index; - for (from += msg_index, mask = good, i = 0; i < tlen; i++) { - unsigned int equals = constant_time_eq(i, mlen); - - from -= tlen & equals; /* if (i == mlen) rewind */ - mask &= mask ^ equals; /* if (i == mlen) mask = 0 */ - to[i] = constant_time_select_8(mask, from[i], to[i]); + tlen = constant_time_select_int(constant_time_lt(num - 11, tlen), + num - 11, tlen); + for (msg_index = 1; msg_index < num - 11; msg_index <<= 1) { + mask = ~constant_time_eq(msg_index & (num - 11 - mlen), 0); + for (i = 11; i < num - msg_index; i++) + em[i] = constant_time_select_8(mask, em[i + msg_index], em[i]); + } + for (i = 0; i < tlen; i++) { + mask = good & constant_time_lt(i, mlen); + to[i] = constant_time_select_8(mask, em[i + 11], to[i]); } OPENSSL_clear_free(em, num); diff --git a/freebsd/crypto/openssl/crypto/rsa/rsa_x931g.c b/freebsd/crypto/openssl/crypto/rsa/rsa_x931g.c index 9435cad8..36857a12 100644 --- a/freebsd/crypto/openssl/crypto/rsa/rsa_x931g.c +++ b/freebsd/crypto/openssl/crypto/rsa/rsa_x931g.c @@ -1,7 +1,7 @@ #include <machine/rtems-bsd-user-space.h> /* - * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -135,8 +135,7 @@ int RSA_X931_derive_ex(RSA *rsa, BIGNUM *p1, BIGNUM *p2, BIGNUM *q1, ret = 1; err: - if (ctx) - BN_CTX_end(ctx); + BN_CTX_end(ctx); BN_CTX_free(ctx); BN_CTX_free(ctx2); @@ -190,8 +189,7 @@ int RSA_X931_generate_key_ex(RSA *rsa, int bits, const BIGNUM *e, ok = 1; error: - if (ctx) - BN_CTX_end(ctx); + BN_CTX_end(ctx); BN_CTX_free(ctx); if (ok) diff --git a/freebsd/crypto/openssl/crypto/sha/keccak1600.c b/freebsd/crypto/openssl/crypto/sha/keccak1600.c index 082810d7..7ab6c6f4 100644 --- a/freebsd/crypto/openssl/crypto/sha/keccak1600.c +++ b/freebsd/crypto/openssl/crypto/sha/keccak1600.c @@ -1,7 +1,7 @@ #include <machine/rtems-bsd-user-space.h> /* - * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -80,30 +80,30 @@ static const unsigned char rhotates[5][5] = { }; static const uint64_t iotas[] = { - BIT_INTERLEAVE ? 0x0000000000000001U : 0x0000000000000001U, - BIT_INTERLEAVE ? 0x0000008900000000U : 0x0000000000008082U, - BIT_INTERLEAVE ? 0x8000008b00000000U : 0x800000000000808aU, - BIT_INTERLEAVE ? 0x8000808000000000U : 0x8000000080008000U, - BIT_INTERLEAVE ? 0x0000008b00000001U : 0x000000000000808bU, - BIT_INTERLEAVE ? 0x0000800000000001U : 0x0000000080000001U, - BIT_INTERLEAVE ? 0x8000808800000001U : 0x8000000080008081U, - BIT_INTERLEAVE ? 0x8000008200000001U : 0x8000000000008009U, - BIT_INTERLEAVE ? 0x0000000b00000000U : 0x000000000000008aU, - BIT_INTERLEAVE ? 0x0000000a00000000U : 0x0000000000000088U, - BIT_INTERLEAVE ? 0x0000808200000001U : 0x0000000080008009U, - BIT_INTERLEAVE ? 0x0000800300000000U : 0x000000008000000aU, - BIT_INTERLEAVE ? 0x0000808b00000001U : 0x000000008000808bU, - BIT_INTERLEAVE ? 0x8000000b00000001U : 0x800000000000008bU, - BIT_INTERLEAVE ? 0x8000008a00000001U : 0x8000000000008089U, - BIT_INTERLEAVE ? 0x8000008100000001U : 0x8000000000008003U, - BIT_INTERLEAVE ? 0x8000008100000000U : 0x8000000000008002U, - BIT_INTERLEAVE ? 0x8000000800000000U : 0x8000000000000080U, - BIT_INTERLEAVE ? 0x0000008300000000U : 0x000000000000800aU, - BIT_INTERLEAVE ? 0x8000800300000000U : 0x800000008000000aU, - BIT_INTERLEAVE ? 0x8000808800000001U : 0x8000000080008081U, - BIT_INTERLEAVE ? 0x8000008800000000U : 0x8000000000008080U, - BIT_INTERLEAVE ? 0x0000800000000001U : 0x0000000080000001U, - BIT_INTERLEAVE ? 0x8000808200000000U : 0x8000000080008008U + BIT_INTERLEAVE ? 0x0000000000000001ULL : 0x0000000000000001ULL, + BIT_INTERLEAVE ? 0x0000008900000000ULL : 0x0000000000008082ULL, + BIT_INTERLEAVE ? 0x8000008b00000000ULL : 0x800000000000808aULL, + BIT_INTERLEAVE ? 0x8000808000000000ULL : 0x8000000080008000ULL, + BIT_INTERLEAVE ? 0x0000008b00000001ULL : 0x000000000000808bULL, + BIT_INTERLEAVE ? 0x0000800000000001ULL : 0x0000000080000001ULL, + BIT_INTERLEAVE ? 0x8000808800000001ULL : 0x8000000080008081ULL, + BIT_INTERLEAVE ? 0x8000008200000001ULL : 0x8000000000008009ULL, + BIT_INTERLEAVE ? 0x0000000b00000000ULL : 0x000000000000008aULL, + BIT_INTERLEAVE ? 0x0000000a00000000ULL : 0x0000000000000088ULL, + BIT_INTERLEAVE ? 0x0000808200000001ULL : 0x0000000080008009ULL, + BIT_INTERLEAVE ? 0x0000800300000000ULL : 0x000000008000000aULL, + BIT_INTERLEAVE ? 0x0000808b00000001ULL : 0x000000008000808bULL, + BIT_INTERLEAVE ? 0x8000000b00000001ULL : 0x800000000000008bULL, + BIT_INTERLEAVE ? 0x8000008a00000001ULL : 0x8000000000008089ULL, + BIT_INTERLEAVE ? 0x8000008100000001ULL : 0x8000000000008003ULL, + BIT_INTERLEAVE ? 0x8000008100000000ULL : 0x8000000000008002ULL, + BIT_INTERLEAVE ? 0x8000000800000000ULL : 0x8000000000000080ULL, + BIT_INTERLEAVE ? 0x0000008300000000ULL : 0x000000000000800aULL, + BIT_INTERLEAVE ? 0x8000800300000000ULL : 0x800000008000000aULL, + BIT_INTERLEAVE ? 0x8000808800000001ULL : 0x8000000080008081ULL, + BIT_INTERLEAVE ? 0x8000008800000000ULL : 0x8000000000008080ULL, + BIT_INTERLEAVE ? 0x0000800000000001ULL : 0x0000000080000001ULL, + BIT_INTERLEAVE ? 0x8000808200000000ULL : 0x8000000080008008ULL }; #if defined(KECCAK_REF) diff --git a/freebsd/crypto/openssl/crypto/x509/x509_lu.c b/freebsd/crypto/openssl/crypto/x509/x509_lu.c index 5343ccfb..42010e62 100644 --- a/freebsd/crypto/openssl/crypto/x509/x509_lu.c +++ b/freebsd/crypto/openssl/crypto/x509/x509_lu.c @@ -1,7 +1,7 @@ #include <machine/rtems-bsd-user-space.h> /* - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -299,6 +299,9 @@ int X509_STORE_CTX_get_by_subject(X509_STORE_CTX *vs, X509_LOOKUP_TYPE type, if (ctx == NULL) return 0; + stmp.type = X509_LU_NONE; + stmp.data.ptr = NULL; + CRYPTO_THREAD_write_lock(ctx->lock); tmp = X509_OBJECT_retrieve_by_subject(ctx->objs, type, name); CRYPTO_THREAD_unlock(ctx->lock); diff --git a/freebsd/crypto/openssl/crypto/x509v3/v3_genn.c b/freebsd/crypto/openssl/crypto/x509v3/v3_genn.c index 7fcc2193..7c78c9ab 100644 --- a/freebsd/crypto/openssl/crypto/x509v3/v3_genn.c +++ b/freebsd/crypto/openssl/crypto/x509v3/v3_genn.c @@ -1,7 +1,7 @@ #include <machine/rtems-bsd-user-space.h> /* - * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1999-2019 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -145,7 +145,7 @@ void GENERAL_NAME_set0_value(GENERAL_NAME *a, int type, void *value) a->type = type; } -void *GENERAL_NAME_get0_value(GENERAL_NAME *a, int *ptype) +void *GENERAL_NAME_get0_value(const GENERAL_NAME *a, int *ptype) { if (ptype) *ptype = a->type; @@ -190,7 +190,7 @@ int GENERAL_NAME_set0_othername(GENERAL_NAME *gen, return 1; } -int GENERAL_NAME_get0_otherName(GENERAL_NAME *gen, +int GENERAL_NAME_get0_otherName(const GENERAL_NAME *gen, ASN1_OBJECT **poid, ASN1_TYPE **pvalue) { if (gen->type != GEN_OTHERNAME) diff --git a/freebsd/crypto/openssl/e_os.h b/freebsd/crypto/openssl/e_os.h index 8e6efa96..e9ce6c9c 100644 --- a/freebsd/crypto/openssl/e_os.h +++ b/freebsd/crypto/openssl/e_os.h @@ -1,5 +1,5 @@ /* - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -27,10 +27,9 @@ * set this to a comma-separated list of 'random' device files to try out. By * default, we will try to read at least one of these files */ -# if defined(__s390__) -# define DEVRANDOM "/dev/prandom","/dev/urandom","/dev/hwrng","/dev/random" -# else -# define DEVRANDOM "/dev/urandom","/dev/random","/dev/srandom" +# define DEVRANDOM "/dev/urandom", "/dev/random", "/dev/hwrng", "/dev/srandom" +# ifdef __linux +# define DEVRANDOM_WAIT "/dev/random" # endif # endif # if !defined(OPENSSL_NO_EGD) && !defined(DEVRANDOM_EGD) @@ -39,7 +38,7 @@ * sockets will be tried in the order listed in case accessing the device * files listed in DEVRANDOM did not return enough randomness. */ -# define DEVRANDOM_EGD "/var/run/egd-pool","/dev/egd-pool","/etc/egd-pool","/etc/entropy" +# define DEVRANDOM_EGD "/var/run/egd-pool", "/dev/egd-pool", "/etc/egd-pool", "/etc/entropy" # endif # if defined(OPENSSL_SYS_VXWORKS) || defined(OPENSSL_SYS_UEFI) diff --git a/freebsd/crypto/openssl/engines/e_padlock.c b/freebsd/crypto/openssl/engines/e_padlock.c index 9688d5f3..98cff372 100644 --- a/freebsd/crypto/openssl/engines/e_padlock.c +++ b/freebsd/crypto/openssl/engines/e_padlock.c @@ -1,7 +1,7 @@ #include <machine/rtems-bsd-user-space.h> /* - * Copyright 2004-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2004-2019 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -43,7 +43,7 @@ */ # undef COMPILE_HW_PADLOCK -# if !defined(I386_ONLY) && defined(PADLOCK_ASM) +# if defined(PADLOCK_ASM) # define COMPILE_HW_PADLOCK # ifdef OPENSSL_NO_DYNAMIC_ENGINE static ENGINE *ENGINE_padlock(void); @@ -150,7 +150,7 @@ static int padlock_init(ENGINE *e) * This stuff is needed if this ENGINE is being compiled into a * self-contained shared-library. */ -# ifdef DYNAMIC_ENGINE +# ifndef OPENSSL_NO_DYNAMIC_ENGINE static int padlock_bind_fn(ENGINE *e, const char *id) { if (id && (strcmp(id, padlock_id) != 0)) { @@ -166,7 +166,7 @@ static int padlock_bind_fn(ENGINE *e, const char *id) IMPLEMENT_DYNAMIC_CHECK_FN() IMPLEMENT_DYNAMIC_BIND_FN(padlock_bind_fn) -# endif /* DYNAMIC_ENGINE */ +# endif /* !OPENSSL_NO_DYNAMIC_ENGINE */ /* ===== Here comes the "real" engine ===== */ /* Some AES-related constants */ diff --git a/freebsd/crypto/openssl/include/internal/dsoerr.h b/freebsd/crypto/openssl/include/internal/dsoerr.h index a54a1854..0edf277f 100644 --- a/freebsd/crypto/openssl/include/internal/dsoerr.h +++ b/freebsd/crypto/openssl/include/internal/dsoerr.h @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -13,11 +13,9 @@ # include <openssl/opensslconf.h> -# ifndef OPENSSL_NO_DSO - -# ifdef __cplusplus +# ifdef __cplusplus extern "C" -# endif +# endif int ERR_load_DSO_strings(void); /* @@ -79,5 +77,4 @@ int ERR_load_DSO_strings(void); # define DSO_R_UNLOAD_FAILED 107 # define DSO_R_UNSUPPORTED 108 -# endif #endif diff --git a/freebsd/crypto/openssl/include/internal/refcount.h b/freebsd/crypto/openssl/include/internal/refcount.h index 75d70a64..d2364c62 100644 --- a/freebsd/crypto/openssl/include/internal/refcount.h +++ b/freebsd/crypto/openssl/include/internal/refcount.h @@ -1,5 +1,5 @@ /* - * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -79,7 +79,7 @@ static __inline__ int CRYPTO_DOWN_REF(int *val, int *ret, void *lock) typedef volatile int CRYPTO_REF_COUNT; -# if (defined(_M_ARM) && _M_ARM>=7) || defined(_M_ARM64) +# if (defined(_M_ARM) && _M_ARM>=7 && !defined(_WIN32_WCE)) || defined(_M_ARM64) # include <intrin.h> # if defined(_M_ARM64) && !defined(_ARM_BARRIER_ISH) # define _ARM_BARRIER_ISH _ARM64_BARRIER_ISH @@ -99,7 +99,17 @@ static __inline int CRYPTO_DOWN_REF(volatile int *val, int *ret, void *lock) return 1; } # else -# pragma intrinsic(_InterlockedExchangeAdd) +# if !defined(_WIN32_WCE) +# pragma intrinsic(_InterlockedExchangeAdd) +# else +# if _WIN32_WCE >= 0x600 + extern long __cdecl _InterlockedExchangeAdd(long volatile*, long); +# else + // under Windows CE we still have old-style Interlocked* functions + extern long __cdecl InterlockedExchangeAdd(long volatile*, long); +# define _InterlockedExchangeAdd InterlockedExchangeAdd +# endif +# endif static __inline int CRYPTO_UP_REF(volatile int *val, int *ret, void *lock) { diff --git a/freebsd/crypto/openssl/include/internal/tsan_assist.h b/freebsd/crypto/openssl/include/internal/tsan_assist.h index 38ba0c7e..d41ebb34 100644 --- a/freebsd/crypto/openssl/include/internal/tsan_assist.h +++ b/freebsd/crypto/openssl/include/internal/tsan_assist.h @@ -77,7 +77,7 @@ #elif defined(_MSC_VER) && _MSC_VER>=1200 \ && (defined(_M_IX86) || defined(_M_AMD64) || defined(_M_X64) || \ - defined(_M_ARM64) || (defined(_M_ARM) && _M_ARM >= 7)) + defined(_M_ARM64) || (defined(_M_ARM) && _M_ARM >= 7 && !defined(_WIN32_WCE))) /* * There is subtle dependency on /volatile:<iso|ms> command-line option. * "ms" implies same semantic as memory_order_acquire for loads and diff --git a/freebsd/crypto/openssl/include/openssl/err.h b/freebsd/crypto/openssl/include/openssl/err.h index 6cae1a36..b49f8812 100644 --- a/freebsd/crypto/openssl/include/openssl/err.h +++ b/freebsd/crypto/openssl/include/openssl/err.h @@ -1,5 +1,5 @@ /* - * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -37,6 +37,7 @@ extern "C" { # define ERR_TXT_STRING 0x02 # define ERR_FLAG_MARK 0x01 +# define ERR_FLAG_CLEAR 0x02 # define ERR_NUM_ERRORS 16 typedef struct err_state_st { diff --git a/freebsd/crypto/openssl/include/openssl/evp.h b/freebsd/crypto/openssl/include/openssl/evp.h index 9f05b5a3..dd1117d0 100644 --- a/freebsd/crypto/openssl/include/openssl/evp.h +++ b/freebsd/crypto/openssl/include/openssl/evp.h @@ -995,6 +995,7 @@ int EVP_PKEY_set_type_str(EVP_PKEY *pkey, const char *str, int len); int EVP_PKEY_set_alias_type(EVP_PKEY *pkey, int type); # ifndef OPENSSL_NO_ENGINE int EVP_PKEY_set1_engine(EVP_PKEY *pkey, ENGINE *e); +ENGINE *EVP_PKEY_get0_engine(const EVP_PKEY *pkey); # endif int EVP_PKEY_assign(EVP_PKEY *pkey, int type, void *key); void *EVP_PKEY_get0(const EVP_PKEY *pkey); diff --git a/freebsd/crypto/openssl/include/openssl/obj_mac.h b/freebsd/crypto/openssl/include/openssl/obj_mac.h index 31fad464..47dafe48 100644 --- a/freebsd/crypto/openssl/include/openssl/obj_mac.h +++ b/freebsd/crypto/openssl/include/openssl/obj_mac.h @@ -4280,7 +4280,7 @@ #define SN_id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15 "id-tc26-wrap-gostr3412-2015-kuznyechik-kexp15" #define NID_id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15 1183 -#define OBJ_id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15 OBJ_id_tc26_wrap_gostr3412_2015_magma,1L +#define OBJ_id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15 OBJ_id_tc26_wrap_gostr3412_2015_kuznyechik,1L #define SN_id_tc26_constants "id-tc26-constants" #define NID_id_tc26_constants 994 diff --git a/freebsd/crypto/openssl/include/openssl/ocsp.h b/freebsd/crypto/openssl/include/openssl/ocsp.h index 0a17166b..8582fe1e 100644 --- a/freebsd/crypto/openssl/include/openssl/ocsp.h +++ b/freebsd/crypto/openssl/include/openssl/ocsp.h @@ -1,5 +1,5 @@ /* - * Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -229,8 +229,8 @@ int OCSP_request_verify(OCSP_REQUEST *req, STACK_OF(X509) *certs, int OCSP_parse_url(const char *url, char **phost, char **pport, char **ppath, int *pssl); -int OCSP_id_issuer_cmp(OCSP_CERTID *a, OCSP_CERTID *b); -int OCSP_id_cmp(OCSP_CERTID *a, OCSP_CERTID *b); +int OCSP_id_issuer_cmp(const OCSP_CERTID *a, const OCSP_CERTID *b); +int OCSP_id_cmp(const OCSP_CERTID *a, const OCSP_CERTID *b); int OCSP_request_onereq_count(OCSP_REQUEST *req); OCSP_ONEREQ *OCSP_request_onereq_get0(OCSP_REQUEST *req, int i); diff --git a/freebsd/crypto/openssl/include/openssl/opensslv.h b/freebsd/crypto/openssl/include/openssl/opensslv.h index e1e4f224..e4f3ffe9 100644 --- a/freebsd/crypto/openssl/include/openssl/opensslv.h +++ b/freebsd/crypto/openssl/include/openssl/opensslv.h @@ -1,5 +1,5 @@ /* - * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1999-2019 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -39,8 +39,8 @@ extern "C" { * (Prior to 0.9.5a beta1, a different scheme was used: MMNNFFRBB for * major minor fix final patch/beta) */ -# define OPENSSL_VERSION_NUMBER 0x1010102fL -# define OPENSSL_VERSION_TEXT "OpenSSL 1.1.1b-freebsd 26 Feb 2019" +# define OPENSSL_VERSION_NUMBER 0x1010103fL +# define OPENSSL_VERSION_TEXT "OpenSSL 1.1.1c-freebsd 28 May 2019" /*- * The macros below are to be used for shared library (.so, .dll, ...) diff --git a/freebsd/crypto/openssl/include/openssl/ssl.h b/freebsd/crypto/openssl/include/openssl/ssl.h index 48e1152a..f93dc68f 100644 --- a/freebsd/crypto/openssl/include/openssl/ssl.h +++ b/freebsd/crypto/openssl/include/openssl/ssl.h @@ -2139,7 +2139,7 @@ size_t SSL_CTX_get_num_tickets(const SSL_CTX *ctx); # define SSL_cache_hit(s) SSL_session_reused(s) # endif -__owur int SSL_session_reused(SSL *s); +__owur int SSL_session_reused(const SSL *s); __owur int SSL_is_server(const SSL *s); __owur __owur SSL_CONF_CTX *SSL_CONF_CTX_new(void); diff --git a/freebsd/crypto/openssl/include/openssl/x509v3.h b/freebsd/crypto/openssl/include/openssl/x509v3.h index fe1791c6..9ea20275 100644 --- a/freebsd/crypto/openssl/include/openssl/x509v3.h +++ b/freebsd/crypto/openssl/include/openssl/x509v3.h @@ -1,5 +1,5 @@ /* - * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1999-2019 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -497,10 +497,10 @@ DECLARE_ASN1_FUNCTIONS(OTHERNAME) DECLARE_ASN1_FUNCTIONS(EDIPARTYNAME) int OTHERNAME_cmp(OTHERNAME *a, OTHERNAME *b); void GENERAL_NAME_set0_value(GENERAL_NAME *a, int type, void *value); -void *GENERAL_NAME_get0_value(GENERAL_NAME *a, int *ptype); +void *GENERAL_NAME_get0_value(const GENERAL_NAME *a, int *ptype); int GENERAL_NAME_set0_othername(GENERAL_NAME *gen, ASN1_OBJECT *oid, ASN1_TYPE *value); -int GENERAL_NAME_get0_otherName(GENERAL_NAME *gen, +int GENERAL_NAME_get0_otherName(const GENERAL_NAME *gen, ASN1_OBJECT **poid, ASN1_TYPE **pvalue); char *i2s_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method, diff --git a/freebsd/crypto/openssl/ssl/ssl_lib.c b/freebsd/crypto/openssl/ssl/ssl_lib.c index 1516f492..9c2c9dac 100644 --- a/freebsd/crypto/openssl/ssl/ssl_lib.c +++ b/freebsd/crypto/openssl/ssl/ssl_lib.c @@ -4480,7 +4480,7 @@ int ssl_handshake_hash(SSL *s, unsigned char *out, size_t outlen, return ret; } -int SSL_session_reused(SSL *s) +int SSL_session_reused(const SSL *s) { return s->hit; } @@ -5072,6 +5072,11 @@ int SSL_client_hello_get1_extensions_present(SSL *s, int **out, size_t *outlen) if (ext->present) num++; } + if (num == 0) { + *out = NULL; + *outlen = 0; + return 1; + } if ((present = OPENSSL_malloc(sizeof(*present) * num)) == NULL) { SSLerr(SSL_F_SSL_CLIENT_HELLO_GET1_EXTENSIONS_PRESENT, ERR_R_MALLOC_FAILURE); diff --git a/freebsd/crypto/openssl/ssl/ssl_locl.h b/freebsd/crypto/openssl/ssl/ssl_locl.h index f326399e..0cf3893e 100644 --- a/freebsd/crypto/openssl/ssl/ssl_locl.h +++ b/freebsd/crypto/openssl/ssl/ssl_locl.h @@ -574,7 +574,6 @@ struct ssl_session_st { /* Session lifetime hint in seconds */ unsigned long tick_lifetime_hint; uint32_t tick_age_add; - int tick_identity; /* Max number of bytes that can be sent as early data */ uint32_t max_early_data; /* The ALPN protocol selected for this session */ @@ -1356,6 +1355,13 @@ struct ssl_st { * as this extension is optional on server side. */ uint8_t max_fragment_len_mode; + + /* + * On the client side the number of ticket identities we sent in the + * ClientHello. On the server side the identity of the ticket we + * selected. + */ + int tick_identity; } ext; /* @@ -1509,7 +1515,7 @@ typedef struct cert_pkey_st CERT_PKEY; * CERT_PKEY entries */ typedef struct { - int nid; /* NID of pubic key algorithm */ + int nid; /* NID of public key algorithm */ uint32_t amask; /* authmask corresponding to key type */ } SSL_CERT_LOOKUP; @@ -2052,9 +2058,6 @@ typedef enum downgrade_en { #define TLSEXT_KEX_MODE_FLAG_KE 1 #define TLSEXT_KEX_MODE_FLAG_KE_DHE 2 -/* An invalid index into the TLSv1.3 PSK identities */ -#define TLSEXT_PSK_BAD_IDENTITY -1 - #define SSL_USE_PSS(s) (s->s3->tmp.peer_sigalg != NULL && \ s->s3->tmp.peer_sigalg->sig == EVP_PKEY_RSA_PSS) diff --git a/freebsd/crypto/openssl/ssl/statem/extensions.c b/freebsd/crypto/openssl/ssl/statem/extensions.c index f105ea78..91c3fd56 100644 --- a/freebsd/crypto/openssl/ssl/statem/extensions.c +++ b/freebsd/crypto/openssl/ssl/statem/extensions.c @@ -991,7 +991,6 @@ static int final_server_name(SSL *s, unsigned int context, int sent) ss->ext.ticklen = 0; ss->ext.tick_lifetime_hint = 0; ss->ext.tick_age_add = 0; - ss->ext.tick_identity = 0; if (!ssl_generate_session_id(s, ss)) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_FINAL_SERVER_NAME, ERR_R_INTERNAL_ERROR); @@ -1648,7 +1647,6 @@ static int final_early_data(SSL *s, unsigned int context, int sent) if (s->max_early_data == 0 || !s->hit - || s->session->ext.tick_identity != 0 || s->early_data_state != SSL_EARLY_DATA_ACCEPTING || !s->ext.early_data_ok || s->hello_retry_request != SSL_HRR_NONE diff --git a/freebsd/crypto/openssl/ssl/statem/extensions_clnt.c b/freebsd/crypto/openssl/ssl/statem/extensions_clnt.c index a64d5367..ead0dde9 100644 --- a/freebsd/crypto/openssl/ssl/statem/extensions_clnt.c +++ b/freebsd/crypto/openssl/ssl/statem/extensions_clnt.c @@ -1,7 +1,7 @@ #include <machine/rtems-bsd-user-space.h> /* - * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -995,7 +995,7 @@ EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context, const EVP_MD *handmd = NULL, *mdres = NULL, *mdpsk = NULL; int dores = 0; - s->session->ext.tick_identity = TLSEXT_PSK_BAD_IDENTITY; + s->ext.tick_identity = 0; /* * Note: At this stage of the code we only support adding a single @@ -1085,6 +1085,7 @@ EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context, agems += s->session->ext.tick_age_add; reshashsize = EVP_MD_size(mdres); + s->ext.tick_identity++; dores = 1; } @@ -1144,6 +1145,7 @@ EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context, ERR_R_INTERNAL_ERROR); return EXT_RETURN_FAIL; } + s->ext.tick_identity++; } if (!WPACKET_close(pkt) @@ -1182,11 +1184,6 @@ EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context, return EXT_RETURN_FAIL; } - if (dores) - s->session->ext.tick_identity = 0; - if (s->psksession != NULL) - s->psksession->ext.tick_identity = (dores ? 1 : 0); - return EXT_RETURN_SENT; #else return EXT_RETURN_NOT_SENT; @@ -1929,8 +1926,7 @@ int tls_parse_stoc_early_data(SSL *s, PACKET *pkt, unsigned int context, } if (!s->ext.early_data_ok - || !s->hit - || s->session->ext.tick_identity != 0) { + || !s->hit) { /* * If we get here then we didn't send early data, or we didn't resume * using the first identity, or the SNI/ALPN is not consistent so the @@ -1958,17 +1954,28 @@ int tls_parse_stoc_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x, return 0; } - if (s->session->ext.tick_identity == (int)identity) { + if (identity >= (unsigned int)s->ext.tick_identity) { + SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_PSK, + SSL_R_BAD_PSK_IDENTITY); + return 0; + } + + /* + * Session resumption tickets are always sent before PSK tickets. If the + * ticket index is 0 then it must be for a session resumption ticket if we + * sent two tickets, or if we didn't send a PSK ticket. + */ + if (identity == 0 && (s->psksession == NULL || s->ext.tick_identity == 2)) { s->hit = 1; SSL_SESSION_free(s->psksession); s->psksession = NULL; return 1; } - if (s->psksession == NULL - || s->psksession->ext.tick_identity != (int)identity) { - SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_PSK, - SSL_R_BAD_PSK_IDENTITY); + if (s->psksession == NULL) { + /* Should never happen */ + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_PSK, + ERR_R_INTERNAL_ERROR); return 0; } @@ -1987,6 +1994,9 @@ int tls_parse_stoc_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x, s->session = s->psksession; s->psksession = NULL; s->hit = 1; + /* Early data is only allowed if we used the first ticket */ + if (identity != 0) + s->ext.early_data_ok = 0; #endif return 1; diff --git a/freebsd/crypto/openssl/ssl/statem/extensions_srvr.c b/freebsd/crypto/openssl/ssl/statem/extensions_srvr.c index d6907198..a2c2ebe4 100644 --- a/freebsd/crypto/openssl/ssl/statem/extensions_srvr.c +++ b/freebsd/crypto/openssl/ssl/statem/extensions_srvr.c @@ -1,7 +1,7 @@ #include <machine/rtems-bsd-user-space.h> /* - * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -1276,7 +1276,7 @@ int tls_parse_ctos_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x, goto err; } - sess->ext.tick_identity = id; + s->ext.tick_identity = id; SSL_SESSION_free(s->session); s->session = sess; @@ -1950,7 +1950,7 @@ EXT_RETURN tls_construct_stoc_psk(SSL *s, WPACKET *pkt, unsigned int context, if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_psk) || !WPACKET_start_sub_packet_u16(pkt) - || !WPACKET_put_bytes_u16(pkt, s->session->ext.tick_identity) + || !WPACKET_put_bytes_u16(pkt, s->ext.tick_identity) || !WPACKET_close(pkt)) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_PSK, ERR_R_INTERNAL_ERROR); diff --git a/freebsd/crypto/openssl/ssl/statem/statem_clnt.c b/freebsd/crypto/openssl/ssl/statem/statem_clnt.c index 5ddbebd3..ec82e6d3 100644 --- a/freebsd/crypto/openssl/ssl/statem/statem_clnt.c +++ b/freebsd/crypto/openssl/ssl/statem/statem_clnt.c @@ -1615,10 +1615,7 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt) * so the PAC-based session secret is always preserved. It'll be * overwritten if the server refuses resumption. */ - if (s->session->session_id_length > 0 - || (SSL_IS_TLS13(s) - && s->session->ext.tick_identity - != TLSEXT_PSK_BAD_IDENTITY)) { + if (s->session->session_id_length > 0) { tsan_counter(&s->session_ctx->stats.sess_miss); if (!ssl_get_new_session(s, 0)) { /* SSLfatal() already called */ diff --git a/freebsd/crypto/openssl/ssl/statem/statem_srvr.c b/freebsd/crypto/openssl/ssl/statem/statem_srvr.c index f00623d6..de1a6c77 100644 --- a/freebsd/crypto/openssl/ssl/statem/statem_srvr.c +++ b/freebsd/crypto/openssl/ssl/statem/statem_srvr.c @@ -777,6 +777,10 @@ static ossl_inline int conn_is_closed(void) case ECONNRESET: return 1; #endif +#if defined(WSAECONNRESET) + case WSAECONNRESET: + return 1; +#endif default: return 0; } diff --git a/freebsd/lib/libc/include/libc_private.h b/freebsd/lib/libc/include/libc_private.h index 8e78f556..2231241f 100644 --- a/freebsd/lib/libc/include/libc_private.h +++ b/freebsd/lib/libc/include/libc_private.h @@ -239,6 +239,7 @@ enum { INTERPOS_map_stacks_exec, INTERPOS_fdatasync, INTERPOS_clock_nanosleep, + INTERPOS_distribute_static_tls, INTERPOS_MAX }; @@ -417,6 +418,8 @@ struct dl_phdr_info; int __elf_phdr_match_addr(struct dl_phdr_info *, void *); void __init_elf_aux_vector(void); void __libc_map_stacks_exec(void); +void __libc_distribute_static_tls(__size_t, void *, __size_t, __size_t); +__uintptr_t __libc_static_tls_base(__size_t); void _pthread_cancel_enter(int); void _pthread_cancel_leave(int); diff --git a/freebsd/lib/libc/net/getnameinfo.c b/freebsd/lib/libc/net/getnameinfo.c index 219e149d..8fa00b24 100644 --- a/freebsd/lib/libc/net/getnameinfo.c +++ b/freebsd/lib/libc/net/getnameinfo.c @@ -226,10 +226,8 @@ getnameinfo_inet(const struct afd *afd, case AF_INET: v4a = (u_int32_t) ntohl(((const struct sockaddr_in *)sa)->sin_addr.s_addr); - if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a)) - flags |= NI_NUMERICHOST; - v4a >>= IN_CLASSA_NSHIFT; - if (v4a == 0) + if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a) || + IN_ZERONET(v4a)) flags |= NI_NUMERICHOST; break; #ifdef INET6 diff --git a/freebsd/sbin/ifconfig/ifconfig.c b/freebsd/sbin/ifconfig/ifconfig.c index c0907866..d27dcdc2 100644 --- a/freebsd/sbin/ifconfig/ifconfig.c +++ b/freebsd/sbin/ifconfig/ifconfig.c @@ -86,6 +86,7 @@ static const char rcsid[] = #ifdef JAIL #include <jail.h> #endif +#include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -148,6 +149,31 @@ struct ifa_order_elt { TAILQ_HEAD(ifa_queue, ifa_order_elt); +static struct module_map_entry { + const char *ifname; + const char *kldname; +} module_map[] = { + { + .ifname = "vmnet", + .kldname = "if_tap", + }, + { + .ifname = "ipsec", + .kldname = "ipsec", + }, + { + /* + * This mapping exists because there is a conflicting enc module + * in CAM. ifconfig's guessing behavior will attempt to match + * the ifname to a module as well as if_${ifname} and clash with + * CAM enc. This is an assertion of the correct module to load. + */ + .ifname = "enc", + .kldname = "if_enc", + }, +}; + + void opt_register(struct option *p) { @@ -1499,9 +1525,11 @@ ifmaybeload(const char *name) #ifndef __rtems__ #define MOD_PREFIX_LEN 3 /* "if_" */ struct module_stat mstat; - int fileid, modid; + int i, fileid, modid; char ifkind[IFNAMSIZ + MOD_PREFIX_LEN], ifname[IFNAMSIZ], *dp; const char *cp; + struct module_map_entry *mme; + bool found; /* loading suppressed by the user */ if (noload) @@ -1515,9 +1543,24 @@ ifmaybeload(const char *name) break; } - /* turn interface and unit into module name */ - strlcpy(ifkind, "if_", sizeof(ifkind)); - strlcat(ifkind, ifname, sizeof(ifkind)); + /* Either derive it from the map or guess otherwise */ + *ifkind = '\0'; + found = false; + for (i = 0; i < nitems(module_map); ++i) { + mme = &module_map[i]; + if (strcmp(mme->ifname, ifname) == 0) { + strlcpy(ifkind, mme->kldname, sizeof(ifkind)); + found = true; + break; + } + } + + /* We didn't have an alias for it... we'll guess. */ + if (!found) { + /* turn interface and unit into module name */ + strlcpy(ifkind, "if_", sizeof(ifkind)); + strlcat(ifkind, ifname, sizeof(ifkind)); + } /* scan files in kernel */ mstat.version = sizeof(struct module_stat); @@ -1533,8 +1576,12 @@ ifmaybeload(const char *name) } else { cp = mstat.name; } - /* already loaded? */ - if (strcmp(ifname, cp) == 0 || + /* + * Is it already loaded? Don't compare with ifname if + * we were specifically told which kld to use. Doing + * so could lead to conflicts not trivially solved. + */ + if ((!found && strcmp(ifname, cp) == 0) || strcmp(ifkind, cp) == 0) return; } diff --git a/freebsd/sbin/ifconfig/ifgre.c b/freebsd/sbin/ifconfig/ifgre.c index 2adc6d76..092e70c2 100644 --- a/freebsd/sbin/ifconfig/ifgre.c +++ b/freebsd/sbin/ifconfig/ifgre.c @@ -56,15 +56,16 @@ __FBSDID("$FreeBSD$"); #include "rtems-bsd-ifconfig-ifgre-data.h" #endif /* __rtems__ */ -#define GREBITS "\020\01ENABLE_CSUM\02ENABLE_SEQ" +#define GREBITS "\020\01ENABLE_CSUM\02ENABLE_SEQ\03UDPENCAP" static void gre_status(int s); static void gre_status(int s) { - uint32_t opts = 0; + uint32_t opts, port; + opts = 0; ifr.ifr_data = (caddr_t)&opts; if (ioctl(s, GREGKEY, &ifr) == 0) if (opts != 0) @@ -72,6 +73,11 @@ gre_status(int s) opts = 0; if (ioctl(s, GREGOPTS, &ifr) != 0 || opts == 0) return; + + port = 0; + ifr.ifr_data = (caddr_t)&port; + if (ioctl(s, GREGPORT, &ifr) == 0 && port != 0) + printf("\tudpport: %u\n", port); printb("\toptions", opts, GREBITS); putchar('\n'); } @@ -89,6 +95,18 @@ setifgrekey(const char *val, int dummy __unused, int s, } static void +setifgreport(const char *val, int dummy __unused, int s, + const struct afswtch *afp) +{ + uint32_t udpport = strtol(val, NULL, 0); + + strlcpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); + ifr.ifr_data = (caddr_t)&udpport; + if (ioctl(s, GRESPORT, (caddr_t)&ifr) < 0) + warn("ioctl (set udpport)"); +} + +static void setifgreopts(const char *val, int d, int s, const struct afswtch *afp) { uint32_t opts; @@ -113,10 +131,13 @@ setifgreopts(const char *val, int d, int s, const struct afswtch *afp) static struct cmd gre_cmds[] = { DEF_CMD_ARG("grekey", setifgrekey), + DEF_CMD_ARG("udpport", setifgreport), DEF_CMD("enable_csum", GRE_ENABLE_CSUM, setifgreopts), DEF_CMD("-enable_csum",-GRE_ENABLE_CSUM,setifgreopts), DEF_CMD("enable_seq", GRE_ENABLE_SEQ, setifgreopts), DEF_CMD("-enable_seq",-GRE_ENABLE_SEQ, setifgreopts), + DEF_CMD("udpencap", GRE_UDPENCAP, setifgreopts), + DEF_CMD("-udpencap",-GRE_UDPENCAP, setifgreopts), }; static struct afswtch af_gre = { .af_name = "af_gre", diff --git a/freebsd/sbin/pfctl/pfctl_optimize.c b/freebsd/sbin/pfctl/pfctl_optimize.c index cbf94e80..02a1018c 100644 --- a/freebsd/sbin/pfctl/pfctl_optimize.c +++ b/freebsd/sbin/pfctl/pfctl_optimize.c @@ -1549,14 +1549,24 @@ superblock_inclusive(struct superblock *block, struct pf_opt_rule *por) int interface_group(const char *ifname) { + int s; + struct ifgroupreq ifgr; + if (ifname == NULL || !ifname[0]) return (0); - /* Real interfaces must end in a number, interface groups do not */ - if (isdigit(ifname[strlen(ifname) - 1])) - return (0); - else - return (1); + s = get_query_socket(); + + memset(&ifgr, 0, sizeof(ifgr)); + strlcpy(ifgr.ifgr_name, ifname, IFNAMSIZ); + if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) == -1) { + if (errno == ENOENT) + return (0); + else + err(1, "SIOCGIFGMEMB"); + } + + return (1); } diff --git a/freebsd/sys/arm/ti/cpsw/if_cpsw.c b/freebsd/sys/arm/ti/cpsw/if_cpsw.c index 1fbda688..fb61aeb4 100644 --- a/freebsd/sys/arm/ti/cpsw/if_cpsw.c +++ b/freebsd/sys/arm/ti/cpsw/if_cpsw.c @@ -84,6 +84,8 @@ __FBSDID("$FreeBSD$"); #include <dev/ofw/ofw_bus.h> #include <dev/ofw/ofw_bus_subr.h> + +#include <dev/fdt/fdt_common.h> #ifdef CPSW_ETHERSWITCH #include <dev/etherswitch/etherswitch.h> @@ -749,7 +751,7 @@ cpsw_get_fdt_data(struct cpsw_softc *sc, int port) phandle_t child; unsigned long mdio_child_addr; - /* Find any slave with phy_id */ + /* Find any slave with phy-handle/phy_id */ phy = -1; vlan = -1; for (child = OF_child(sc->node); child != 0; child = OF_peer(child)) { @@ -763,11 +765,15 @@ cpsw_get_fdt_data(struct cpsw_softc *sc, int port) if (mdio_child_addr != slave_mdio_addr[port]) continue; - len = OF_getproplen(child, "phy_id"); - if (len / sizeof(pcell_t) == 2) { - /* Get phy address from fdt */ - if (OF_getencprop(child, "phy_id", phy_id, len) > 0) - phy = phy_id[1]; + if (fdt_get_phyaddr(child, NULL, &phy, NULL) != 0){ + /* Users with old DTB will have phy_id instead */ + phy = -1; + len = OF_getproplen(child, "phy_id"); + if (len / sizeof(pcell_t) == 2) { + /* Get phy address from fdt */ + if (OF_getencprop(child, "phy_id", phy_id, len) > 0) + phy = phy_id[1]; + } } len = OF_getproplen(child, "dual_emac_res_vlan"); diff --git a/freebsd/sys/cam/cam_periph.h b/freebsd/sys/cam/cam_periph.h index 6eb0084a..b087b872 100644 --- a/freebsd/sys/cam/cam_periph.h +++ b/freebsd/sys/cam/cam_periph.h @@ -149,6 +149,7 @@ struct cam_periph { struct cam_periph_map_info { int num_bufs_used; + void *orig[CAM_PERIPH_MAXMAPS]; struct buf *bp[CAM_PERIPH_MAXMAPS]; }; diff --git a/freebsd/sys/cam/scsi/scsi_all.c b/freebsd/sys/cam/scsi/scsi_all.c index 1a469f32..d0eb431a 100644 --- a/freebsd/sys/cam/scsi/scsi_all.c +++ b/freebsd/sys/cam/scsi/scsi_all.c @@ -3947,7 +3947,7 @@ scsi_set_sense_data_fixed_va(struct scsi_sense_data *sense_data, } if (len > sizeof(sense->cmd_spec_info)) { data += len - sizeof(sense->cmd_spec_info); - len -= len - sizeof(sense->cmd_spec_info); + len = sizeof(sense->cmd_spec_info); } bcopy(data, &sense->cmd_spec_info[ sizeof(sense->cmd_spec_info) - len], len); @@ -4066,6 +4066,10 @@ scsi_get_sense_info(struct scsi_sense_data *sense_data, u_int sense_len, struct scsi_sense_info *info_desc; info_desc = (struct scsi_sense_info *)desc; + + if ((info_desc->byte2 & SSD_INFO_VALID) == 0) + goto bailout; + *info = scsi_8btou64(info_desc->info); if (signed_info != NULL) *signed_info = *info; @@ -4086,6 +4090,9 @@ scsi_get_sense_info(struct scsi_sense_data *sense_data, u_int sense_len, fru_desc = (struct scsi_sense_fru *)desc; + if (fru_desc->fru == 0) + goto bailout; + *info = fru_desc->fru; if (signed_info != NULL) *signed_info = (int8_t)fru_desc->fru; @@ -4186,10 +4193,9 @@ scsi_get_sks(struct scsi_sense_data *sense_data, u_int sense_len, uint8_t *sks) if (desc == NULL) goto bailout; - /* - * No need to check the SKS valid bit for descriptor sense. - * If the descriptor is present, it is valid. - */ + if ((desc->sense_key_spec[0] & SSD_SKS_VALID) == 0) + goto bailout; + bcopy(desc->sense_key_spec, sks, sizeof(desc->sense_key_spec)); break; } @@ -4266,9 +4272,6 @@ scsi_get_block_info(struct scsi_sense_data *sense_data, u_int sense_len, if (SSD_FIXED_IS_PRESENT(sense, sense_len, flags) == 0) goto bailout; - if ((sense->flags & SSD_ILI) == 0) - goto bailout; - *block_bits = sense->flags & SSD_ILI; break; } @@ -4322,9 +4325,6 @@ scsi_get_stream_info(struct scsi_sense_data *sense_data, u_int sense_len, if (SSD_FIXED_IS_PRESENT(sense, sense_len, flags) == 0) goto bailout; - if ((sense->flags & (SSD_ILI|SSD_EOM|SSD_FILEMARK)) == 0) - goto bailout; - *stream_bits = sense->flags & (SSD_ILI|SSD_EOM|SSD_FILEMARK); break; } @@ -4366,8 +4366,6 @@ scsi_progress_sbuf(struct sbuf *sb, uint16_t progress) int scsi_sks_sbuf(struct sbuf *sb, int sense_key, uint8_t *sks) { - if ((sks[0] & SSD_SKS_VALID) == 0) - return (1); switch (sense_key) { case SSD_KEY_ILLEGAL_REQUEST: { @@ -4464,7 +4462,7 @@ scsi_fru_sbuf(struct sbuf *sb, uint64_t fru) } void -scsi_stream_sbuf(struct sbuf *sb, uint8_t stream_bits, uint64_t info) +scsi_stream_sbuf(struct sbuf *sb, uint8_t stream_bits) { int need_comma; @@ -4472,6 +4470,7 @@ scsi_stream_sbuf(struct sbuf *sb, uint8_t stream_bits, uint64_t info) /* * XXX KDM this needs more descriptive decoding. */ + sbuf_printf(sb, "Stream Command Sense Data: "); if (stream_bits & SSD_DESC_STREAM_FM) { sbuf_printf(sb, "Filemark"); need_comma = 1; @@ -4484,15 +4483,15 @@ scsi_stream_sbuf(struct sbuf *sb, uint8_t stream_bits, uint64_t info) if (stream_bits & SSD_DESC_STREAM_ILI) sbuf_printf(sb, "%sILI", (need_comma) ? "," : ""); - - sbuf_printf(sb, ": Info: %#jx", (uintmax_t) info); } void -scsi_block_sbuf(struct sbuf *sb, uint8_t block_bits, uint64_t info) +scsi_block_sbuf(struct sbuf *sb, uint8_t block_bits) { + + sbuf_printf(sb, "Block Command Sense Data: "); if (block_bits & SSD_DESC_BLOCK_ILI) - sbuf_printf(sb, "ILI: residue %#jx", (uintmax_t) info); + sbuf_printf(sb, "ILI"); } void @@ -4505,6 +4504,9 @@ scsi_sense_info_sbuf(struct sbuf *sb, struct scsi_sense_data *sense, info = (struct scsi_sense_info *)header; + if ((info->byte2 & SSD_INFO_VALID) == 0) + return; + scsi_info_sbuf(sb, cdb, cdb_len, inq_data, scsi_8btou64(info->info)); } @@ -4533,6 +4535,9 @@ scsi_sense_sks_sbuf(struct sbuf *sb, struct scsi_sense_data *sense, sks = (struct scsi_sense_sks *)header; + if ((sks->sense_key_spec[0] & SSD_SKS_VALID) == 0) + return; + scsi_extract_sense_len(sense, sense_len, &error_code, &sense_key, &asc, &ascq, /*show_errors*/ 1); @@ -4549,6 +4554,9 @@ scsi_sense_fru_sbuf(struct sbuf *sb, struct scsi_sense_data *sense, fru = (struct scsi_sense_fru *)header; + if (fru->fru == 0) + return; + scsi_fru_sbuf(sb, (uint64_t)fru->fru); } @@ -4559,14 +4567,9 @@ scsi_sense_stream_sbuf(struct sbuf *sb, struct scsi_sense_data *sense, struct scsi_sense_desc_header *header) { struct scsi_sense_stream *stream; - uint64_t info; stream = (struct scsi_sense_stream *)header; - info = 0; - - scsi_get_sense_info(sense, sense_len, SSD_DESC_INFO, &info, NULL); - - scsi_stream_sbuf(sb, stream->byte3, info); + scsi_stream_sbuf(sb, stream->byte3); } void @@ -4576,14 +4579,9 @@ scsi_sense_block_sbuf(struct sbuf *sb, struct scsi_sense_data *sense, struct scsi_sense_desc_header *header) { struct scsi_sense_block *block; - uint64_t info; block = (struct scsi_sense_block *)header; - info = 0; - - scsi_get_sense_info(sense, sense_len, SSD_DESC_INFO, &info, NULL); - - scsi_block_sbuf(sb, block->byte3, info); + scsi_block_sbuf(sb, block->byte3); } void @@ -4868,7 +4866,7 @@ scsi_sense_only_sbuf(struct scsi_sense_data *sense, u_int sense_len, const char *asc_desc; uint8_t sks[3]; uint64_t val; - int info_valid; + uint8_t bits; /* * Get descriptions for the sense key, ASC, and ASCQ. If @@ -4887,42 +4885,28 @@ scsi_sense_only_sbuf(struct scsi_sense_data *sense, u_int sense_len, sbuf_printf(sb, " asc:%x,%x (%s)\n", asc, ascq, asc_desc); /* - * Get the info field if it is valid. + * Print any block or stream device-specific information. */ - if (scsi_get_sense_info(sense, sense_len, SSD_DESC_INFO, - &val, NULL) == 0) - info_valid = 1; - else - info_valid = 0; - - if (info_valid != 0) { - uint8_t bits; + if (scsi_get_block_info(sense, sense_len, inq_data, + &bits) == 0 && bits != 0) { + sbuf_cat(sb, path_str); + scsi_block_sbuf(sb, bits); + sbuf_printf(sb, "\n"); + } else if (scsi_get_stream_info(sense, sense_len, inq_data, + &bits) == 0 && bits != 0) { + sbuf_cat(sb, path_str); + scsi_stream_sbuf(sb, bits); + sbuf_printf(sb, "\n"); + } - /* - * Determine whether we have any block or stream - * device-specific information. - */ - if (scsi_get_block_info(sense, sense_len, inq_data, - &bits) == 0) { - sbuf_cat(sb, path_str); - scsi_block_sbuf(sb, bits, val); - sbuf_printf(sb, "\n"); - } else if (scsi_get_stream_info(sense, sense_len, - inq_data, &bits) == 0) { - sbuf_cat(sb, path_str); - scsi_stream_sbuf(sb, bits, val); - sbuf_printf(sb, "\n"); - } else if (val != 0) { - /* - * The information field can be valid but 0. - * If the block or stream bits aren't set, - * and this is 0, it isn't terribly useful - * to print it out. - */ - sbuf_cat(sb, path_str); - scsi_info_sbuf(sb, cdb, cdb_len, inq_data, val); - sbuf_printf(sb, "\n"); - } + /* + * Print the info field. + */ + if (scsi_get_sense_info(sense, sense_len, SSD_DESC_INFO, + &val, NULL) == 0) { + sbuf_cat(sb, path_str); + scsi_info_sbuf(sb, cdb, cdb_len, inq_data, val); + sbuf_printf(sb, "\n"); } /* diff --git a/freebsd/sys/cam/scsi/scsi_all.h b/freebsd/sys/cam/scsi/scsi_all.h index 80f8a221..735d0685 100644 --- a/freebsd/sys/cam/scsi/scsi_all.h +++ b/freebsd/sys/cam/scsi/scsi_all.h @@ -2931,6 +2931,7 @@ struct scsi_read_capacity_data_long uint8_t length[4]; #define SRC16_PROT_EN 0x01 #define SRC16_P_TYPE 0x0e +#define SRC16_P_TYPE_SHIFT 1 #define SRC16_PTYPE_1 0x00 #define SRC16_PTYPE_2 0x02 #define SRC16_PTYPE_3 0x04 @@ -3749,8 +3750,8 @@ void scsi_command_sbuf(struct sbuf *sb, uint8_t *cdb, int cdb_len, void scsi_progress_sbuf(struct sbuf *sb, uint16_t progress); int scsi_sks_sbuf(struct sbuf *sb, int sense_key, uint8_t *sks); void scsi_fru_sbuf(struct sbuf *sb, uint64_t fru); -void scsi_stream_sbuf(struct sbuf *sb, uint8_t stream_bits, uint64_t info); -void scsi_block_sbuf(struct sbuf *sb, uint8_t block_bits, uint64_t info); +void scsi_stream_sbuf(struct sbuf *sb, uint8_t stream_bits); +void scsi_block_sbuf(struct sbuf *sb, uint8_t block_bits); void scsi_sense_info_sbuf(struct sbuf *sb, struct scsi_sense_data *sense, u_int sense_len, uint8_t *cdb, int cdb_len, struct scsi_inquiry_data *inq_data, diff --git a/freebsd/sys/dev/cadence/if_cgem.c b/freebsd/sys/dev/cadence/if_cgem.c index 191362c4..34340f22 100644 --- a/freebsd/sys/dev/cadence/if_cgem.c +++ b/freebsd/sys/dev/cadence/if_cgem.c @@ -107,6 +107,14 @@ __FBSDID("$FreeBSD$"); #define CGEM_CKSUM_ASSIST (CSUM_IP | CSUM_TCP | CSUM_UDP | \ CSUM_TCP_IPV6 | CSUM_UDP_IPV6) +#ifndef __rtems__ +static struct ofw_compat_data compat_data[] = { + { "cadence,gem", 1 }, + { "cdns,macb", 1 }, + { NULL, 0 }, +}; +#endif /* __rtems__ */ + struct cgem_softc { if_t ifp; struct mtx sc_mtx; @@ -1724,7 +1732,7 @@ cgem_probe(device_t dev) if (!ofw_bus_status_okay(dev)) return (ENXIO); - if (!ofw_bus_is_compatible(dev, "cadence,gem")) + if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) return (ENXIO); #endif /* __rtems__ */ diff --git a/freebsd/sys/dev/e1000/if_em.c b/freebsd/sys/dev/e1000/if_em.c index 68e78ef0..1988cc07 100644 --- a/freebsd/sys/dev/e1000/if_em.c +++ b/freebsd/sys/dev/e1000/if_em.c @@ -1272,21 +1272,7 @@ em_if_init(if_ctx_t ctx) /* Setup Multicast table */ em_if_multi_set(ctx); - /* - * Figure out the desired mbuf - * pool for doing jumbos - */ - if (adapter->hw.mac.max_frame_size <= 2048) - adapter->rx_mbuf_sz = MCLBYTES; -#ifndef CONTIGMALLOC_WORKS - else - adapter->rx_mbuf_sz = MJUMPAGESIZE; -#else - else if (adapter->hw.mac.max_frame_size <= 4096) - adapter->rx_mbuf_sz = MJUMPAGESIZE; - else - adapter->rx_mbuf_sz = MJUM9BYTES; -#endif + adapter->rx_mbuf_sz = iflib_get_rx_mbuf_sz(ctx); em_initialize_receive_unit(ctx); /* Use real VLAN Filter support? */ diff --git a/freebsd/sys/dev/fdt/fdt_common.c b/freebsd/sys/dev/fdt/fdt_common.c index ff32dc0a..12979fda 100644 --- a/freebsd/sys/dev/fdt/fdt_common.c +++ b/freebsd/sys/dev/fdt/fdt_common.c @@ -401,6 +401,9 @@ fdt_get_phyaddr(phandle_t node, device_t dev, int *phy_addr, void **phy_sc) *phy_addr = phy_reg; + if (phy_sc == NULL) + return (0); + /* * Search for softc used to communicate with phy. */ diff --git a/freebsd/sys/dev/nvme/nvme.h b/freebsd/sys/dev/nvme/nvme.h index 845ba75b..ae48a82f 100644 --- a/freebsd/sys/dev/nvme/nvme.h +++ b/freebsd/sys/dev/nvme/nvme.h @@ -349,6 +349,20 @@ #define NVME_NS_DATA_FPI_SUPP_SHIFT (7) #define NVME_NS_DATA_FPI_SUPP_MASK (0x1) +/** Deallocate Logical Block Features */ +/* deallocated logical block read behavior */ +#define NVME_NS_DATA_DLFEAT_READ_SHIFT (0) +#define NVME_NS_DATA_DLFEAT_READ_MASK (0x07) +#define NVME_NS_DATA_DLFEAT_READ_NR (0x00) +#define NVME_NS_DATA_DLFEAT_READ_00 (0x01) +#define NVME_NS_DATA_DLFEAT_READ_FF (0x02) +/* supports the Deallocate bit in the Write Zeroes */ +#define NVME_NS_DATA_DLFEAT_DWZ_SHIFT (3) +#define NVME_NS_DATA_DLFEAT_DWZ_MASK (0x01) +/* Guard field for deallocated logical blocks is set to the CRC */ +#define NVME_NS_DATA_DLFEAT_GCRC_SHIFT (4) +#define NVME_NS_DATA_DLFEAT_GCRC_MASK (0x01) + /** lba format support */ /* metadata size */ #define NVME_NS_DATA_LBAF_MS_SHIFT (0) diff --git a/freebsd/sys/dev/pci/pci.c b/freebsd/sys/dev/pci/pci.c index 09d1ee42..56c3f589 100644 --- a/freebsd/sys/dev/pci/pci.c +++ b/freebsd/sys/dev/pci/pci.c @@ -127,6 +127,10 @@ static int pci_remap_intr_method(device_t bus, device_t dev, u_int irq); static void pci_hint_device_unit(device_t acdev, device_t child, const char *name, int *unitp); +static int pci_reset_post(device_t dev, device_t child); +static int pci_reset_prepare(device_t dev, device_t child); +static int pci_reset_child(device_t dev, device_t child, + int flags); static int pci_get_id_method(device_t dev, device_t child, enum pci_id_type type, uintptr_t *rid); @@ -151,6 +155,9 @@ static device_method_t pci_methods[] = { DEVMETHOD(bus_driver_added, pci_driver_added), DEVMETHOD(bus_setup_intr, pci_setup_intr), DEVMETHOD(bus_teardown_intr, pci_teardown_intr), + DEVMETHOD(bus_reset_prepare, pci_reset_prepare), + DEVMETHOD(bus_reset_post, pci_reset_post), + DEVMETHOD(bus_reset_child, pci_reset_child), DEVMETHOD(bus_get_dma_tag, pci_get_dma_tag), DEVMETHOD(bus_get_resource_list,pci_get_resource_list), @@ -6374,6 +6381,94 @@ pcie_flr(device_t dev, u_int max_delay, bool force) return (true); } +/* + * Attempt a power-management reset by cycling the device in/out of D3 + * state. PCI spec says we can only go into D3 state from D0 state. + * Transition from D[12] into D0 before going to D3 state. + */ +int +pci_power_reset(device_t dev) +{ + int ps; + + ps = pci_get_powerstate(dev); + if (ps != PCI_POWERSTATE_D0 && ps != PCI_POWERSTATE_D3) + pci_set_powerstate(dev, PCI_POWERSTATE_D0); + pci_set_powerstate(dev, PCI_POWERSTATE_D3); + pci_set_powerstate(dev, ps); + return (0); +} + +/* + * Try link drop and retrain of the downstream port of upstream + * switch, for PCIe. According to the PCIe 3.0 spec 6.6.1, this must + * cause Conventional Hot reset of the device in the slot. + * Alternative, for PCIe, could be the secondary bus reset initiatied + * on the upstream switch PCIR_BRIDGECTL_1, bit 6. + */ +int +pcie_link_reset(device_t port, int pcie_location) +{ + uint16_t v; + + v = pci_read_config(port, pcie_location + PCIER_LINK_CTL, 2); + v |= PCIEM_LINK_CTL_LINK_DIS; + pci_write_config(port, pcie_location + PCIER_LINK_CTL, v, 2); + pause_sbt("pcier1", mstosbt(20), 0, 0); + v &= ~PCIEM_LINK_CTL_LINK_DIS; + v |= PCIEM_LINK_CTL_RETRAIN_LINK; + pci_write_config(port, pcie_location + PCIER_LINK_CTL, v, 2); + pause_sbt("pcier2", mstosbt(100), 0, 0); /* 100 ms */ + v = pci_read_config(port, pcie_location + PCIER_LINK_STA, 2); + return ((v & PCIEM_LINK_STA_TRAINING) != 0 ? ETIMEDOUT : 0); +} + +static int +pci_reset_post(device_t dev, device_t child) +{ + + if (dev == device_get_parent(child)) + pci_restore_state(child); + return (0); +} + +static int +pci_reset_prepare(device_t dev, device_t child) +{ + + if (dev == device_get_parent(child)) + pci_save_state(child); + return (0); +} + +static int +pci_reset_child(device_t dev, device_t child, int flags) +{ + int error; + + if (dev == NULL || device_get_parent(child) != dev) + return (0); + if ((flags & DEVF_RESET_DETACH) != 0) { + error = device_get_state(child) == DS_ATTACHED ? + device_detach(child) : 0; + } else { + error = BUS_SUSPEND_CHILD(dev, child); + } + if (error == 0) { + if (!pcie_flr(child, 1000, false)) { + error = BUS_RESET_PREPARE(dev, child); + if (error == 0) + pci_power_reset(child); + BUS_RESET_POST(dev, child); + } + if ((flags & DEVF_RESET_DETACH) != 0) + device_probe_and_attach(child); + else + BUS_RESUME_CHILD(dev, child); + } + return (error); +} + const struct pci_device_table * pci_match_device(device_t child, const struct pci_device_table *id, size_t nelt) { diff --git a/freebsd/sys/dev/pci/pci_pci.c b/freebsd/sys/dev/pci/pci_pci.c index ec52e1fb..30fbbc09 100644 --- a/freebsd/sys/dev/pci/pci_pci.c +++ b/freebsd/sys/dev/pci/pci_pci.c @@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$"); #include <sys/kernel.h> #include <sys/malloc.h> #include <sys/module.h> +#include <sys/pciio.h> #include <sys/rman.h> #include <sys/sysctl.h> #include <sys/systm.h> @@ -82,6 +83,7 @@ static void pcib_pcie_dll_timeout(void *arg); #endif static int pcib_request_feature_default(device_t pcib, device_t dev, enum pci_feature feature); +static int pcib_reset_child(device_t dev, device_t child, int flags); static device_method_t pcib_methods[] = { /* Device interface */ @@ -108,6 +110,7 @@ static device_method_t pcib_methods[] = { DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), + DEVMETHOD(bus_reset_child, pcib_reset_child), /* pcib interface */ DEVMETHOD(pcib_maxslots, pcib_ari_maxslots), @@ -2910,3 +2913,31 @@ pcib_request_feature_default(device_t pcib, device_t dev, bus = device_get_parent(pcib); return (PCIB_REQUEST_FEATURE(device_get_parent(bus), dev, feature)); } + +static int +pcib_reset_child(device_t dev, device_t child, int flags) +{ + struct pci_devinfo *pdinfo; + int error; + + error = 0; + if (dev == NULL || device_get_parent(child) != dev) + goto out; + error = ENXIO; + if (device_get_devclass(child) != devclass_find("pci")) + goto out; + pdinfo = device_get_ivars(dev); + if (pdinfo->cfg.pcie.pcie_location != 0 && + (pdinfo->cfg.pcie.pcie_type == PCIEM_TYPE_DOWNSTREAM_PORT || + pdinfo->cfg.pcie.pcie_type == PCIEM_TYPE_ROOT_PORT)) { + error = bus_helper_reset_prepare(child, flags); + if (error == 0) { + error = pcie_link_reset(dev, + pdinfo->cfg.pcie.pcie_location); + /* XXXKIB call _post even if error != 0 ? */ + bus_helper_reset_post(child, flags); + } + } +out: + return (error); +} diff --git a/freebsd/sys/dev/pci/pcivar.h b/freebsd/sys/dev/pci/pcivar.h index 8fd0d9f7..b530fdcb 100644 --- a/freebsd/sys/dev/pci/pcivar.h +++ b/freebsd/sys/dev/pci/pcivar.h @@ -674,6 +674,7 @@ int pci_get_max_read_req(device_t dev); void pci_restore_state(device_t dev); void pci_save_state(device_t dev); int pci_set_max_read_req(device_t dev, int size); +int pci_power_reset(device_t dev); uint32_t pcie_read_config(device_t dev, int reg, int width); void pcie_write_config(device_t dev, int reg, uint32_t value, int width); uint32_t pcie_adjust_config(device_t dev, int reg, uint32_t mask, @@ -681,6 +682,7 @@ uint32_t pcie_adjust_config(device_t dev, int reg, uint32_t mask, bool pcie_flr(device_t dev, u_int max_delay, bool force); int pcie_get_max_completion_timeout(device_t dev); bool pcie_wait_for_pending_transactions(device_t dev, u_int max_delay); +int pcie_link_reset(device_t port, int pcie_location); void pci_print_faulted_dev(void); diff --git a/freebsd/sys/dev/rtwn/if_rtwn.c b/freebsd/sys/dev/rtwn/if_rtwn.c index f660ea5d..0ca83e8a 100644 --- a/freebsd/sys/dev/rtwn/if_rtwn.c +++ b/freebsd/sys/dev/rtwn/if_rtwn.c @@ -1562,10 +1562,6 @@ rtwn_set_channel(struct ieee80211com *ic) RTWN_LOCK(sc); rtwn_set_chan(sc, c); - sc->sc_rxtap.wr_chan_freq = htole16(c->ic_freq); - sc->sc_rxtap.wr_chan_flags = htole16(c->ic_flags); - sc->sc_txtap.wt_chan_freq = htole16(c->ic_freq); - sc->sc_txtap.wt_chan_flags = htole16(c->ic_flags); RTWN_UNLOCK(sc); } diff --git a/freebsd/sys/dev/rtwn/if_rtwnvar.h b/freebsd/sys/dev/rtwn/if_rtwnvar.h index 3ebcba52..a6e7ea9f 100644 --- a/freebsd/sys/dev/rtwn/if_rtwnvar.h +++ b/freebsd/sys/dev/rtwn/if_rtwnvar.h @@ -62,9 +62,10 @@ struct rtwn_rx_radiotap_header { struct rtwn_tx_radiotap_header { struct ieee80211_radiotap_header wt_ihdr; uint8_t wt_flags; + uint8_t wt_pad; uint16_t wt_chan_freq; uint16_t wt_chan_flags; -} __packed __aligned(8); +} __packed; #define RTWN_TX_RADIOTAP_PRESENT \ (1 << IEEE80211_RADIOTAP_FLAGS | \ diff --git a/freebsd/sys/dev/sdhci/sdhci.c b/freebsd/sys/dev/sdhci/sdhci.c index b9a8a38d..952fbd50 100644 --- a/freebsd/sys/dev/sdhci/sdhci.c +++ b/freebsd/sys/dev/sdhci/sdhci.c @@ -1564,23 +1564,23 @@ sdhci_retune(void *arg) static void sdhci_req_done(struct sdhci_slot *slot) { - union ccb *ccb; + union ccb *ccb; if (__predict_false(sdhci_debug > 1)) slot_printf(slot, "%s\n", __func__); if (slot->ccb != NULL && slot->curcmd != NULL) { callout_stop(&slot->timeout_callout); - ccb = slot->ccb; - slot->ccb = NULL; + ccb = slot->ccb; + slot->ccb = NULL; slot->curcmd = NULL; - /* Tell CAM the request is finished */ - struct ccb_mmcio *mmcio; - mmcio = &ccb->mmcio; + /* Tell CAM the request is finished */ + struct ccb_mmcio *mmcio; + mmcio = &ccb->mmcio; - ccb->ccb_h.status = - (mmcio->cmd.error == 0 ? CAM_REQ_CMP : CAM_REQ_CMP_ERR); - xpt_done(ccb); + ccb->ccb_h.status = + (mmcio->cmd.error == 0 ? CAM_REQ_CMP : CAM_REQ_CMP_ERR); + xpt_done(ccb); } } #else @@ -2498,47 +2498,45 @@ void sdhci_start_slot(struct sdhci_slot *slot) { - if ((slot->devq = cam_simq_alloc(1)) == NULL) { - goto fail; - } - - mtx_init(&slot->sim_mtx, "sdhcisim", NULL, MTX_DEF); - slot->sim = cam_sim_alloc(sdhci_cam_action, sdhci_cam_poll, - "sdhci_slot", slot, device_get_unit(slot->bus), - &slot->sim_mtx, 1, 1, slot->devq); - - if (slot->sim == NULL) { - cam_simq_free(slot->devq); - slot_printf(slot, "cannot allocate CAM SIM\n"); - goto fail; - } - - mtx_lock(&slot->sim_mtx); - if (xpt_bus_register(slot->sim, slot->bus, 0) != 0) { - slot_printf(slot, - "cannot register SCSI pass-through bus\n"); - cam_sim_free(slot->sim, FALSE); - cam_simq_free(slot->devq); - mtx_unlock(&slot->sim_mtx); - goto fail; - } - - mtx_unlock(&slot->sim_mtx); - /* End CAM-specific init */ + if ((slot->devq = cam_simq_alloc(1)) == NULL) + goto fail; + + mtx_init(&slot->sim_mtx, "sdhcisim", NULL, MTX_DEF); + slot->sim = cam_sim_alloc(sdhci_cam_action, sdhci_cam_poll, + "sdhci_slot", slot, device_get_unit(slot->bus), + &slot->sim_mtx, 1, 1, slot->devq); + + if (slot->sim == NULL) { + cam_simq_free(slot->devq); + slot_printf(slot, "cannot allocate CAM SIM\n"); + goto fail; + } + + mtx_lock(&slot->sim_mtx); + if (xpt_bus_register(slot->sim, slot->bus, 0) != 0) { + slot_printf(slot, "cannot register SCSI pass-through bus\n"); + cam_sim_free(slot->sim, FALSE); + cam_simq_free(slot->devq); + mtx_unlock(&slot->sim_mtx); + goto fail; + } + mtx_unlock(&slot->sim_mtx); + + /* End CAM-specific init */ slot->card_present = 0; sdhci_card_task(slot, 0); - return; + return; fail: - if (slot->sim != NULL) { - mtx_lock(&slot->sim_mtx); - xpt_bus_deregister(cam_sim_path(slot->sim)); - cam_sim_free(slot->sim, FALSE); - mtx_unlock(&slot->sim_mtx); - } - - if (slot->devq != NULL) - cam_simq_free(slot->devq); + if (slot->sim != NULL) { + mtx_lock(&slot->sim_mtx); + xpt_bus_deregister(cam_sim_path(slot->sim)); + cam_sim_free(slot->sim, FALSE); + mtx_unlock(&slot->sim_mtx); + } + + if (slot->devq != NULL) + cam_simq_free(slot->devq); } static void @@ -2668,15 +2666,13 @@ sdhci_cam_get_possible_host_clock(const struct sdhci_slot *slot, clock = max_clock; if (slot->version < SDHCI_SPEC_300) { - for (i = 0; i < SDHCI_200_MAX_DIVIDER; - i <<= 1) { + for (i = 0; i < SDHCI_200_MAX_DIVIDER; i <<= 1) { if (clock <= proposed_clock) break; clock >>= 1; } } else { - for (i = 0; i < SDHCI_300_MAX_DIVIDER; - i += 2) { + for (i = 0; i < SDHCI_300_MAX_DIVIDER; i += 2) { if (clock <= proposed_clock) break; clock = max_clock / (i + 2); @@ -2726,7 +2722,7 @@ sdhci_cam_settran_settings(struct sdhci_slot *slot, union ccb *ccb) slot_printf(slot, "Bus mode => %d\n", ios->bus_mode); } - /* XXX Provide a way to call a chip-specific IOS update, required for TI */ + /* XXX Provide a way to call a chip-specific IOS update, required for TI */ return (sdhci_cam_update_ios(slot)); } @@ -2794,7 +2790,7 @@ sdhci_cam_request(struct sdhci_slot *slot, union ccb *ccb) if (mmcio->cmd.data != NULL) { if (mmcio->cmd.data->len == 0 || mmcio->cmd.data->flags == 0) panic("data->len = %d, data->flags = %d -- something is b0rked", - (int)mmcio->cmd.data->len, mmcio->cmd.data->flags); + (int)mmcio->cmd.data->len, mmcio->cmd.data->flags); } slot->ccb = ccb; slot->flags = 0; diff --git a/freebsd/sys/dev/sdhci/sdhci.h b/freebsd/sys/dev/sdhci/sdhci.h index 4c4c2745..38c5e1b9 100644 --- a/freebsd/sys/dev/sdhci/sdhci.h +++ b/freebsd/sys/dev/sdhci/sdhci.h @@ -413,10 +413,10 @@ struct sdhci_slot { #ifdef MMCCAM /* CAM stuff */ union ccb *ccb; - struct cam_devq *devq; - struct cam_sim *sim; - struct mtx sim_mtx; - u_char card_present; /* XXX Maybe derive this from elsewhere? */ + struct cam_devq *devq; + struct cam_sim *sim; + struct mtx sim_mtx; + u_char card_present; /* XXX Maybe derive this from elsewhere? */ #endif }; diff --git a/freebsd/sys/dev/usb/net/if_smsc.c b/freebsd/sys/dev/usb/net/if_smsc.c index 87e181d8..74516536 100644 --- a/freebsd/sys/dev/usb/net/if_smsc.c +++ b/freebsd/sys/dev/usb/net/if_smsc.c @@ -99,6 +99,7 @@ __FBSDID("$FreeBSD$"); #include <dev/fdt/fdt_common.h> #include <dev/ofw/ofw_bus.h> #include <dev/ofw/ofw_bus_subr.h> +#include <dev/usb/usb_fdt_support.h> #endif #include <dev/usb/usb.h> @@ -1561,147 +1562,6 @@ smsc_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) return (rc); } -#ifdef FDT -/* - * This is FreeBSD-specific compatibility strings for RPi/RPi2 - */ -static phandle_t -smsc_fdt_find_eth_node(phandle_t start) -{ - phandle_t child, node; - - /* Traverse through entire tree to find usb ethernet nodes. */ - for (node = OF_child(start); node != 0; node = OF_peer(node)) { - if ((ofw_bus_node_is_compatible(node, "net,ethernet") && - ofw_bus_node_is_compatible(node, "usb,device")) || - ofw_bus_node_is_compatible(node, "usb424,ec00")) - return (node); - child = smsc_fdt_find_eth_node(node); - if (child != -1) - return (child); - } - - return (-1); -} - -/* - * Check if node's path is <*>/usb/hub/ethernet - */ -static int -smsc_fdt_is_usb_eth(phandle_t node) -{ - char name[16]; - int len; - - memset(name, 0, sizeof(name)); - len = OF_getprop(node, "name", name, sizeof(name)); - if (len <= 0) - return (0); - - if (strcmp(name, "ethernet")) - return (0); - - node = OF_parent(node); - if (node == -1) - return (0); - len = OF_getprop(node, "name", name, sizeof(name)); - if (len <= 0) - return (0); - - if (strcmp(name, "hub")) - return (0); - - node = OF_parent(node); - if (node == -1) - return (0); - len = OF_getprop(node, "name", name, sizeof(name)); - if (len <= 0) - return (0); - - if (strcmp(name, "usb")) - return (0); - - return (1); -} - -static phandle_t -smsc_fdt_find_eth_node_by_path(phandle_t start) -{ - phandle_t child, node; - - /* Traverse through entire tree to find usb ethernet nodes. */ - for (node = OF_child(start); node != 0; node = OF_peer(node)) { - if (smsc_fdt_is_usb_eth(node)) - return (node); - child = smsc_fdt_find_eth_node_by_path(node); - if (child != -1) - return (child); - } - - return (-1); -} - -/* - * Look through known names that can contain mac address - * return 0 if valid MAC address has been found - */ -static int -smsc_fdt_read_mac_property(phandle_t node, unsigned char *mac) -{ - int len; - - /* Check if there is property */ - if ((len = OF_getproplen(node, "local-mac-address")) > 0) { - if (len != ETHER_ADDR_LEN) - return (EINVAL); - - OF_getprop(node, "local-mac-address", mac, - ETHER_ADDR_LEN); - return (0); - } - - if ((len = OF_getproplen(node, "mac-address")) > 0) { - if (len != ETHER_ADDR_LEN) - return (EINVAL); - - OF_getprop(node, "mac-address", mac, - ETHER_ADDR_LEN); - return (0); - } - - return (ENXIO); -} - -/** - * Get MAC address from FDT blob. Firmware or loader should fill - * mac-address or local-mac-address property. Returns 0 if MAC address - * obtained, error code otherwise. - */ -static int -smsc_fdt_find_mac(unsigned char *mac) -{ - phandle_t node, root; - - root = OF_finddevice("/"); - node = smsc_fdt_find_eth_node(root); - if (node != -1) { - if (smsc_fdt_read_mac_property(node, mac) == 0) - return (0); - } - - /* - * If it's not FreeBSD FDT blob for RPi, try more - * generic .../usb/hub/ethernet - */ - node = smsc_fdt_find_eth_node_by_path(root); - - if (node != -1) - return smsc_fdt_read_mac_property(node, mac); - - return (ENXIO); -} -#endif - /** * smsc_attach_post - Called after the driver attached to the USB interface * @ue: the USB ethernet device @@ -1750,7 +1610,7 @@ smsc_attach_post(struct usb_ether *ue) err = smsc_eeprom_read(sc, 0x01, sc->sc_ue.ue_eaddr, ETHER_ADDR_LEN); #ifdef FDT if ((err != 0) || (!ETHER_IS_VALID(sc->sc_ue.ue_eaddr))) - err = smsc_fdt_find_mac(sc->sc_ue.ue_eaddr); + err = usb_fdt_get_mac_addr(sc->sc_ue.ue_dev, &sc->sc_ue); #endif if ((err != 0) || (!ETHER_IS_VALID(sc->sc_ue.ue_eaddr))) { read_random(sc->sc_ue.ue_eaddr, ETHER_ADDR_LEN); diff --git a/freebsd/sys/dev/usb/net/if_urereg.h b/freebsd/sys/dev/usb/net/if_urereg.h index 8eff1c25..cc70093f 100644 --- a/freebsd/sys/dev/usb/net/if_urereg.h +++ b/freebsd/sys/dev/usb/net/if_urereg.h @@ -176,7 +176,7 @@ #define URE_EEEP_CR_EEEP_TX 0x0002 /* PLA_WDT6_CTRL */ -#define URE_WDT6_SET_MODE 0x001 +#define URE_WDT6_SET_MODE 0x0010 /* PLA_TCR0 */ #define URE_TCR0_TX_EMPTY 0x0800 diff --git a/freebsd/sys/dev/usb/wlan/if_rsu.c b/freebsd/sys/dev/usb/wlan/if_rsu.c index 45cd30ad..112b8675 100644 --- a/freebsd/sys/dev/usb/wlan/if_rsu.c +++ b/freebsd/sys/dev/usb/wlan/if_rsu.c @@ -2452,8 +2452,6 @@ rsu_rx_frame(struct rsu_softc *sc, struct mbuf *m) tap->wr_rate = rxs.c_rate; tap->wr_dbm_antsignal = rssi; - tap->wr_chan_freq = htole16(ic->ic_curchan->ic_freq); - tap->wr_chan_flags = htole16(ic->ic_curchan->ic_flags); }; (void) ieee80211_add_rx_params(m, &rxs); @@ -2755,7 +2753,6 @@ rsu_tx_start(struct rsu_softc *sc, struct ieee80211_node *ni, struct mbuf *m0, struct rsu_data *data) { const struct ieee80211_txparam *tp = ni->ni_txparms; - struct ieee80211com *ic = &sc->sc_ic; struct ieee80211vap *vap = ni->ni_vap; struct ieee80211_frame *wh; struct ieee80211_key *k = NULL; @@ -2899,8 +2896,6 @@ rsu_tx_start(struct rsu_softc *sc, struct ieee80211_node *ni, struct rsu_tx_radiotap_header *tap = &sc->sc_txtap; tap->wt_flags = 0; - tap->wt_chan_freq = htole16(ic->ic_curchan->ic_freq); - tap->wt_chan_flags = htole16(ic->ic_curchan->ic_flags); ieee80211_radiotap_tx(vap, m0); } diff --git a/freebsd/sys/dev/usb/wlan/if_rsureg.h b/freebsd/sys/dev/usb/wlan/if_rsureg.h index a6ab170b..246b06b7 100644 --- a/freebsd/sys/dev/usb/wlan/if_rsureg.h +++ b/freebsd/sys/dev/usb/wlan/if_rsureg.h @@ -800,9 +800,10 @@ struct rsu_rx_radiotap_header { struct rsu_tx_radiotap_header { struct ieee80211_radiotap_header wt_ihdr; uint8_t wt_flags; + uint8_t wt_pad; uint16_t wt_chan_freq; uint16_t wt_chan_flags; -} __packed __aligned(8); +} __packed; #define RSU_TX_RADIOTAP_PRESENT \ (1 << IEEE80211_RADIOTAP_FLAGS | \ diff --git a/freebsd/sys/dev/usb/wlan/if_rumvar.h b/freebsd/sys/dev/usb/wlan/if_rumvar.h index 4ff831f4..e19a7088 100644 --- a/freebsd/sys/dev/usb/wlan/if_rumvar.h +++ b/freebsd/sys/dev/usb/wlan/if_rumvar.h @@ -49,7 +49,7 @@ struct rum_tx_radiotap_header { uint16_t wt_chan_freq; uint16_t wt_chan_flags; uint8_t wt_antenna; -} __packed __aligned(8); +} __packed; #define RT2573_TX_RADIOTAP_PRESENT \ ((1 << IEEE80211_RADIOTAP_FLAGS) | \ diff --git a/freebsd/sys/dev/usb/wlan/if_run.c b/freebsd/sys/dev/usb/wlan/if_run.c index 5cec460e..2208e4fd 100644 --- a/freebsd/sys/dev/usb/wlan/if_run.c +++ b/freebsd/sys/dev/usb/wlan/if_run.c @@ -466,6 +466,7 @@ static void run_usb_timeout_cb(void *); static void run_reset_livelock(struct run_softc *); static void run_enable_tsf_sync(struct run_softc *); static void run_enable_tsf(struct run_softc *); +static void run_disable_tsf(struct run_softc *); static void run_get_tsf(struct run_softc *, uint64_t *); static void run_enable_mrr(struct run_softc *); static void run_set_txpreamble(struct run_softc *); @@ -2092,7 +2093,6 @@ run_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) struct run_vap *rvp = RUN_VAP(vap); enum ieee80211_state ostate; uint32_t sta[3]; - uint32_t tmp; uint8_t ratectl; uint8_t restart_ratectl = 0; uint8_t bid = 1 << rvp->rvp_id; @@ -2125,12 +2125,8 @@ run_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) sc->runbmap &= ~bid; /* abort TSF synchronization if there is no vap running */ - if (--sc->running == 0) { - run_read(sc, RT2860_BCN_TIME_CFG, &tmp); - run_write(sc, RT2860_BCN_TIME_CFG, - tmp & ~(RT2860_BCN_TX_EN | RT2860_TSF_TIMER_EN | - RT2860_TBTT_TIMER_EN)); - } + if (--sc->running == 0) + run_disable_tsf(sc); break; case IEEE80211_S_RUN: @@ -2857,10 +2853,6 @@ run_rx_frame(struct run_softc *sc, struct mbuf *m, uint32_t dmalen) } if (flags & RT2860_RX_L2PAD) { - /* - * XXX OpenBSD removes padding between header - * and payload here... - */ RUN_DPRINTF(sc, RUN_DEBUG_RECV, "received RT2860_RX_L2PAD frame\n"); len += 2; @@ -2871,8 +2863,8 @@ run_rx_frame(struct run_softc *sc, struct mbuf *m, uint32_t dmalen) wh = mtod(m, struct ieee80211_frame *); - /* XXX wrong for monitor mode */ - if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { + if ((wh->i_fc[1] & IEEE80211_FC1_PROTECTED) != 0 && + (flags & RT2860_RX_DEC) != 0) { wh->i_fc[1] &= ~IEEE80211_FC1_PROTECTED; m->m_flags |= M_WEP; } @@ -2902,8 +2894,8 @@ run_rx_frame(struct run_softc *sc, struct mbuf *m, uint32_t dmalen) uint16_t phy; tap->wr_flags = 0; - tap->wr_chan_freq = htole16(ic->ic_curchan->ic_freq); - tap->wr_chan_flags = htole16(ic->ic_curchan->ic_flags); + if (flags & RT2860_RX_L2PAD) + tap->wr_flags |= IEEE80211_RADIOTAP_F_DATAPAD; tap->wr_antsignal = rssi; tap->wr_antenna = ant; tap->wr_dbm_antsignal = run_rssi2dbm(sc, rssi, ant); @@ -3170,16 +3162,23 @@ tr_setup: vap = data->ni->ni_vap; if (ieee80211_radiotap_active_vap(vap)) { + const struct ieee80211_frame *wh; struct run_tx_radiotap_header *tap = &sc->sc_txtap; struct rt2860_txwi *txwi = (struct rt2860_txwi *)(&data->desc + sizeof(struct rt2870_txd)); + int has_l2pad; + + wh = mtod(m, struct ieee80211_frame *); + has_l2pad = IEEE80211_HAS_ADDR4(wh) != + IEEE80211_QOS_HAS_SEQ(wh); + tap->wt_flags = 0; tap->wt_rate = rt2860_rates[data->ridx].rate; - tap->wt_chan_freq = htole16(ic->ic_curchan->ic_freq); - tap->wt_chan_flags = htole16(ic->ic_curchan->ic_flags); tap->wt_hwqueue = index; if (le16toh(txwi->phy) & RT2860_PHY_SHPRE) tap->wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE; + if (has_l2pad) + tap->wt_flags |= IEEE80211_RADIOTAP_F_DATAPAD; ieee80211_radiotap_tx(vap, m); } @@ -4869,15 +4868,11 @@ static void run_scan_start(struct ieee80211com *ic) { struct run_softc *sc = ic->ic_softc; - uint32_t tmp; RUN_LOCK(sc); /* abort TSF synchronization */ - run_read(sc, RT2860_BCN_TIME_CFG, &tmp); - run_write(sc, RT2860_BCN_TIME_CFG, - tmp & ~(RT2860_BCN_TX_EN | RT2860_TSF_TIMER_EN | - RT2860_TBTT_TIMER_EN)); + run_disable_tsf(sc); run_set_bssid(sc, ieee80211broadcastaddr); RUN_UNLOCK(sc); @@ -5164,6 +5159,18 @@ run_enable_tsf(struct run_softc *sc) } static void +run_disable_tsf(struct run_softc *sc) +{ + uint32_t tmp; + + if (run_read(sc, RT2860_BCN_TIME_CFG, &tmp) == 0) { + tmp &= ~(RT2860_BCN_TX_EN | RT2860_TSF_TIMER_EN | + RT2860_TBTT_TIMER_EN); + run_write(sc, RT2860_BCN_TIME_CFG, tmp); + } +} + +static void run_get_tsf(struct run_softc *sc, uint64_t *buf) { run_read_region_1(sc, RT2860_TSF_TIMER_DW0, (uint8_t *)buf, @@ -6114,10 +6121,7 @@ run_init_locked(struct run_softc *sc) } /* abort TSF synchronization */ - run_read(sc, RT2860_BCN_TIME_CFG, &tmp); - tmp &= ~(RT2860_BCN_TX_EN | RT2860_TSF_TIMER_EN | - RT2860_TBTT_TIMER_EN); - run_write(sc, RT2860_BCN_TIME_CFG, tmp); + run_disable_tsf(sc); /* clear RX WCID search table */ run_set_region_4(sc, RT2860_WCID_ENTRY(0), 0, 512); diff --git a/freebsd/sys/dev/usb/wlan/if_runvar.h b/freebsd/sys/dev/usb/wlan/if_runvar.h index 7209bfc7..a17d5b46 100644 --- a/freebsd/sys/dev/usb/wlan/if_runvar.h +++ b/freebsd/sys/dev/usb/wlan/if_runvar.h @@ -71,7 +71,7 @@ struct run_tx_radiotap_header { uint16_t wt_chan_freq; uint16_t wt_chan_flags; uint8_t wt_hwqueue; -} __packed __aligned(8); +} __packed; #define IEEE80211_RADIOTAP_HWQUEUE 15 diff --git a/freebsd/sys/dev/usb/wlan/if_uath.c b/freebsd/sys/dev/usb/wlan/if_uath.c index 541263ab..9f0c9d5d 100644 --- a/freebsd/sys/dev/usb/wlan/if_uath.c +++ b/freebsd/sys/dev/usb/wlan/if_uath.c @@ -1278,8 +1278,8 @@ uath_watchdog(void *arg) if (sc->sc_tx_timer > 0) { if (--sc->sc_tx_timer == 0) { device_printf(sc->sc_dev, "device timeout\n"); - /*uath_init(sc); XXX needs a process context! */ counter_u64_add(ic->ic_oerrors, 1); + ieee80211_restart_all(ic); return; } callout_reset(&sc->watchdog_ch, hz, uath_watchdog, sc); diff --git a/freebsd/sys/dev/usb/wlan/if_uathvar.h b/freebsd/sys/dev/usb/wlan/if_uathvar.h index a38f54fc..a0ef4eab 100644 --- a/freebsd/sys/dev/usb/wlan/if_uathvar.h +++ b/freebsd/sys/dev/usb/wlan/if_uathvar.h @@ -67,9 +67,10 @@ struct uath_rx_radiotap_header { struct uath_tx_radiotap_header { struct ieee80211_radiotap_header wt_ihdr; uint8_t wt_flags; + uint8_t wt_pad; uint16_t wt_chan_freq; uint16_t wt_chan_flags; -} __packed __aligned(8); +} __packed; #define UATH_TX_RADIOTAP_PRESENT \ ((1 << IEEE80211_RADIOTAP_FLAGS) | \ diff --git a/freebsd/sys/dev/usb/wlan/if_upgtvar.h b/freebsd/sys/dev/usb/wlan/if_upgtvar.h index ce996f6a..9d4c85e6 100644 --- a/freebsd/sys/dev/usb/wlan/if_upgtvar.h +++ b/freebsd/sys/dev/usb/wlan/if_upgtvar.h @@ -394,7 +394,7 @@ struct upgt_tx_radiotap_header { uint8_t wt_rate; uint16_t wt_chan_freq; uint16_t wt_chan_flags; -} __packed __aligned(8); +} __packed; #define UPGT_TX_RADIOTAP_PRESENT \ ((1 << IEEE80211_RADIOTAP_FLAGS) | \ diff --git a/freebsd/sys/dev/usb/wlan/if_uralvar.h b/freebsd/sys/dev/usb/wlan/if_uralvar.h index dd863fe0..b59b7911 100644 --- a/freebsd/sys/dev/usb/wlan/if_uralvar.h +++ b/freebsd/sys/dev/usb/wlan/if_uralvar.h @@ -51,7 +51,7 @@ struct ural_tx_radiotap_header { uint16_t wt_chan_freq; uint16_t wt_chan_flags; uint8_t wt_antenna; -} __packed __aligned(8); +} __packed; #define RAL_TX_RADIOTAP_PRESENT \ ((1 << IEEE80211_RADIOTAP_FLAGS) | \ diff --git a/freebsd/sys/dev/usb/wlan/if_urtw.c b/freebsd/sys/dev/usb/wlan/if_urtw.c index 84f28d56..aba334af 100644 --- a/freebsd/sys/dev/usb/wlan/if_urtw.c +++ b/freebsd/sys/dev/usb/wlan/if_urtw.c @@ -754,6 +754,7 @@ static void urtw_free_tx_data_list(struct urtw_softc *); static void urtw_free_rx_data_list(struct urtw_softc *); static void urtw_free_data_list(struct urtw_softc *, struct urtw_data data[], int, int); +static usb_error_t urtw_set_macaddr(struct urtw_softc *, const uint8_t *); static usb_error_t urtw_adapter_start(struct urtw_softc *); static usb_error_t urtw_adapter_start_b(struct urtw_softc *); static usb_error_t urtw_set_mode(struct urtw_softc *, uint32_t); @@ -1189,9 +1190,23 @@ fail: } static usb_error_t +urtw_set_macaddr(struct urtw_softc *sc, const uint8_t *macaddr) +{ + usb_error_t error; + + urtw_write32_m(sc, URTW_MAC0, ((const uint32_t *)macaddr)[0]); + urtw_write16_m(sc, URTW_MAC4, ((const uint32_t *)macaddr)[1] & 0xffff); + +fail: + return (error); +} + +static usb_error_t urtw_adapter_start(struct urtw_softc *sc) { struct ieee80211com *ic = &sc->sc_ic; + struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); + const uint8_t *macaddr; usb_error_t error; error = urtw_reset(sc); @@ -1211,8 +1226,11 @@ urtw_adapter_start(struct urtw_softc *sc) if (error) goto fail; /* applying MAC address again. */ - urtw_write32_m(sc, URTW_MAC0, ((uint32_t *)ic->ic_macaddr)[0]); - urtw_write16_m(sc, URTW_MAC4, ((uint32_t *)ic->ic_macaddr)[1] & 0xffff); + macaddr = vap ? vap->iv_myaddr : ic->ic_macaddr; + urtw_set_macaddr(sc, macaddr); + if (error) + goto fail; + error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL); if (error) goto fail; @@ -1699,11 +1717,7 @@ urtw_tx_start(struct urtw_softc *sc, struct ieee80211_node *ni, struct mbuf *m0, if (ieee80211_radiotap_active_vap(vap)) { struct urtw_tx_radiotap_header *tap = &sc->sc_txtap; - /* XXX Are variables correct? */ tap->wt_flags = 0; - tap->wt_chan_freq = htole16(ic->ic_curchan->ic_freq); - tap->wt_chan_flags = htole16(ic->ic_curchan->ic_flags); - ieee80211_radiotap_tx(vap, m0); } @@ -1897,11 +1911,13 @@ static void urtw_watchdog(void *arg) { struct urtw_softc *sc = arg; + struct ieee80211com *ic = &sc->sc_ic; if (sc->sc_txtimer > 0) { if (--sc->sc_txtimer == 0) { device_printf(sc->sc_dev, "device timeout\n"); - counter_u64_add(sc->sc_ic.ic_oerrors, 1); + counter_u64_add(ic->ic_oerrors, 1); + ieee80211_restart_all(ic); return; } callout_reset(&sc->sc_watchdog_ch, hz, urtw_watchdog, sc); @@ -3184,6 +3200,8 @@ static usb_error_t urtw_8225v2b_rf_init(struct urtw_softc *sc) { struct ieee80211com *ic = &sc->sc_ic; + struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); + const uint8_t *macaddr; unsigned int i; uint8_t data8; usb_error_t error; @@ -3231,8 +3249,10 @@ urtw_8225v2b_rf_init(struct urtw_softc *sc) urtw_write8_m(sc, URTW_CONFIG1, data8); /* applying MAC address again. */ - urtw_write32_m(sc, URTW_MAC0, ((uint32_t *)ic->ic_macaddr)[0]); - urtw_write16_m(sc, URTW_MAC4, ((uint32_t *)ic->ic_macaddr)[1] & 0xffff); + macaddr = vap ? vap->iv_myaddr : ic->ic_macaddr; + error = urtw_set_macaddr(sc, macaddr); + if (error) + goto fail; error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL); if (error) @@ -3938,6 +3958,7 @@ urtw_rxeof(struct usb_xfer *xfer, struct urtw_data *data, int *rssi_p, struct urtw_softc *sc = data->sc; struct ieee80211com *ic = &sc->sc_ic; uint8_t noise = 0, rate; + uint64_t mactime; usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL); @@ -3957,6 +3978,9 @@ urtw_rxeof(struct usb_xfer *xfer, struct urtw_data *data, int *rssi_p, /* XXX correct? */ rssi = rx->rssi & URTW_RX_RSSI_MASK; noise = rx->noise; + + if (ieee80211_radiotap_active(ic)) + mactime = rx->mactime; } else { struct urtw_8187l_rxhdr *rx; @@ -3973,6 +3997,9 @@ urtw_rxeof(struct usb_xfer *xfer, struct urtw_data *data, int *rssi_p, /* XXX correct? */ rssi = rx->rssi & URTW_RX_8187L_RSSI_MASK; noise = rx->noise; + + if (ieee80211_radiotap_active(ic)) + mactime = rx->mactime; } if (flen < IEEE80211_ACK_LEN) @@ -3992,9 +4019,8 @@ urtw_rxeof(struct usb_xfer *xfer, struct urtw_data *data, int *rssi_p, if (ieee80211_radiotap_active(ic)) { struct urtw_rx_radiotap_header *tap = &sc->sc_rxtap; - /* XXX Are variables correct? */ - tap->wr_chan_freq = htole16(ic->ic_curchan->ic_freq); - tap->wr_chan_flags = htole16(ic->ic_curchan->ic_flags); + tap->wr_tsf = mactime; + tap->wr_flags = 0; tap->wr_dbm_antsignal = (int8_t)rssi; } diff --git a/freebsd/sys/dev/usb/wlan/if_urtwvar.h b/freebsd/sys/dev/usb/wlan/if_urtwvar.h index 1b5e2cd1..87c24d64 100644 --- a/freebsd/sys/dev/usb/wlan/if_urtwvar.h +++ b/freebsd/sys/dev/usb/wlan/if_urtwvar.h @@ -55,23 +55,27 @@ typedef STAILQ_HEAD(, urtw_data) urtw_datahead; struct urtw_rx_radiotap_header { struct ieee80211_radiotap_header wr_ihdr; + uint64_t wr_tsf; uint8_t wr_flags; + uint8_t wr_pad; uint16_t wr_chan_freq; uint16_t wr_chan_flags; int8_t wr_dbm_antsignal; } __packed __aligned(8); #define URTW_RX_RADIOTAP_PRESENT \ - ((1 << IEEE80211_RADIOTAP_FLAGS) | \ + ((1 << IEEE80211_RADIOTAP_TSFT) | \ + (1 << IEEE80211_RADIOTAP_FLAGS) | \ (1 << IEEE80211_RADIOTAP_CHANNEL) | \ (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL)) struct urtw_tx_radiotap_header { struct ieee80211_radiotap_header wt_ihdr; uint8_t wt_flags; + uint8_t wt_pad; uint16_t wt_chan_freq; uint16_t wt_chan_flags; -} __packed __aligned(8); +} __packed; #define URTW_TX_RADIOTAP_PRESENT \ ((1 << IEEE80211_RADIOTAP_FLAGS) | \ diff --git a/freebsd/sys/dev/usb/wlan/if_zydreg.h b/freebsd/sys/dev/usb/wlan/if_zydreg.h index 8c4a16c5..a4523199 100644 --- a/freebsd/sys/dev/usb/wlan/if_zydreg.h +++ b/freebsd/sys/dev/usb/wlan/if_zydreg.h @@ -1200,7 +1200,7 @@ struct zyd_tx_radiotap_header { uint8_t wt_rate; uint16_t wt_chan_freq; uint16_t wt_chan_flags; -} __packed __aligned(8); +} __packed; #define ZYD_TX_RADIOTAP_PRESENT \ ((1 << IEEE80211_RADIOTAP_FLAGS) | \ diff --git a/freebsd/sys/kern/init_main.c b/freebsd/sys/kern/init_main.c index 43eaea5c..224c9f66 100644 --- a/freebsd/sys/kern/init_main.c +++ b/freebsd/sys/kern/init_main.c @@ -439,7 +439,6 @@ struct sysentvec null_sysvec = { .sv_coredump = NULL, .sv_imgact_try = NULL, .sv_minsigstksz = 0, - .sv_pagesize = PAGE_SIZE, .sv_minuser = VM_MIN_ADDRESS, .sv_maxuser = VM_MAXUSER_ADDRESS, .sv_usrstack = USRSTACK, diff --git a/freebsd/sys/kern/kern_intr.c b/freebsd/sys/kern/kern_intr.c index 2ba76e88..8a85a5b2 100644 --- a/freebsd/sys/kern/kern_intr.c +++ b/freebsd/sys/kern/kern_intr.c @@ -231,10 +231,20 @@ intr_event_update(struct intr_event *ie) } /* - * If the handler names were too long, add +'s to indicate missing - * names. If we run out of room and still have +'s to add, change - * the last character from a + to a *. + * If there is only one handler and its name is too long, just copy in + * as much of the end of the name (includes the unit number) as will + * fit. Otherwise, we have multiple handlers and not all of the names + * will fit. Add +'s to indicate missing names. If we run out of room + * and still have +'s to add, change the last character from a + to a *. */ + if (missed == 1 && space == 1) { + ih = CK_SLIST_FIRST(&ie->ie_handlers); + missed = strlen(ie->ie_fullname) + strlen(ih->ih_name) + 2 - + sizeof(ie->ie_fullname); + strcat(ie->ie_fullname, (missed == 0) ? " " : "-"); + strcat(ie->ie_fullname, &ih->ih_name[missed]); + missed = 0; + } last = &ie->ie_fullname[sizeof(ie->ie_fullname) - 2]; while (missed-- > 0) { if (strlen(ie->ie_fullname) + 1 == sizeof(ie->ie_fullname)) { diff --git a/freebsd/sys/kern/kern_mib.c b/freebsd/sys/kern/kern_mib.c index 1933af9a..b1c02570 100644 --- a/freebsd/sys/kern/kern_mib.c +++ b/freebsd/sys/kern/kern_mib.c @@ -148,7 +148,7 @@ SYSCTL_INT(_kern, KERN_SAVED_IDS, saved_ids, CTLFLAG_RD|CTLFLAG_CAPRD, SYSCTL_NULL_INT_PTR, 0, "Whether saved set-group/user ID is available"); #endif -char kernelname[MAXPATHLEN] = "/kernel"; /* XXX bloat */ +char kernelname[MAXPATHLEN] = "/boot/kernel/kernel"; /* XXX bloat */ SYSCTL_STRING(_kern, KERN_BOOTFILE, bootfile, CTLFLAG_RW | CTLFLAG_MPSAFE, kernelname, sizeof kernelname, "Name of kernel file booted"); @@ -199,7 +199,8 @@ sysctl_hw_physmem(SYSCTL_HANDLER_ARGS) return (sysctl_handle_long(oidp, &val, 0, req)); } SYSCTL_PROC(_hw, HW_PHYSMEM, physmem, CTLTYPE_ULONG | CTLFLAG_RD, - 0, 0, sysctl_hw_physmem, "LU", ""); + 0, 0, sysctl_hw_physmem, "LU", + "Amount of physical memory (in bytes)"); static int sysctl_hw_realmem(SYSCTL_HANDLER_ARGS) @@ -213,7 +214,8 @@ sysctl_hw_realmem(SYSCTL_HANDLER_ARGS) return (sysctl_handle_long(oidp, &val, 0, req)); } SYSCTL_PROC(_hw, HW_REALMEM, realmem, CTLTYPE_ULONG | CTLFLAG_RD, - 0, 0, sysctl_hw_realmem, "LU", ""); + 0, 0, sysctl_hw_realmem, "LU", + "Amount of memory (in bytes) reported by the firmware"); static int sysctl_hw_usermem(SYSCTL_HANDLER_ARGS) @@ -228,9 +230,11 @@ sysctl_hw_usermem(SYSCTL_HANDLER_ARGS) return (sysctl_handle_long(oidp, &val, 0, req)); } SYSCTL_PROC(_hw, HW_USERMEM, usermem, CTLTYPE_ULONG | CTLFLAG_RD, - 0, 0, sysctl_hw_usermem, "LU", ""); + 0, 0, sysctl_hw_usermem, "LU", + "Amount of memory (in bytes) which is not wired"); -SYSCTL_LONG(_hw, OID_AUTO, availpages, CTLFLAG_RD, &physmem, 0, ""); +SYSCTL_LONG(_hw, OID_AUTO, availpages, CTLFLAG_RD, &physmem, 0, + "Amount of physical memory (in pages)"); u_long pagesizes[MAXPAGESIZES] = { PAGE_SIZE }; diff --git a/freebsd/sys/kern/subr_bus.c b/freebsd/sys/kern/subr_bus.c index 29fdfe34..8a6b4edf 100644 --- a/freebsd/sys/kern/subr_bus.c +++ b/freebsd/sys/kern/subr_bus.c @@ -3040,6 +3040,10 @@ device_detach(device_t dev) PDEBUG(("%s", DEVICENAME(dev))); if (dev->state == DS_BUSY) return (EBUSY); + if (dev->state == DS_ATTACHING) { + device_printf(dev, "device in attaching state! Deferring detach.\n"); + return (EBUSY); + } if (dev->state != DS_ATTACHED) return (0); @@ -3904,6 +3908,96 @@ bus_generic_resume(device_t dev) return (0); } + +/** + * @brief Helper function for implementing BUS_RESET_POST + * + * Bus can use this function to implement common operations of + * re-attaching or resuming the children after the bus itself was + * reset, and after restoring bus-unique state of children. + * + * @param dev The bus + * #param flags DEVF_RESET_* + */ +int +bus_helper_reset_post(device_t dev, int flags) +{ + device_t child; + int error, error1; + + error = 0; + TAILQ_FOREACH(child, &dev->children,link) { + BUS_RESET_POST(dev, child); + error1 = (flags & DEVF_RESET_DETACH) != 0 ? + device_probe_and_attach(child) : + BUS_RESUME_CHILD(dev, child); + if (error == 0 && error1 != 0) + error = error1; + } + return (error); +} + +static void +bus_helper_reset_prepare_rollback(device_t dev, device_t child, int flags) +{ + + child = TAILQ_NEXT(child, link); + if (child == NULL) + return; + TAILQ_FOREACH_FROM(child, &dev->children,link) { + BUS_RESET_POST(dev, child); + if ((flags & DEVF_RESET_DETACH) != 0) + device_probe_and_attach(child); + else + BUS_RESUME_CHILD(dev, child); + } +} + +/** + * @brief Helper function for implementing BUS_RESET_PREPARE + * + * Bus can use this function to implement common operations of + * detaching or suspending the children before the bus itself is + * reset, and then save bus-unique state of children that must + * persists around reset. + * + * @param dev The bus + * #param flags DEVF_RESET_* + */ +int +bus_helper_reset_prepare(device_t dev, int flags) +{ + device_t child; + int error; + + if (dev->state != DS_ATTACHED) + return (EBUSY); + + TAILQ_FOREACH_REVERSE(child, &dev->children, device_list, link) { + if ((flags & DEVF_RESET_DETACH) != 0) { + error = device_get_state(child) == DS_ATTACHED ? + device_detach(child) : 0; + } else { + error = BUS_SUSPEND_CHILD(dev, child); + } + if (error == 0) { + error = BUS_RESET_PREPARE(dev, child); + if (error != 0) { + if ((flags & DEVF_RESET_DETACH) != 0) + device_probe_and_attach(child); + else + BUS_RESUME_CHILD(dev, child); + } + } + if (error != 0) { + bus_helper_reset_prepare_rollback(dev, child, flags); + return (error); + } + } + return (0); +} + + /** * @brief Helper function for implementing BUS_PRINT_CHILD(). * @@ -5603,6 +5697,7 @@ devctl2_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag, case DEV_CLEAR_DRIVER: case DEV_RESCAN: case DEV_DELETE: + case DEV_RESET: error = priv_check(td, PRIV_DRIVER); if (error == 0) error = find_device(req, &dev); @@ -5829,6 +5924,14 @@ devctl2_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag, device_frozen = false; } break; + case DEV_RESET: + if ((req->dr_flags & ~(DEVF_RESET_DETACH)) != 0) { + error = EINVAL; + break; + } + error = BUS_RESET_CHILD(device_get_parent(dev), dev, + req->dr_flags); + break; } #endif /* __rtems__ */ mtx_unlock(&Giant); diff --git a/freebsd/sys/net/bpf.c b/freebsd/sys/net/bpf.c index edee632b..33c58c3e 100644 --- a/freebsd/sys/net/bpf.c +++ b/freebsd/sys/net/bpf.c @@ -2695,16 +2695,16 @@ bpfattach2(struct ifnet *ifp, u_int dlt, u_int hdrlen, struct bpf_if **driverp) { struct bpf_if *bp; - bp = malloc(sizeof(*bp), M_BPF, M_NOWAIT | M_ZERO); - if (bp == NULL) - panic("bpfattach"); + KASSERT(*driverp == NULL, ("bpfattach2: driverp already initialized")); + + bp = malloc(sizeof(*bp), M_BPF, M_WAITOK | M_ZERO); + rw_init(&bp->bif_lock, "bpf interface lock"); LIST_INIT(&bp->bif_dlist); LIST_INIT(&bp->bif_wlist); bp->bif_ifp = ifp; bp->bif_dlt = dlt; - rw_init(&bp->bif_lock, "bpf interface lock"); - KASSERT(*driverp == NULL, ("bpfattach2: driverp already initialized")); + bp->bif_hdrlen = hdrlen; bp->bif_bpf = driverp; *driverp = bp; @@ -2712,8 +2712,6 @@ bpfattach2(struct ifnet *ifp, u_int dlt, u_int hdrlen, struct bpf_if **driverp) LIST_INSERT_HEAD(&bpf_iflist, bp, bif_next); BPF_UNLOCK(); - bp->bif_hdrlen = hdrlen; - if (bootverbose && IS_DEFAULT_VNET(curvnet)) if_printf(ifp, "bpf attached\n"); } diff --git a/freebsd/sys/net/bridgestp.c b/freebsd/sys/net/bridgestp.c index 49e772b3..b654b04e 100644 --- a/freebsd/sys/net/bridgestp.c +++ b/freebsd/sys/net/bridgestp.c @@ -2275,4 +2275,7 @@ bstp_destroy(struct bstp_port *bp) taskqueue_drain(taskqueue_swi, &bp->bp_statetask); taskqueue_drain(taskqueue_swi, &bp->bp_rtagetask); taskqueue_drain(taskqueue_swi, &bp->bp_mediatask); + + if (bp->bp_bs->bs_root_port == bp) + bstp_assign_roles(bp->bp_bs); } diff --git a/freebsd/sys/net/ethernet.h b/freebsd/sys/net/ethernet.h index fa75c1df..0753e31d 100644 --- a/freebsd/sys/net/ethernet.h +++ b/freebsd/sys/net/ethernet.h @@ -422,6 +422,7 @@ void ether_vlan_mtap(struct bpf_if *, struct mbuf *, struct mbuf *ether_vlanencap(struct mbuf *, uint16_t); bool ether_8021q_frame(struct mbuf **mp, struct ifnet *ife, struct ifnet *p, uint16_t vid, uint8_t pcp); +void ether_gen_addr(struct ifnet *ifp, struct ether_addr *hwaddr); #ifdef _SYS_EVENTHANDLER_H_ /* new ethernet interface attached event */ diff --git a/freebsd/sys/net/ieee_oui.h b/freebsd/sys/net/ieee_oui.h new file mode 100644 index 00000000..f543f561 --- /dev/null +++ b/freebsd/sys/net/ieee_oui.h @@ -0,0 +1,80 @@ +/* - + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2013 The FreeBSD Foundation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + * + * Author: George V. Neville-Neil + * + */ + +/* Organizationally Unique Identifier assigned by IEEE 14 Nov 2013 */ +#define OUI_FREEBSD_BASE 0x589cfc000000 +#define OUI_FREEBSD(nic) (OUI_FREEBSD_BASE | (nic)) + +/* + * OUIs are most often used to uniquely identify network interfaces + * and occupy the first 3 bytes of both destination and source MAC + * addresses. The following allocations exist so that various + * software systems associated with FreeBSD can have unique IDs in the + * absence of hardware. The use of OUIs for this purpose is not fully + * fleshed out but is now in common use in virtualization technology. + * + * Allocations from this range are expected to be made using COMMON + * SENSE by developers. Do NOT take a large range just because + * they're currently wide open. Take the smallest useful range for + * your system. We have (2^24 - 2) available addresses (see Reserved + * Values below) but that is far from infinite. + * + * In the event of a conflict arbitration of allocation in this file + * is subject to core@ approval. + * + * Applications are differentiated based on the high order bit(s) of + * the remaining three bytes. Our first allocation has all 0s, the + * next allocation has the highest bit set. Allocating in this way + * gives us 254 allocations of 64K addresses. Address blocks can be + * concatenated if necessary. + * + * Reserved Values: 0x000000 and 0xffffff are reserved and MUST NOT BE + * allocated for any reason. + */ + +/* Allocate 20 bits to bhyve */ +#define OUI_FREEBSD_BHYVE_LOW OUI_FREEBSD(0x000001) +#define OUI_FREEBSD_BHYVE_HIGH OUI_FREEBSD(0x0fffff) + +/* + * Allocate 16 bits for a pool to give to various interfaces that need a + * generated address, but don't quite need to slice off a whole section of + * the OUI (e.g. cloned interfaces, one-off NICs of various vendors). + * + * ether_gen_addr should be used to generate an address from this pool. + */ +#define OUI_FREEBSD_GENERATED_MASK 0x10ffff +#define OUI_FREEBSD_GENERATED_LOW OUI_FREEBSD(0x100000) +#define OUI_FREEBSD_GENERATED_HIGH OUI_FREEBSD(OU_FREEBSD_GENERATED_MASK) diff --git a/freebsd/sys/net/if.c b/freebsd/sys/net/if.c index 588753f9..5f0329fd 100644 --- a/freebsd/sys/net/if.c +++ b/freebsd/sys/net/if.c @@ -64,6 +64,8 @@ #include <sys/domain.h> #include <sys/jail.h> #include <sys/priv.h> +#include <sys/sched.h> +#include <sys/smp.h> #include <machine/stdarg.h> #include <vm/uma.h> @@ -1763,6 +1765,32 @@ if_data_copy(struct ifnet *ifp, struct if_data *ifd) ifd->ifi_noproto = ifp->if_get_counter(ifp, IFCOUNTER_NOPROTO); } +#ifndef __rtems__ +struct ifnet_read_lock { + struct mtx mtx; /* lock protecting tracker below */ + struct epoch_tracker et; +}; + +DPCPU_DEFINE_STATIC(struct ifnet_read_lock, ifnet_addr_read_lock); +DPCPU_DEFINE_STATIC(struct ifnet_read_lock, ifnet_maddr_read_lock); + +static void +ifnet_read_lock_init(void __unused *arg) +{ + struct ifnet_read_lock *pifrl; + int cpu; + + CPU_FOREACH(cpu) { + pifrl = DPCPU_ID_PTR(cpu, ifnet_addr_read_lock); + mtx_init(&pifrl->mtx, "ifnet_addr_read_lock", NULL, MTX_DEF); + + pifrl = DPCPU_ID_PTR(cpu, ifnet_maddr_read_lock); + mtx_init(&pifrl->mtx, "ifnet_maddr_read_lock", NULL, MTX_DEF); + } +} +SYSINIT(ifnet_read_lock_init, SI_SUB_CPU + 1, SI_ORDER_FIRST, &ifnet_read_lock_init, NULL); +#endif /* __rtems__ */ + /* * Wrapper functions for struct ifnet address list locking macros. These are * used by kernel modules to avoid encoding programming interface or binary @@ -1772,35 +1800,63 @@ if_data_copy(struct ifnet *ifp, struct if_data *ifd) void if_addr_rlock(struct ifnet *ifp) { - MPASS(*(uint64_t *)&ifp->if_addr_et == 0); - epoch_enter_preempt(net_epoch_preempt, &ifp->if_addr_et); +#ifndef __rtems__ + struct ifnet_read_lock *pifrl; + + sched_pin(); + pifrl = DPCPU_PTR(ifnet_addr_read_lock); + mtx_lock(&pifrl->mtx); + epoch_enter_preempt(net_epoch_preempt, &pifrl->et); +#else /* __rtems__ */ + epoch_enter_preempt(net_epoch_preempt, curthread->td_et); +#endif /* __rtems__ */ } void if_addr_runlock(struct ifnet *ifp) { - epoch_exit_preempt(net_epoch_preempt, &ifp->if_addr_et); -#ifdef INVARIANTS - bzero(&ifp->if_addr_et, sizeof(struct epoch_tracker)); -#endif +#ifndef __rtems__ + struct ifnet_read_lock *pifrl; + + pifrl = DPCPU_PTR(ifnet_addr_read_lock); + + epoch_exit_preempt(net_epoch_preempt, &pifrl->et); + mtx_unlock(&pifrl->mtx); + sched_unpin(); +#else /* __rtems__ */ + epoch_exit_preempt(net_epoch_preempt, curthread->td_et); +#endif /* __rtems__ */ } void if_maddr_rlock(if_t ifp) { +#ifndef __rtems__ + struct ifnet_read_lock *pifrl; - MPASS(*(uint64_t *)&ifp->if_maddr_et == 0); - epoch_enter_preempt(net_epoch_preempt, &ifp->if_maddr_et); + sched_pin(); + pifrl = DPCPU_PTR(ifnet_maddr_read_lock); + mtx_lock(&pifrl->mtx); + epoch_enter_preempt(net_epoch_preempt, &pifrl->et); +#else /* __rtems__ */ + epoch_enter_preempt(net_epoch_preempt, curthread->td_et); +#endif /* __rtems__ */ } void if_maddr_runlock(if_t ifp) { +#ifndef __rtems__ + struct ifnet_read_lock *pifrl; - epoch_exit_preempt(net_epoch_preempt, &ifp->if_maddr_et); -#ifdef INVARIANTS - bzero(&ifp->if_maddr_et, sizeof(struct epoch_tracker)); -#endif + pifrl = DPCPU_PTR(ifnet_maddr_read_lock); + + epoch_exit_preempt(net_epoch_preempt, &pifrl->et); + mtx_unlock(&pifrl->mtx); + sched_unpin(); +#else /* __rtems__ */ + epoch_exit_preempt(net_epoch_preempt, curthread->td_et); +#endif /* __rtems__ */ } /* diff --git a/freebsd/sys/net/if_bridge.c b/freebsd/sys/net/if_bridge.c index b5e231b8..4bfb67a8 100644 --- a/freebsd/sys/net/if_bridge.c +++ b/freebsd/sys/net/if_bridge.c @@ -228,7 +228,7 @@ struct bridge_softc { struct bstp_state sc_stp; /* STP state */ uint32_t sc_brtexceeded; /* # of cache drops */ struct ifnet *sc_ifaddr; /* member mac copied from */ - u_char sc_defaddr[6]; /* Default MAC address */ + struct ether_addr sc_defaddr; /* Default MAC address */ }; VNET_DEFINE_STATIC(struct mtx, bridge_list_mtx); @@ -237,7 +237,8 @@ static eventhandler_tag bridge_detach_cookie; int bridge_rtable_prune_period = BRIDGE_RTABLE_PRUNE_PERIOD; -uma_zone_t bridge_rtnode_zone; +VNET_DEFINE_STATIC(uma_zone_t, bridge_rtnode_zone); +#define V_bridge_rtnode_zone VNET(bridge_rtnode_zone) static int bridge_clone_create(struct if_clone *, int, caddr_t); static void bridge_clone_destroy(struct ifnet *); @@ -529,6 +530,9 @@ static void vnet_bridge_init(const void *unused __unused) { + V_bridge_rtnode_zone = uma_zcreate("bridge_rtnode", + sizeof(struct bridge_rtnode), NULL, NULL, NULL, NULL, + UMA_ALIGN_PTR, 0); BRIDGE_LIST_LOCK_INIT(); LIST_INIT(&V_bridge_list); V_bridge_cloner = if_clone_simple(bridge_name, @@ -544,6 +548,7 @@ vnet_bridge_uninit(const void *unused __unused) if_clone_detach(V_bridge_cloner); V_bridge_cloner = NULL; BRIDGE_LIST_LOCK_DESTROY(); + uma_zdestroy(V_bridge_rtnode_zone); } VNET_SYSUNINIT(vnet_bridge_uninit, SI_SUB_PSEUDO, SI_ORDER_ANY, vnet_bridge_uninit, NULL); @@ -554,9 +559,6 @@ bridge_modevent(module_t mod, int type, void *data) switch (type) { case MOD_LOAD: - bridge_rtnode_zone = uma_zcreate("bridge_rtnode", - sizeof(struct bridge_rtnode), NULL, NULL, NULL, NULL, - UMA_ALIGN_PTR, 0); bridge_dn_p = bridge_dummynet; bridge_detach_cookie = EVENTHANDLER_REGISTER( ifnet_departure_event, bridge_ifdetach, NULL, @@ -565,7 +567,6 @@ bridge_modevent(module_t mod, int type, void *data) case MOD_UNLOAD: EVENTHANDLER_DEREGISTER(ifnet_departure_event, bridge_detach_cookie); - uma_zdestroy(bridge_rtnode_zone); bridge_dn_p = NULL; break; default: @@ -672,16 +673,14 @@ bridge_clone_create(struct if_clone *ifc, int unit, caddr_t params) getcredhostid(curthread->td_ucred, &hostid); do { if (fb || hostid == 0) { - arc4rand(sc->sc_defaddr, ETHER_ADDR_LEN, 1); - sc->sc_defaddr[0] &= ~1;/* clear multicast bit */ - sc->sc_defaddr[0] |= 2; /* set the LAA bit */ + ether_gen_addr(ifp, &sc->sc_defaddr); } else { - sc->sc_defaddr[0] = 0x2; - sc->sc_defaddr[1] = (hostid >> 24) & 0xff; - sc->sc_defaddr[2] = (hostid >> 16) & 0xff; - sc->sc_defaddr[3] = (hostid >> 8 ) & 0xff; - sc->sc_defaddr[4] = hostid & 0xff; - sc->sc_defaddr[5] = ifp->if_dunit & 0xff; + sc->sc_defaddr.octet[0] = 0x2; + sc->sc_defaddr.octet[1] = (hostid >> 24) & 0xff; + sc->sc_defaddr.octet[2] = (hostid >> 16) & 0xff; + sc->sc_defaddr.octet[3] = (hostid >> 8 ) & 0xff; + sc->sc_defaddr.octet[4] = hostid & 0xff; + sc->sc_defaddr.octet[5] = ifp->if_dunit & 0xff; } fb = 1; @@ -689,7 +688,7 @@ bridge_clone_create(struct if_clone *ifc, int unit, caddr_t params) BRIDGE_LIST_LOCK(); LIST_FOREACH(sc2, &V_bridge_list, sc_list) { bifp = sc2->sc_ifp; - if (memcmp(sc->sc_defaddr, + if (memcmp(sc->sc_defaddr.octet, IF_LLADDR(bifp), ETHER_ADDR_LEN) == 0) { retry = 1; break; @@ -699,7 +698,7 @@ bridge_clone_create(struct if_clone *ifc, int unit, caddr_t params) } while (retry == 1); bstp_attach(&sc->sc_stp, &bridge_ops); - ether_ifattach(ifp, sc->sc_defaddr); + ether_ifattach(ifp, sc->sc_defaddr.octet); /* Now undo some of the damage... */ ifp->if_baudrate = 0; ifp->if_type = IFT_BRIDGE; @@ -734,6 +733,9 @@ bridge_clone_destroy(struct ifnet *ifp) bridge_delete_span(sc, bif); } + /* Tear down the routing table. */ + bridge_rtable_fini(sc); + BRIDGE_UNLOCK(sc); callout_drain(&sc->sc_brcallout); @@ -746,9 +748,6 @@ bridge_clone_destroy(struct ifnet *ifp) ether_ifdetach(ifp); if_free(ifp); - /* Tear down the routing table. */ - bridge_rtable_fini(sc); - BRIDGE_LOCK_DESTROY(sc); free(sc, M_DEVBUF); } @@ -1020,7 +1019,7 @@ bridge_delete_member(struct bridge_softc *sc, struct bridge_iflist *bif, */ if (V_bridge_inherit_mac && sc->sc_ifaddr == ifs) { if (LIST_EMPTY(&sc->sc_iflist)) { - bcopy(sc->sc_defaddr, + bcopy(&sc->sc_defaddr, IF_LLADDR(sc->sc_ifp), ETHER_ADDR_LEN); sc->sc_ifaddr = NULL; } else { @@ -1191,7 +1190,7 @@ bridge_ioctl_add(struct bridge_softc *sc, void *arg) * the default randomly generated one. */ if (V_bridge_inherit_mac && LIST_EMPTY(&sc->sc_iflist) && - !memcmp(IF_LLADDR(sc->sc_ifp), sc->sc_defaddr, ETHER_ADDR_LEN)) { + !memcmp(IF_LLADDR(sc->sc_ifp), sc->sc_defaddr.octet, ETHER_ADDR_LEN)) { bcopy(IF_LLADDR(ifs), IF_LLADDR(sc->sc_ifp), ETHER_ADDR_LEN); sc->sc_ifaddr = ifs; EVENTHANDLER_INVOKE(iflladdr_event, sc->sc_ifp); @@ -2673,7 +2672,7 @@ bridge_rtupdate(struct bridge_softc *sc, const uint8_t *dst, uint16_t vlan, * initialize the expiration time and Ethernet * address. */ - brt = uma_zalloc(bridge_rtnode_zone, M_NOWAIT | M_ZERO); + brt = uma_zalloc(V_bridge_rtnode_zone, M_NOWAIT | M_ZERO); if (brt == NULL) return (ENOMEM); @@ -2686,7 +2685,7 @@ bridge_rtupdate(struct bridge_softc *sc, const uint8_t *dst, uint16_t vlan, brt->brt_vlan = vlan; if ((error = bridge_rtnode_insert(sc, brt)) != 0) { - uma_zfree(bridge_rtnode_zone, brt); + uma_zfree(V_bridge_rtnode_zone, brt); return (error); } brt->brt_dst = bif; @@ -2770,11 +2769,14 @@ bridge_timer(void *arg) BRIDGE_LOCK_ASSERT(sc); + /* Destruction of rtnodes requires a proper vnet context */ + CURVNET_SET(sc->sc_ifp->if_vnet); bridge_rtage(sc); if (sc->sc_ifp->if_drv_flags & IFF_DRV_RUNNING) callout_reset(&sc->sc_brcallout, bridge_rtable_prune_period * hz, bridge_timer, sc); + CURVNET_RESTORE(); } /* @@ -3032,7 +3034,7 @@ bridge_rtnode_destroy(struct bridge_softc *sc, struct bridge_rtnode *brt) LIST_REMOVE(brt, brt_list); sc->sc_brtcnt--; brt->brt_dst->bif_addrcnt--; - uma_zfree(bridge_rtnode_zone, brt); + uma_zfree(V_bridge_rtnode_zone, brt); } /* @@ -3046,6 +3048,7 @@ bridge_rtable_expire(struct ifnet *ifp, int age) struct bridge_softc *sc = ifp->if_bridge; struct bridge_rtnode *brt; + CURVNET_SET(ifp->if_vnet); BRIDGE_LOCK(sc); /* @@ -3064,6 +3067,7 @@ bridge_rtable_expire(struct ifnet *ifp, int age) } } BRIDGE_UNLOCK(sc); + CURVNET_RESTORE(); } /* diff --git a/freebsd/sys/net/if_ethersubr.c b/freebsd/sys/net/if_ethersubr.c index 01e757e5..70b26160 100644 --- a/freebsd/sys/net/if_ethersubr.c +++ b/freebsd/sys/net/if_ethersubr.c @@ -44,11 +44,13 @@ #include <sys/systm.h> #include <sys/bus.h> #include <sys/eventhandler.h> +#include <sys/jail.h> #include <sys/kernel.h> #include <sys/lock.h> #include <sys/malloc.h> #include <sys/module.h> #include <sys/mbuf.h> +#include <sys/proc.h> #include <sys/priv.h> #include <sys/random.h> #include <sys/socket.h> @@ -56,6 +58,7 @@ #include <sys/sysctl.h> #include <sys/uuid.h> +#include <net/ieee_oui.h> #include <net/if.h> #include <net/if_var.h> #include <net/if_arp.h> @@ -87,6 +90,8 @@ #endif #include <security/mac/mac_framework.h> +#include <crypto/sha1.h> + #ifdef CTASSERT CTASSERT(sizeof (struct ether_header) == ETHER_ADDR_LEN * 2 + 2); CTASSERT(sizeof (struct ether_addr) == ETHER_ADDR_LEN); @@ -1370,5 +1375,38 @@ ether_8021q_frame(struct mbuf **mp, struct ifnet *ife, struct ifnet *p, return (true); } +/* + * Allocate an address from the FreeBSD Foundation OUI. This uses a + * cryptographic hash function on the containing jail's UUID and the interface + * name to attempt to provide a unique but stable address. Pseudo-interfaces + * which require a MAC address should use this function to allocate + * non-locally-administered addresses. + */ +void +ether_gen_addr(struct ifnet *ifp, struct ether_addr *hwaddr) +{ +#define ETHER_GEN_ADDR_BUFSIZ HOSTUUIDLEN + IFNAMSIZ + 2 + SHA1_CTX ctx; + char buf[ETHER_GEN_ADDR_BUFSIZ]; + char uuid[HOSTUUIDLEN + 1]; + uint64_t addr; + int i, sz; + char digest[SHA1_RESULTLEN]; + + getcredhostuuid(curthread->td_ucred, uuid, sizeof(uuid)); + sz = snprintf(buf, ETHER_GEN_ADDR_BUFSIZ, "%s-%s", uuid, ifp->if_xname); + SHA1Init(&ctx); + SHA1Update(&ctx, buf, sz); + SHA1Final(digest, &ctx); + + addr = ((digest[0] << 16) | (digest[1] << 8) | digest[2]) & + OUI_FREEBSD_GENERATED_MASK; + addr = OUI_FREEBSD(addr); + for (i = 0; i < ETHER_ADDR_LEN; ++i) { + hwaddr->octet[i] = addr >> ((ETHER_ADDR_LEN - i - 1) * 8) & + 0xFF; + } +} + DECLARE_MODULE(ether, ether_mod, SI_SUB_INIT_IF, SI_ORDER_ANY); MODULE_VERSION(ether, 1); diff --git a/freebsd/sys/net/if_gre.c b/freebsd/sys/net/if_gre.c index 4fbc105e..5aeb8266 100644 --- a/freebsd/sys/net/if_gre.c +++ b/freebsd/sys/net/if_gre.c @@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$"); #include <rtems/bsd/local/opt_inet.h> #include <rtems/bsd/local/opt_inet6.h> +#include <rtems/bsd/local/opt_rss.h> #include <sys/param.h> #include <sys/kernel.h> @@ -51,6 +52,7 @@ __FBSDID("$FreeBSD$"); #include <sys/priv.h> #include <sys/proc.h> #include <sys/socket.h> +#include <sys/socketvar.h> #include <sys/sockio.h> #include <sys/sx.h> #include <sys/sysctl.h> @@ -67,19 +69,27 @@ __FBSDID("$FreeBSD$"); #include <net/route.h> #include <netinet/in.h> +#include <netinet/in_pcb.h> #ifdef INET #include <netinet/in_var.h> #include <netinet/ip.h> #include <netinet/ip_var.h> +#ifdef RSS +#include <netinet/in_rss.h> +#endif #endif #ifdef INET6 #include <netinet/ip6.h> #include <netinet6/in6_var.h> #include <netinet6/ip6_var.h> +#ifdef RSS +#include <netinet6/in6_rss.h> +#endif #endif #include <netinet/ip_encap.h> +#include <netinet/udp.h> #include <net/bpf.h> #include <net/if_gre.h> @@ -153,6 +163,7 @@ vnet_gre_uninit(const void *unused __unused) #ifdef INET6 in6_gre_uninit(); #endif + /* XXX: epoch_call drain */ } VNET_SYSUNINIT(vnet_gre_uninit, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY, vnet_gre_uninit, NULL); @@ -272,6 +283,7 @@ gre_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) break; case GRESKEY: case GRESOPTS: + case GRESPORT: if ((error = priv_check(curthread, PRIV_NET_GRE)) != 0) break; if ((error = copyin(ifr_data_get_ptr(ifr), &opt, @@ -287,23 +299,45 @@ gre_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) } if (sc->gre_options == opt) break; + } else if (cmd == GRESPORT) { + if (opt != 0 && (opt < V_ipport_hifirstauto || + opt > V_ipport_hilastauto)) { + error = EINVAL; + break; + } + if (sc->gre_port == opt) + break; + if ((sc->gre_options & GRE_UDPENCAP) == 0) { + /* + * UDP encapsulation is not enabled, thus + * there is no need to reattach softc. + */ + sc->gre_port = opt; + break; + } } switch (sc->gre_family) { #ifdef INET case AF_INET: - in_gre_setopts(sc, cmd, opt); + error = in_gre_setopts(sc, cmd, opt); break; #endif #ifdef INET6 case AF_INET6: - in6_gre_setopts(sc, cmd, opt); + error = in6_gre_setopts(sc, cmd, opt); break; #endif default: + /* + * Tunnel is not yet configured. + * We can just change any parameters. + */ if (cmd == GRESKEY) sc->gre_key = opt; - else + if (cmd == GRESOPTS) sc->gre_options = opt; + if (cmd == GRESPORT) + sc->gre_port = opt; break; } /* @@ -319,6 +353,10 @@ gre_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) error = copyout(&sc->gre_options, ifr_data_get_ptr(ifr), sizeof(sc->gre_options)); break; + case GREGPORT: + error = copyout(&sc->gre_port, ifr_data_get_ptr(ifr), + sizeof(sc->gre_port)); + break; default: error = EINVAL; break; @@ -343,6 +381,7 @@ end: static void gre_delete_tunnel(struct gre_softc *sc) { + struct gre_socket *gs; sx_assert(&gre_ioctl_sx, SA_XLOCKED); if (sc->gre_family != 0) { @@ -352,6 +391,16 @@ gre_delete_tunnel(struct gre_softc *sc) free(sc->gre_hdr, M_GRE); sc->gre_family = 0; } + /* + * If this Tunnel was the last one that could use UDP socket, + * we should unlink socket from hash table and close it. + */ + if ((gs = sc->gre_so) != NULL && CK_LIST_EMPTY(&gs->list)) { + CK_LIST_REMOVE(gs, chain); + soclose(gs->so); + epoch_call(net_epoch_preempt, &gs->epoch_ctx, gre_sofree); + sc->gre_so = NULL; + } GRE2IFP(sc)->if_drv_flags &= ~IFF_DRV_RUNNING; if_link_state_change(GRE2IFP(sc), LINK_STATE_DOWN); } @@ -378,7 +427,38 @@ gre_hashdestroy(struct gre_list *hash) } void -gre_updatehdr(struct gre_softc *sc, struct grehdr *gh) +gre_sofree(epoch_context_t ctx) +{ + struct gre_socket *gs; + + gs = __containerof(ctx, struct gre_socket, epoch_ctx); + free(gs, M_GRE); +} + +static __inline uint16_t +gre_cksum_add(uint16_t sum, uint16_t a) +{ + uint16_t res; + + res = sum + a; + return (res + (res < a)); +} + +void +gre_update_udphdr(struct gre_softc *sc, struct udphdr *udp, uint16_t csum) +{ + + sx_assert(&gre_ioctl_sx, SA_XLOCKED); + MPASS(sc->gre_options & GRE_UDPENCAP); + + udp->uh_dport = htons(GRE_UDPPORT); + udp->uh_sport = htons(sc->gre_port); + udp->uh_sum = csum; + udp->uh_ulen = 0; +} + +void +gre_update_hdr(struct gre_softc *sc, struct grehdr *gh) { uint32_t *opts; uint16_t flags; @@ -545,6 +625,52 @@ gre_setseqn(struct grehdr *gh, uint32_t seq) *opts = htonl(seq); } +static uint32_t +gre_flowid(struct gre_softc *sc, struct mbuf *m, uint32_t af) +{ + uint32_t flowid; + + if ((sc->gre_options & GRE_UDPENCAP) == 0 || sc->gre_port != 0) + return (0); +#ifndef RSS + switch (af) { +#ifdef INET + case AF_INET: + flowid = mtod(m, struct ip *)->ip_src.s_addr ^ + mtod(m, struct ip *)->ip_dst.s_addr; + break; +#endif +#ifdef INET6 + case AF_INET6: + flowid = mtod(m, struct ip6_hdr *)->ip6_src.s6_addr32[3] ^ + mtod(m, struct ip6_hdr *)->ip6_dst.s6_addr32[3]; + break; +#endif + default: + flowid = 0; + } +#else /* RSS */ + switch (af) { +#ifdef INET + case AF_INET: + flowid = rss_hash_ip4_2tuple(mtod(m, struct ip *)->ip_src, + mtod(m, struct ip *)->ip_dst); + break; +#endif +#ifdef INET6 + case AF_INET6: + flowid = rss_hash_ip6_2tuple( + &mtod(m, struct ip6_hdr *)->ip6_src, + &mtod(m, struct ip6_hdr *)->ip6_dst); + break; +#endif + default: + flowid = 0; + } +#endif + return (flowid); +} + #define MTAG_GRE 1307983903 static int gre_transmit(struct ifnet *ifp, struct mbuf *m) @@ -552,7 +678,8 @@ gre_transmit(struct ifnet *ifp, struct mbuf *m) GRE_RLOCK_TRACKER; struct gre_softc *sc; struct grehdr *gh; - uint32_t af; + struct udphdr *uh; + uint32_t af, flowid; int error, len; uint16_t proto; @@ -579,6 +706,7 @@ gre_transmit(struct ifnet *ifp, struct mbuf *m) af = m->m_pkthdr.csum_data; BPF_MTAP2(ifp, &af, sizeof(af), m); m->m_flags &= ~(M_BCAST|M_MCAST); + flowid = gre_flowid(sc, m, af); M_SETFIB(m, sc->gre_fibnum); M_PREPEND(m, sc->gre_hlen, M_NOWAIT); if (m == NULL) { @@ -620,6 +748,19 @@ gre_transmit(struct ifnet *ifp, struct mbuf *m) error = ENETDOWN; goto drop; } + if (sc->gre_options & GRE_UDPENCAP) { + uh = (struct udphdr *)mtodo(m, len); + uh->uh_sport |= htons(V_ipport_hifirstauto) | + (flowid >> 16) | (flowid & 0xFFFF); + uh->uh_sport = htons(ntohs(uh->uh_sport) % + V_ipport_hilastauto); + uh->uh_ulen = htons(m->m_pkthdr.len - len); + uh->uh_sum = gre_cksum_add(uh->uh_sum, + htons(m->m_pkthdr.len - len + IPPROTO_UDP)); + m->m_pkthdr.csum_flags = sc->gre_csumflags; + m->m_pkthdr.csum_data = offsetof(struct udphdr, uh_sum); + len += sizeof(struct udphdr); + } gh = (struct grehdr *)mtodo(m, len); gh->gre_proto = proto; if (sc->gre_options & GRE_ENABLE_SEQ) @@ -637,7 +778,7 @@ gre_transmit(struct ifnet *ifp, struct mbuf *m) #endif #ifdef INET6 case AF_INET6: - error = in6_gre_output(m, af, sc->gre_hlen); + error = in6_gre_output(m, af, sc->gre_hlen, flowid); break; #endif default: diff --git a/freebsd/sys/net/if_gre.h b/freebsd/sys/net/if_gre.h index 4b93321a..de3c5979 100644 --- a/freebsd/sys/net/if_gre.h +++ b/freebsd/sys/net/if_gre.h @@ -53,14 +53,35 @@ struct greip { struct ip gi_ip; struct grehdr gi_gre; } __packed; -#endif + +struct greudp { + struct ip gi_ip; + struct udphdr gi_udp; + struct grehdr gi_gre; +} __packed; +#endif /* INET */ #ifdef INET6 struct greip6 { struct ip6_hdr gi6_ip6; struct grehdr gi6_gre; } __packed; -#endif + +struct greudp6 { + struct ip6_hdr gi6_ip6; + struct udphdr gi6_udp; + struct grehdr gi6_gre; +} __packed; +#endif /* INET6 */ + +CK_LIST_HEAD(gre_list, gre_softc); +CK_LIST_HEAD(gre_sockets, gre_socket); +struct gre_socket { + struct socket *so; + struct gre_list list; + CK_LIST_ENTRY(gre_socket) chain; + struct epoch_context epoch_ctx; +}; struct gre_softc { struct ifnet *gre_ifp; @@ -69,22 +90,26 @@ struct gre_softc { uint32_t gre_oseq; uint32_t gre_key; uint32_t gre_options; + uint32_t gre_csumflags; + uint32_t gre_port; u_int gre_fibnum; u_int gre_hlen; /* header size */ union { void *hdr; #ifdef INET - struct greip *gihdr; + struct greip *iphdr; + struct greudp *udphdr; #endif #ifdef INET6 - struct greip6 *gi6hdr; + struct greip6 *ip6hdr; + struct greudp6 *udp6hdr; #endif } gre_uhdr; + struct gre_socket *gre_so; CK_LIST_ENTRY(gre_softc) chain; CK_LIST_ENTRY(gre_softc) srchash; }; -CK_LIST_HEAD(gre_list, gre_softc); MALLOC_DECLARE(M_GRE); #ifndef GRE_HASH_SIZE @@ -98,28 +123,35 @@ MALLOC_DECLARE(M_GRE); #define GRE_WAIT() epoch_wait_preempt(net_epoch_preempt) #define gre_hdr gre_uhdr.hdr -#define gre_gihdr gre_uhdr.gihdr -#define gre_gi6hdr gre_uhdr.gi6hdr -#define gre_oip gre_gihdr->gi_ip -#define gre_oip6 gre_gi6hdr->gi6_ip6 +#define gre_iphdr gre_uhdr.iphdr +#define gre_ip6hdr gre_uhdr.ip6hdr +#define gre_udphdr gre_uhdr.udphdr +#define gre_udp6hdr gre_uhdr.udp6hdr + +#define gre_oip gre_iphdr->gi_ip +#define gre_udp gre_udphdr->gi_udp +#define gre_oip6 gre_ip6hdr->gi6_ip6 +#define gre_udp6 gre_udp6hdr->gi6_udp struct gre_list *gre_hashinit(void); void gre_hashdestroy(struct gre_list *); int gre_input(struct mbuf *, int, int, void *); -void gre_updatehdr(struct gre_softc *, struct grehdr *); +void gre_update_hdr(struct gre_softc *, struct grehdr *); +void gre_update_udphdr(struct gre_softc *, struct udphdr *, uint16_t); +void gre_sofree(epoch_context_t); void in_gre_init(void); void in_gre_uninit(void); -void in_gre_setopts(struct gre_softc *, u_long, uint32_t); +int in_gre_setopts(struct gre_softc *, u_long, uint32_t); int in_gre_ioctl(struct gre_softc *, u_long, caddr_t); int in_gre_output(struct mbuf *, int, int); void in6_gre_init(void); void in6_gre_uninit(void); -void in6_gre_setopts(struct gre_softc *, u_long, uint32_t); +int in6_gre_setopts(struct gre_softc *, u_long, uint32_t); int in6_gre_ioctl(struct gre_softc *, u_long, caddr_t); -int in6_gre_output(struct mbuf *, int, int); +int in6_gre_output(struct mbuf *, int, int, uint32_t); /* * CISCO uses special type for GRE tunnel created as part of WCCP * connection, while in fact those packets are just IPv4 encapsulated @@ -139,9 +171,15 @@ int in6_gre_output(struct mbuf *, int, int); #define GRESKEY _IOW('i', 108, struct ifreq) #define GREGOPTS _IOWR('i', 109, struct ifreq) #define GRESOPTS _IOW('i', 110, struct ifreq) +#define GREGPORT _IOWR('i', 111, struct ifreq) +#define GRESPORT _IOW('i', 112, struct ifreq) + +/* GRE-in-UDP encapsulation destination port as defined in RFC8086 */ +#define GRE_UDPPORT 4754 #define GRE_ENABLE_CSUM 0x0001 #define GRE_ENABLE_SEQ 0x0002 -#define GRE_OPTMASK (GRE_ENABLE_CSUM|GRE_ENABLE_SEQ) +#define GRE_UDPENCAP 0x0004 +#define GRE_OPTMASK (GRE_ENABLE_CSUM|GRE_ENABLE_SEQ|GRE_UDPENCAP) #endif /* _NET_IF_GRE_H_ */ diff --git a/freebsd/sys/net/if_lagg.c b/freebsd/sys/net/if_lagg.c index c9c1e8f9..af6f1667 100644 --- a/freebsd/sys/net/if_lagg.c +++ b/freebsd/sys/net/if_lagg.c @@ -113,6 +113,7 @@ static void lagg_clone_destroy(struct ifnet *); VNET_DEFINE_STATIC(struct if_clone *, lagg_cloner); #define V_lagg_cloner VNET(lagg_cloner) static const char laggname[] = "lagg"; +static MALLOC_DEFINE(M_LAGG, laggname, "802.3AD Link Aggregation Interface"); static void lagg_capabilities(struct lagg_softc *); static int lagg_port_create(struct lagg_softc *, struct ifnet *); @@ -480,10 +481,10 @@ lagg_clone_create(struct if_clone *ifc, int unit, caddr_t params) struct ifnet *ifp; static const u_char eaddr[6]; /* 00:00:00:00:00:00 */ - sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK|M_ZERO); + sc = malloc(sizeof(*sc), M_LAGG, M_WAITOK|M_ZERO); ifp = sc->sc_ifp = if_alloc(IFT_ETHER); if (ifp == NULL) { - free(sc, M_DEVBUF); + free(sc, M_LAGG); return (ENOSPC); } LAGG_SX_INIT(sc); @@ -570,7 +571,7 @@ lagg_clone_destroy(struct ifnet *ifp) LAGG_LIST_UNLOCK(); LAGG_SX_DESTROY(sc); - free(sc, M_DEVBUF); + free(sc, M_LAGG); } static void @@ -684,7 +685,7 @@ lagg_port_create(struct lagg_softc *sc, struct ifnet *ifp) ifr.ifr_mtu = oldmtu; } - lp = malloc(sizeof(struct lagg_port), M_DEVBUF, M_WAITOK|M_ZERO); + lp = malloc(sizeof(struct lagg_port), M_LAGG, M_WAITOK|M_ZERO); lp->lp_softc = sc; /* Check if port is a stacked lagg */ @@ -692,7 +693,7 @@ lagg_port_create(struct lagg_softc *sc, struct ifnet *ifp) SLIST_FOREACH(sc_ptr, &V_lagg_list, sc_entries) { if (ifp == sc_ptr->sc_ifp) { LAGG_LIST_UNLOCK(); - free(lp, M_DEVBUF); + free(lp, M_LAGG); if (oldmtu != -1) (*ifp->if_ioctl)(ifp, SIOCSIFMTU, (caddr_t)&ifr); @@ -703,7 +704,7 @@ lagg_port_create(struct lagg_softc *sc, struct ifnet *ifp) if (lagg_port_checkstacking(sc_ptr) >= LAGG_MAX_STACKING) { LAGG_LIST_UNLOCK(); - free(lp, M_DEVBUF); + free(lp, M_LAGG); if (oldmtu != -1) (*ifp->if_ioctl)(ifp, SIOCSIFMTU, (caddr_t)&ifr); @@ -751,7 +752,6 @@ lagg_port_create(struct lagg_softc *sc, struct ifnet *ifp) * is predictable and `ifconfig laggN create ...` command * will lead to the same result each time. */ - LAGG_RLOCK(); CK_SLIST_FOREACH(tlp, &sc->sc_ports, lp_entries) { if (tlp->lp_ifp->if_index < ifp->if_index && ( CK_SLIST_NEXT(tlp, lp_entries) == NULL || @@ -759,7 +759,6 @@ lagg_port_create(struct lagg_softc *sc, struct ifnet *ifp) ifp->if_index)) break; } - LAGG_RUNLOCK(); if (tlp != NULL) CK_SLIST_INSERT_AFTER(tlp, lp, lp_entries); else @@ -814,7 +813,7 @@ lagg_port_destroy_cb(epoch_context_t ec) ifp = lp->lp_ifp; if_rele(ifp); - free(lp, M_DEVBUF); + free(lp, M_LAGG); } static int @@ -1537,14 +1536,17 @@ lagg_snd_tag_alloc(struct ifnet *ifp, struct lagg_lb *lb; uint32_t p; + LAGG_RLOCK(); switch (sc->sc_proto) { case LAGG_PROTO_FAILOVER: lp = lagg_link_active(sc, sc->sc_primary); break; case LAGG_PROTO_LOADBALANCE: if ((sc->sc_opts & LAGG_OPT_USE_FLOWID) == 0 || - params->hdr.flowtype == M_HASHTYPE_NONE) + params->hdr.flowtype == M_HASHTYPE_NONE) { + LAGG_RUNLOCK(); return (EOPNOTSUPP); + } p = params->hdr.flowid >> sc->flowid_shift; p %= sc->sc_count; lb = (struct lagg_lb *)sc->sc_psc; @@ -1553,16 +1555,22 @@ lagg_snd_tag_alloc(struct ifnet *ifp, break; case LAGG_PROTO_LACP: if ((sc->sc_opts & LAGG_OPT_USE_FLOWID) == 0 || - params->hdr.flowtype == M_HASHTYPE_NONE) + params->hdr.flowtype == M_HASHTYPE_NONE) { + LAGG_RUNLOCK(); return (EOPNOTSUPP); + } lp = lacp_select_tx_port_by_hash(sc, params->hdr.flowid); break; default: + LAGG_RUNLOCK(); return (EOPNOTSUPP); } - if (lp == NULL) + if (lp == NULL) { + LAGG_RUNLOCK(); return (EOPNOTSUPP); + } ifp = lp->lp_ifp; + LAGG_RUNLOCK(); if (ifp == NULL || ifp->if_snd_tag_alloc == NULL || (ifp->if_capenable & IFCAP_TXRTLMT) == 0) return (EOPNOTSUPP); @@ -1586,7 +1594,7 @@ lagg_setmulti(struct lagg_port *lp) CK_STAILQ_FOREACH(ifma, &scifp->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family != AF_LINK) continue; - mc = malloc(sizeof(struct lagg_mc), M_DEVBUF, M_NOWAIT); + mc = malloc(sizeof(struct lagg_mc), M_LAGG, M_NOWAIT); if (mc == NULL) { IF_ADDR_WUNLOCK(scifp); return (ENOMEM); @@ -1617,7 +1625,7 @@ lagg_clrmulti(struct lagg_port *lp) SLIST_REMOVE(&lp->lp_mc_head, mc, lagg_mc, mc_entries); if (mc->mc_ifma && lp->lp_detaching == 0) if_delmulti_ifma(mc->mc_ifma); - free(mc, M_DEVBUF); + free(mc, M_LAGG); } return (0); } @@ -1846,12 +1854,20 @@ struct lagg_port * lagg_link_active(struct lagg_softc *sc, struct lagg_port *lp) { struct lagg_port *lp_next, *rval = NULL; - struct epoch_tracker net_et; /* * Search a port which reports an active link state. */ +#ifdef INVARIANTS + /* + * This is called with either LAGG_RLOCK() held or + * LAGG_XLOCK(sc) held. + */ + if (!in_epoch(net_epoch_preempt)) + LAGG_XLOCK_ASSERT(sc); +#endif + if (lp == NULL) goto search; if (LAGG_PORTACTIVE(lp)) { @@ -1864,15 +1880,12 @@ lagg_link_active(struct lagg_softc *sc, struct lagg_port *lp) goto found; } - search: - epoch_enter_preempt(net_epoch_preempt, &net_et); +search: CK_SLIST_FOREACH(lp_next, &sc->sc_ports, lp_entries) { if (LAGG_PORTACTIVE(lp_next)) { - epoch_exit_preempt(net_epoch_preempt, &net_et); return (lp_next); } } - epoch_exit_preempt(net_epoch_preempt, &net_et); found: return (rval); } @@ -1954,7 +1967,7 @@ lagg_bcast_start(struct lagg_softc *sc, struct mbuf *m) struct lagg_port *lp, *last = NULL; struct mbuf *m0; - LAGG_RLOCK(); + LAGG_RLOCK_ASSERT(); CK_SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) { if (!LAGG_PORTACTIVE(lp)) continue; @@ -1975,7 +1988,6 @@ lagg_bcast_start(struct lagg_softc *sc, struct mbuf *m) } last = lp; } - LAGG_RUNLOCK(); if (last == NULL) { m_freem(m); @@ -2061,7 +2073,7 @@ lagg_lb_attach(struct lagg_softc *sc) struct lagg_lb *lb; LAGG_XLOCK_ASSERT(sc); - lb = malloc(sizeof(struct lagg_lb), M_DEVBUF, M_WAITOK | M_ZERO); + lb = malloc(sizeof(struct lagg_lb), M_LAGG, M_WAITOK | M_ZERO); lb->lb_key = m_ether_tcpip_hash_init(); sc->sc_psc = lb; @@ -2076,7 +2088,7 @@ lagg_lb_detach(struct lagg_softc *sc) lb = (struct lagg_lb *)sc->sc_psc; if (lb != NULL) - free(lb, M_DEVBUF); + free(lb, M_LAGG); } static int @@ -2088,7 +2100,7 @@ lagg_lb_porttable(struct lagg_softc *sc, struct lagg_port *lp) rv = 0; bzero(&lb->lb_ports, sizeof(lb->lb_ports)); - LAGG_RLOCK(); + LAGG_XLOCK_ASSERT(sc); CK_SLIST_FOREACH(lp_next, &sc->sc_ports, lp_entries) { if (lp_next == lp) continue; @@ -2101,7 +2113,6 @@ lagg_lb_porttable(struct lagg_softc *sc, struct lagg_port *lp) sc->sc_ifname, lp_next->lp_ifp->if_xname, i); lb->lb_ports[i++] = lp_next; } - LAGG_RUNLOCK(); return (rv); } diff --git a/freebsd/sys/net/if_stf.c b/freebsd/sys/net/if_stf.c index 3ba9f8c0..7185fb8d 100644 --- a/freebsd/sys/net/if_stf.c +++ b/freebsd/sys/net/if_stf.c @@ -730,6 +730,7 @@ stf_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) } ifp->if_flags |= IFF_UP; + ifp->if_drv_flags |= IFF_DRV_RUNNING; break; case SIOCADDMULTI: diff --git a/freebsd/sys/net/if_tap.c b/freebsd/sys/net/if_tap.c index a540a59a..4ca35b66 100644 --- a/freebsd/sys/net/if_tap.c +++ b/freebsd/sys/net/if_tap.c @@ -43,6 +43,7 @@ #include <sys/param.h> #include <sys/conf.h> +#include <sys/lock.h> #include <sys/fcntl.h> #include <sys/filio.h> #include <sys/jail.h> @@ -57,6 +58,7 @@ #include <sys/signalvar.h> #include <sys/socket.h> #include <sys/sockio.h> +#include <sys/sx.h> #include <sys/sysctl.h> #include <sys/systm.h> #include <sys/ttycom.h> @@ -165,6 +167,9 @@ MALLOC_DECLARE(M_TAP); MALLOC_DEFINE(M_TAP, CDEV_NAME, "Ethernet tunnel interface"); SYSCTL_INT(_debug, OID_AUTO, if_tap_debug, CTLFLAG_RW, &tapdebug, 0, ""); +static struct sx tap_ioctl_sx; +SX_SYSINIT(tap_ioctl_sx, &tap_ioctl_sx, "tap_ioctl"); + SYSCTL_DECL(_net_link); static SYSCTL_NODE(_net_link, OID_AUTO, tap, CTLFLAG_RW, 0, "Ethernet tunnel software network interface"); @@ -177,6 +182,7 @@ SYSCTL_INT(_net_link_tap, OID_AUTO, devfs_cloning, CTLFLAG_RWTUN, &tapdclone, 0, SYSCTL_INT(_net_link_tap, OID_AUTO, debug, CTLFLAG_RW, &tapdebug, 0, ""); DEV_MODULE(if_tap, tapmodevent, NULL); +MODULE_VERSION(if_tap, 1); static int tap_clone_create(struct if_clone *ifc, int unit, caddr_t params) @@ -219,11 +225,17 @@ tap_destroy(struct tap_softc *tp) struct ifnet *ifp = tp->tap_ifp; CURVNET_SET(ifp->if_vnet); + destroy_dev(tp->tap_dev); seldrain(&tp->tap_rsel); knlist_clear(&tp->tap_rsel.si_note, 0); knlist_destroy(&tp->tap_rsel.si_note); ether_ifdetach(ifp); + + sx_xlock(&tap_ioctl_sx); + ifp->if_softc = NULL; + sx_xunlock(&tap_ioctl_sx); + if_free(ifp); mtx_destroy(&tp->tap_mtx); @@ -606,12 +618,18 @@ tapifinit(void *xtp) static int tapifioctl(struct ifnet *ifp, u_long cmd, caddr_t data) { - struct tap_softc *tp = ifp->if_softc; + struct tap_softc *tp; struct ifreq *ifr = (struct ifreq *)data; struct ifstat *ifs = NULL; struct ifmediareq *ifmr = NULL; int dummy, error = 0; + sx_xlock(&tap_ioctl_sx); + tp = ifp->if_softc; + if (tp == NULL) { + error = ENXIO; + goto bad; + } switch (cmd) { case SIOCSIFFLAGS: /* XXX -- just like vmnet does */ case SIOCADDMULTI: @@ -654,6 +672,8 @@ tapifioctl(struct ifnet *ifp, u_long cmd, caddr_t data) break; } +bad: + sx_xunlock(&tap_ioctl_sx); return (error); } /* tapifioctl */ diff --git a/freebsd/sys/net/if_tun.c b/freebsd/sys/net/if_tun.c index ee5c78b0..9c11cbc2 100644 --- a/freebsd/sys/net/if_tun.c +++ b/freebsd/sys/net/if_tun.c @@ -22,6 +22,7 @@ #include <rtems/bsd/local/opt_inet6.h> #include <sys/param.h> +#include <sys/lock.h> #include <sys/priv.h> #include <sys/proc.h> #include <sys/systm.h> @@ -32,6 +33,7 @@ #include <sys/fcntl.h> #include <sys/filio.h> #include <sys/sockio.h> +#include <sys/sx.h> #include <sys/ttycom.h> #include <sys/poll.h> #include <sys/selinfo.h> @@ -81,17 +83,13 @@ struct tun_softc { #define TUN_RWAIT 0x0040 #define TUN_ASYNC 0x0080 #define TUN_IFHEAD 0x0100 +#define TUN_DYING 0x0200 #define TUN_READY (TUN_OPEN | TUN_INITED) - /* - * XXXRW: tun_pid is used to exclusively lock /dev/tun. Is this - * actually needed? Can we just return EBUSY if already open? - * Problem is that this involved inherent races when a tun device - * is handed off from one process to another, as opposed to just - * being slightly stale informationally. - */ +#ifndef __rtems__ pid_t tun_pid; /* owning pid */ +#endif /* __rtems__ */ struct ifnet *tun_ifp; /* the interface */ struct sigio *tun_sigio; /* information for async I/O */ struct selinfo tun_rsel; /* read select */ @@ -117,6 +115,9 @@ static struct clonedevs *tunclones; static TAILQ_HEAD(,tun_softc) tunhead = TAILQ_HEAD_INITIALIZER(tunhead); SYSCTL_INT(_debug, OID_AUTO, if_tun_debug, CTLFLAG_RW, &tundebug, 0, ""); +static struct sx tun_ioctl_sx; +SX_SYSINIT(tun_ioctl_sx, &tun_ioctl_sx, "tun_ioctl"); + SYSCTL_DECL(_net_link); static SYSCTL_NODE(_net_link, OID_AUTO, tun, CTLFLAG_RW, 0, "IP tunnel software network interface."); @@ -274,15 +275,22 @@ tun_destroy(struct tun_softc *tp) struct cdev *dev; mtx_lock(&tp->tun_mtx); + tp->tun_flags |= TUN_DYING; if ((tp->tun_flags & TUN_OPEN) != 0) cv_wait_unlock(&tp->tun_cv, &tp->tun_mtx); else mtx_unlock(&tp->tun_mtx); CURVNET_SET(TUN2IFP(tp)->if_vnet); + dev = tp->tun_dev; bpfdetach(TUN2IFP(tp)); if_detach(TUN2IFP(tp)); + + sx_xlock(&tun_ioctl_sx); + TUN2IFP(tp)->if_softc = NULL; + sx_xunlock(&tun_ioctl_sx); + free_unr(tun_unrhdr, TUN2IFP(tp)->if_dunit); if_free(TUN2IFP(tp)); destroy_dev(dev); @@ -466,27 +474,15 @@ tunopen(struct cdev *dev, int flag, int mode, struct thread *td) tp = dev->si_drv1; } - /* - * XXXRW: This use of tun_pid is subject to error due to the - * fact that a reference to the tunnel can live beyond the - * death of the process that created it. Can we replace this - * with a simple busy flag? - */ mtx_lock(&tp->tun_mtx); -#ifndef __rtems__ - if (tp->tun_pid != 0 && tp->tun_pid != td->td_proc->p_pid) { -#else /* __rtems__ */ - if (tp->tun_pid != 0 && tp->tun_pid != BSD_DEFAULT_PID) { -#endif /* __rtems__ */ + if ((tp->tun_flags & (TUN_OPEN | TUN_DYING)) != 0) { mtx_unlock(&tp->tun_mtx); return (EBUSY); } + #ifndef __rtems__ tp->tun_pid = td->td_proc->p_pid; -#else /* __rtems__ */ - tp->tun_pid = BSD_DEFAULT_PID; #endif /* __rtems__ */ - tp->tun_flags |= TUN_OPEN; ifp = TUN2IFP(tp); if_link_state_change(ifp, LINK_STATE_UP); @@ -510,8 +506,18 @@ tunclose(struct cdev *dev, int foo, int bar, struct thread *td) ifp = TUN2IFP(tp); mtx_lock(&tp->tun_mtx); - tp->tun_flags &= ~TUN_OPEN; - tp->tun_pid = 0; +#ifndef __rtems__ + /* + * Simply close the device if this isn't the controlling process. This + * may happen if, for instance, the tunnel has been handed off to + * another process. The original controller should be able to close it + * without putting us into an inconsistent state. + */ + if (td->td_proc->p_pid != tp->tun_pid) { + mtx_unlock(&tp->tun_mtx); + return (0); + } +#endif /* __rtems__ */ /* * junk all pending output @@ -550,6 +556,10 @@ tunclose(struct cdev *dev, int foo, int bar, struct thread *td) selwakeuppri(&tp->tun_rsel, PZERO + 1); KNOTE_LOCKED(&tp->tun_rsel.si_note, 0); TUNDEBUG (ifp, "closed\n"); + tp->tun_flags &= ~TUN_OPEN; +#ifndef __rtems__ + tp->tun_pid = 0; +#endif /* __rtems__ */ cv_broadcast(&tp->tun_cv); mtx_unlock(&tp->tun_mtx); @@ -598,18 +608,26 @@ static int tunifioctl(struct ifnet *ifp, u_long cmd, caddr_t data) { struct ifreq *ifr = (struct ifreq *)data; - struct tun_softc *tp = ifp->if_softc; + struct tun_softc *tp; struct ifstat *ifs; int error = 0; + sx_xlock(&tun_ioctl_sx); + tp = ifp->if_softc; + if (tp == NULL) { + error = ENXIO; + goto bad; + } switch(cmd) { case SIOCGIFSTATUS: ifs = (struct ifstat *)data; mtx_lock(&tp->tun_mtx); +#ifndef __rtems__ if (tp->tun_pid) snprintf(ifs->ascii, sizeof(ifs->ascii), "\tOpened by PID %d\n", tp->tun_pid); else +#endif /* __rtems__ */ ifs->ascii[0] = '\0'; mtx_unlock(&tp->tun_mtx); break; @@ -628,6 +646,8 @@ tunifioctl(struct ifnet *ifp, u_long cmd, caddr_t data) default: error = EINVAL; } +bad: + sx_xunlock(&tun_ioctl_sx); return (error); } @@ -809,13 +829,11 @@ tunioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, } break; case TUNSIFPID: - mtx_lock(&tp->tun_mtx); #ifndef __rtems__ + mtx_lock(&tp->tun_mtx); tp->tun_pid = curthread->td_proc->p_pid; -#else /* __rtems__ */ - tp->tun_pid = BSD_DEFAULT_PID; -#endif /* __rtems__ */ mtx_unlock(&tp->tun_mtx); +#endif /* __rtems__ */ break; case FIONBIO: break; diff --git a/freebsd/sys/net/if_var.h b/freebsd/sys/net/if_var.h index 6504837b..87551c4c 100644 --- a/freebsd/sys/net/if_var.h +++ b/freebsd/sys/net/if_var.h @@ -390,8 +390,7 @@ struct ifnet { struct netdump_methods *if_netdump_methods; #endif /* __rtems__ */ struct epoch_context if_epoch_ctx; - struct epoch_tracker if_addr_et; - struct epoch_tracker if_maddr_et; + void *if_unused[4]; #ifndef __rtems__ /* diff --git a/freebsd/sys/net/iflib.h b/freebsd/sys/net/iflib.h index f8524859..f718922e 100644 --- a/freebsd/sys/net/iflib.h +++ b/freebsd/sys/net/iflib.h @@ -248,7 +248,7 @@ struct if_shared_ctx { /* fields necessary for probe */ pci_vendor_info_t *isc_vendor_info; - char *isc_driver_version; + const char *isc_driver_version; /* optional function to transform the read values to match the table*/ void (*isc_parse_devinfo) (uint16_t *device_id, uint16_t *subvendor_id, uint16_t *subdevice_id, uint16_t *rev_id); @@ -381,6 +381,8 @@ void iflib_set_mac(if_ctx_t ctx, uint8_t mac[ETHER_ADDR_LEN]); void iflib_request_reset(if_ctx_t ctx); uint8_t iflib_in_detach(if_ctx_t ctx); +uint32_t iflib_get_rx_mbuf_sz(if_ctx_t ctx); + /* * If the driver can plug cleanly in to newbus use these */ diff --git a/freebsd/sys/net/pfvar.h b/freebsd/sys/net/pfvar.h index 22159bd9..248c1938 100644 --- a/freebsd/sys/net/pfvar.h +++ b/freebsd/sys/net/pfvar.h @@ -1021,6 +1021,17 @@ struct pfr_tstats { int pfrts_cnt; int pfrts_refcnt[PFR_REFCNT_MAX]; }; + +struct pfr_ktstats { + struct pfr_table pfrts_t; + counter_u64_t pfrkts_packets[PFR_DIR_MAX][PFR_OP_TABLE_MAX]; + counter_u64_t pfrkts_bytes[PFR_DIR_MAX][PFR_OP_TABLE_MAX]; + counter_u64_t pfrkts_match; + counter_u64_t pfrkts_nomatch; + long pfrkts_tzero; + int pfrkts_cnt; + int pfrkts_refcnt[PFR_REFCNT_MAX]; +}; #define pfrts_name pfrts_t.pfrt_name #define pfrts_flags pfrts_t.pfrt_flags @@ -1034,8 +1045,9 @@ union sockaddr_union { #endif /* _SOCKADDR_UNION_DEFINED */ struct pfr_kcounters { - u_int64_t pfrkc_packets[PFR_DIR_MAX][PFR_OP_ADDR_MAX]; - u_int64_t pfrkc_bytes[PFR_DIR_MAX][PFR_OP_ADDR_MAX]; + counter_u64_t pfrkc_packets[PFR_DIR_MAX][PFR_OP_ADDR_MAX]; + counter_u64_t pfrkc_bytes[PFR_DIR_MAX][PFR_OP_ADDR_MAX]; + long pfrkc_tzero; }; SLIST_HEAD(pfr_kentryworkq, pfr_kentry); @@ -1043,8 +1055,7 @@ struct pfr_kentry { struct radix_node pfrke_node[2]; union sockaddr_union pfrke_sa; SLIST_ENTRY(pfr_kentry) pfrke_workq; - struct pfr_kcounters *pfrke_counters; - long pfrke_tzero; + struct pfr_kcounters pfrke_counters; u_int8_t pfrke_af; u_int8_t pfrke_net; u_int8_t pfrke_not; @@ -1054,7 +1065,7 @@ struct pfr_kentry { SLIST_HEAD(pfr_ktableworkq, pfr_ktable); RB_HEAD(pfr_ktablehead, pfr_ktable); struct pfr_ktable { - struct pfr_tstats pfrkt_ts; + struct pfr_ktstats pfrkt_kts; RB_ENTRY(pfr_ktable) pfrkt_tree; SLIST_ENTRY(pfr_ktable) pfrkt_workq; struct radix_node_head *pfrkt_ip4; @@ -1065,18 +1076,18 @@ struct pfr_ktable { long pfrkt_larg; int pfrkt_nflags; }; -#define pfrkt_t pfrkt_ts.pfrts_t +#define pfrkt_t pfrkt_kts.pfrts_t #define pfrkt_name pfrkt_t.pfrt_name #define pfrkt_anchor pfrkt_t.pfrt_anchor #define pfrkt_ruleset pfrkt_t.pfrt_ruleset #define pfrkt_flags pfrkt_t.pfrt_flags -#define pfrkt_cnt pfrkt_ts.pfrts_cnt -#define pfrkt_refcnt pfrkt_ts.pfrts_refcnt -#define pfrkt_packets pfrkt_ts.pfrts_packets -#define pfrkt_bytes pfrkt_ts.pfrts_bytes -#define pfrkt_match pfrkt_ts.pfrts_match -#define pfrkt_nomatch pfrkt_ts.pfrts_nomatch -#define pfrkt_tzero pfrkt_ts.pfrts_tzero +#define pfrkt_cnt pfrkt_kts.pfrkts_cnt +#define pfrkt_refcnt pfrkt_kts.pfrkts_refcnt +#define pfrkt_packets pfrkt_kts.pfrkts_packets +#define pfrkt_bytes pfrkt_kts.pfrkts_bytes +#define pfrkt_match pfrkt_kts.pfrkts_match +#define pfrkt_nomatch pfrkt_kts.pfrkts_nomatch +#define pfrkt_tzero pfrkt_kts.pfrkts_tzero /* keep synced with pfi_kif, used in RB_FIND */ struct pfi_kif_cmp { diff --git a/freebsd/sys/net/rtsock.c b/freebsd/sys/net/rtsock.c index e1b87095..35656e48 100644 --- a/freebsd/sys/net/rtsock.c +++ b/freebsd/sys/net/rtsock.c @@ -627,6 +627,8 @@ route_output(struct mbuf *m, struct socket *so, ...) if (rt_xaddrs((caddr_t)(rtm + 1), len + (caddr_t)rtm, &info)) senderr(EINVAL); + if (rtm->rtm_flags & RTF_RNH_LOCKED) + senderr(EINVAL); info.rti_flags = rtm->rtm_flags; if (info.rti_info[RTAX_DST] == NULL || info.rti_info[RTAX_DST]->sa_family >= AF_MAX || diff --git a/freebsd/sys/net80211/ieee80211_ht.c b/freebsd/sys/net80211/ieee80211_ht.c index c5ce444b..da294488 100644 --- a/freebsd/sys/net80211/ieee80211_ht.c +++ b/freebsd/sys/net80211/ieee80211_ht.c @@ -1729,7 +1729,7 @@ ieee80211_ht_updateparams(struct ieee80211_node *ni, const struct ieee80211_ie_htinfo *htinfo; ieee80211_parse_htcap(ni, htcapie); - if (vap->iv_htcaps & IEEE80211_HTCAP_SMPS) + if (vap->iv_htcaps & IEEE80211_HTC_SMPS) htcap_update_mimo_ps(ni); htcap_update_shortgi(ni); htcap_update_ldpc(ni); @@ -1882,7 +1882,7 @@ ieee80211_ht_updatehtcap(struct ieee80211_node *ni, const uint8_t *htcapie) struct ieee80211vap *vap = ni->ni_vap; ieee80211_parse_htcap(ni, htcapie); - if (vap->iv_htcaps & IEEE80211_HTCAP_SMPS) + if (vap->iv_htcaps & IEEE80211_HTC_SMPS) htcap_update_mimo_ps(ni); htcap_update_shortgi(ni); htcap_update_ldpc(ni); diff --git a/freebsd/sys/netinet/cc/cc_newreno.c b/freebsd/sys/netinet/cc/cc_newreno.c index b1307c92..1ab85042 100644 --- a/freebsd/sys/netinet/cc/cc_newreno.c +++ b/freebsd/sys/netinet/cc/cc_newreno.c @@ -301,7 +301,12 @@ newreno_post_recovery(struct cc_var *ccv) pipe = CCV(ccv, snd_max) - ccv->curack; if (pipe < CCV(ccv, snd_ssthresh)) - CCV(ccv, snd_cwnd) = pipe + CCV(ccv, t_maxseg); + /* + * Ensure that cwnd does not collapse to 1 MSS under + * adverse conditons. Implements RFC6582 + */ + CCV(ccv, snd_cwnd) = max(pipe, CCV(ccv, t_maxseg)) + + CCV(ccv, t_maxseg); else CCV(ccv, snd_cwnd) = CCV(ccv, snd_ssthresh); } diff --git a/freebsd/sys/netinet/if_ether.c b/freebsd/sys/netinet/if_ether.c index 5539e973..a71cb7a5 100644 --- a/freebsd/sys/netinet/if_ether.c +++ b/freebsd/sys/netinet/if_ether.c @@ -435,10 +435,10 @@ arprequest(struct ifnet *ifp, const struct in_addr *sip, /* * Resolve an IP address into an ethernet address - heavy version. * Used internally by arpresolve(). - * We have already checked than we can't use existing lle without - * modification so we have to acquire LLE_EXCLUSIVE lle lock. + * We have already checked that we can't use an existing lle without + * modification so we have to acquire an LLE_EXCLUSIVE lle lock. * - * On success, desten and flags are filled in and the function returns 0; + * On success, desten and pflags are filled in and the function returns 0; * If the packet must be held pending resolution, we return EWOULDBLOCK * On other errors, we return the corresponding error code. * Note that m_freem() handles NULL. diff --git a/freebsd/sys/netinet/in.c b/freebsd/sys/netinet/in.c index ae32c8d9..f001faa5 100644 --- a/freebsd/sys/netinet/in.c +++ b/freebsd/sys/netinet/in.c @@ -192,15 +192,10 @@ int in_canforward(struct in_addr in) { u_long i = ntohl(in.s_addr); - u_long net; - if (IN_EXPERIMENTAL(i) || IN_MULTICAST(i) || IN_LINKLOCAL(i)) + if (IN_EXPERIMENTAL(i) || IN_MULTICAST(i) || IN_LINKLOCAL(i) || + IN_ZERONET(i) || IN_LOOPBACK(i)) return (0); - if (IN_CLASSA(i)) { - net = i & IN_CLASSA_NET; - if (net == 0 || net == (IN_LOOPBACKNET << IN_CLASSA_NSHIFT)) - return (0); - } return (1); } diff --git a/freebsd/sys/netinet/in_mcast.c b/freebsd/sys/netinet/in_mcast.c index 3b1d57f8..b989944c 100644 --- a/freebsd/sys/netinet/in_mcast.c +++ b/freebsd/sys/netinet/in_mcast.c @@ -2048,41 +2048,50 @@ inp_join_group(struct inpcb *inp, struct sockopt *sopt) ssa->ss.ss_family = AF_UNSPEC; switch (sopt->sopt_name) { - case IP_ADD_MEMBERSHIP: - case IP_ADD_SOURCE_MEMBERSHIP: { - struct ip_mreq_source mreqs; + case IP_ADD_MEMBERSHIP: { + struct ip_mreqn mreqn; - if (sopt->sopt_name == IP_ADD_MEMBERSHIP) { - error = sooptcopyin(sopt, &mreqs, - sizeof(struct ip_mreq), - sizeof(struct ip_mreq)); - /* - * Do argument switcharoo from ip_mreq into - * ip_mreq_source to avoid using two instances. - */ - mreqs.imr_interface = mreqs.imr_sourceaddr; - mreqs.imr_sourceaddr.s_addr = INADDR_ANY; - } else if (sopt->sopt_name == IP_ADD_SOURCE_MEMBERSHIP) { - error = sooptcopyin(sopt, &mreqs, - sizeof(struct ip_mreq_source), - sizeof(struct ip_mreq_source)); - } + if (sopt->sopt_valsize == sizeof(struct ip_mreqn)) + error = sooptcopyin(sopt, &mreqn, + sizeof(struct ip_mreqn), sizeof(struct ip_mreqn)); + else + error = sooptcopyin(sopt, &mreqn, + sizeof(struct ip_mreq), sizeof(struct ip_mreq)); if (error) return (error); gsa->sin.sin_family = AF_INET; gsa->sin.sin_len = sizeof(struct sockaddr_in); - gsa->sin.sin_addr = mreqs.imr_multiaddr; + gsa->sin.sin_addr = mreqn.imr_multiaddr; + if (!IN_MULTICAST(ntohl(gsa->sin.sin_addr.s_addr))) + return (EINVAL); - if (sopt->sopt_name == IP_ADD_SOURCE_MEMBERSHIP) { - ssa->sin.sin_family = AF_INET; - ssa->sin.sin_len = sizeof(struct sockaddr_in); - ssa->sin.sin_addr = mreqs.imr_sourceaddr; - } + if (sopt->sopt_valsize == sizeof(struct ip_mreqn) && + mreqn.imr_ifindex != 0) + ifp = ifnet_byindex(mreqn.imr_ifindex); + else + ifp = inp_lookup_mcast_ifp(inp, &gsa->sin, + mreqn.imr_address); + break; + } + case IP_ADD_SOURCE_MEMBERSHIP: { + struct ip_mreq_source mreqs; + error = sooptcopyin(sopt, &mreqs, sizeof(struct ip_mreq_source), + sizeof(struct ip_mreq_source)); + if (error) + return (error); + + gsa->sin.sin_family = ssa->sin.sin_family = AF_INET; + gsa->sin.sin_len = ssa->sin.sin_len = + sizeof(struct sockaddr_in); + + gsa->sin.sin_addr = mreqs.imr_multiaddr; if (!IN_MULTICAST(ntohl(gsa->sin.sin_addr.s_addr))) return (EINVAL); + ssa->sin.sin_addr = mreqs.imr_sourceaddr; + ifp = inp_lookup_mcast_ifp(inp, &gsa->sin, mreqs.imr_interface); CTR3(KTR_IGMPV3, "%s: imr_interface = 0x%08x, ifp = %p", @@ -2546,10 +2555,14 @@ out_in_multi_locked: if (is_final) { /* Remove the gap in the membership and filter array. */ + KASSERT(RB_EMPTY(&imf->imf_sources), + ("%s: imf_sources not empty", __func__)); for (++idx; idx < imo->imo_num_memberships; ++idx) { - imo->imo_membership[idx-1] = imo->imo_membership[idx]; - imo->imo_mfilters[idx-1] = imo->imo_mfilters[idx]; + imo->imo_membership[idx - 1] = imo->imo_membership[idx]; + imo->imo_mfilters[idx - 1] = imo->imo_mfilters[idx]; } + imf_init(&imo->imo_mfilters[idx - 1], MCAST_UNDEFINED, + MCAST_EXCLUDE); imo->imo_num_memberships--; } @@ -3052,7 +3065,14 @@ sysctl_ip_mcast_filters(SYSCTL_HANDLER_ARGS) #if defined(KTR) && (KTR_COMPILE & KTR_IGMPV3) -static const char *inm_modestrs[] = { "un", "in", "ex" }; +static const char *inm_modestrs[] = { + [MCAST_UNDEFINED] = "un", + [MCAST_INCLUDE] = "in", + [MCAST_EXCLUDE] = "ex", +}; +_Static_assert(MCAST_UNDEFINED == 0 && + MCAST_EXCLUDE + 1 == nitems(inm_modestrs), + "inm_modestrs: no longer matches #defines"); static const char * inm_mode_str(const int mode) @@ -3064,16 +3084,20 @@ inm_mode_str(const int mode) } static const char *inm_statestrs[] = { - "not-member", - "silent", - "idle", - "lazy", - "sleeping", - "awakening", - "query-pending", - "sg-query-pending", - "leaving" + [IGMP_NOT_MEMBER] = "not-member", + [IGMP_SILENT_MEMBER] = "silent", + [IGMP_REPORTING_MEMBER] = "reporting", + [IGMP_IDLE_MEMBER] = "idle", + [IGMP_LAZY_MEMBER] = "lazy", + [IGMP_SLEEPING_MEMBER] = "sleeping", + [IGMP_AWAKENING_MEMBER] = "awakening", + [IGMP_G_QUERY_PENDING_MEMBER] = "query-pending", + [IGMP_SG_QUERY_PENDING_MEMBER] = "sg-query-pending", + [IGMP_LEAVING_MEMBER] = "leaving", }; +_Static_assert(IGMP_NOT_MEMBER == 0 && + IGMP_LEAVING_MEMBER + 1 == nitems(inm_statestrs), + "inm_statetrs: no longer matches #defines"); static const char * inm_state_str(const int state) diff --git a/freebsd/sys/netinet/in_pcb.c b/freebsd/sys/netinet/in_pcb.c index 0bebb9ea..abcee41b 100644 --- a/freebsd/sys/netinet/in_pcb.c +++ b/freebsd/sys/netinet/in_pcb.c @@ -3410,16 +3410,11 @@ in_pcboutput_txrtlmt(struct inpcb *inp, struct ifnet *ifp, struct mbuf *mb) void in_pcboutput_eagain(struct inpcb *inp) { - struct socket *socket; bool did_upgrade; if (inp == NULL) return; - socket = inp->inp_socket; - if (socket == NULL) - return; - if (inp->inp_snd_tag == NULL) return; diff --git a/freebsd/sys/netinet/ip_fw.h b/freebsd/sys/netinet/ip_fw.h index 41351215..de0cc29d 100644 --- a/freebsd/sys/netinet/ip_fw.h +++ b/freebsd/sys/netinet/ip_fw.h @@ -134,6 +134,13 @@ typedef struct _ip_fw3_opheader { #define IP_FW_NPTV6_STATS 154 /* Get NPTv6 instance statistics */ #define IP_FW_NPTV6_RESET_STATS 155 /* Reset NPTv6 instance statistics */ +#define IP_FW_NAT64CLAT_CREATE 160 /* Create clat NAT64 instance */ +#define IP_FW_NAT64CLAT_DESTROY 161 /* Destroy clat NAT64 instance */ +#define IP_FW_NAT64CLAT_CONFIG 162 /* Modify clat NAT64 instance */ +#define IP_FW_NAT64CLAT_LIST 163 /* List clat NAT64 instances */ +#define IP_FW_NAT64CLAT_STATS 164 /* Get NAT64CLAT instance statistics */ +#define IP_FW_NAT64CLAT_RESET_STATS 165 /* Reset NAT64CLAT instance statistics */ + /* * The kernel representation of ipfw rules is made of a list of * 'instructions' (for all practical purposes equivalent to BPF diff --git a/freebsd/sys/netinet/ip_gre.c b/freebsd/sys/netinet/ip_gre.c index 1758bfff..5a024e16 100644 --- a/freebsd/sys/netinet/ip_gre.c +++ b/freebsd/sys/netinet/ip_gre.c @@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$"); #include <sys/jail.h> #include <sys/systm.h> #include <sys/socket.h> +#include <sys/socketvar.h> #include <sys/sockio.h> #include <sys/mbuf.h> #include <sys/errno.h> @@ -60,15 +61,19 @@ __FBSDID("$FreeBSD$"); #include <netinet/in.h> #include <netinet/in_var.h> +#include <netinet/in_pcb.h> #include <netinet/ip.h> #include <netinet/ip_encap.h> #include <netinet/ip_var.h> +#include <netinet/udp.h> +#include <netinet/udp_var.h> #ifdef INET6 #include <netinet/ip6.h> #endif #include <net/if_gre.h> +#include <machine/in_cksum.h> #define GRE_TTL 30 VNET_DEFINE(int, ip_gre_ttl) = GRE_TTL; @@ -76,14 +81,22 @@ VNET_DEFINE(int, ip_gre_ttl) = GRE_TTL; SYSCTL_INT(_net_inet_ip, OID_AUTO, grettl, CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip_gre_ttl), 0, "Default TTL value for encapsulated packets"); +struct in_gre_socket { + struct gre_socket base; + in_addr_t addr; +}; +VNET_DEFINE_STATIC(struct gre_sockets *, ipv4_sockets) = NULL; VNET_DEFINE_STATIC(struct gre_list *, ipv4_hashtbl) = NULL; VNET_DEFINE_STATIC(struct gre_list *, ipv4_srchashtbl) = NULL; +#define V_ipv4_sockets VNET(ipv4_sockets) #define V_ipv4_hashtbl VNET(ipv4_hashtbl) #define V_ipv4_srchashtbl VNET(ipv4_srchashtbl) #define GRE_HASH(src, dst) (V_ipv4_hashtbl[\ in_gre_hashval((src), (dst)) & (GRE_HASH_SIZE - 1)]) #define GRE_SRCHASH(src) (V_ipv4_srchashtbl[\ fnv_32_buf(&(src), sizeof(src), FNV1_32_INIT) & (GRE_HASH_SIZE - 1)]) +#define GRE_SOCKHASH(src) (V_ipv4_sockets[\ + fnv_32_buf(&(src), sizeof(src), FNV1_32_INIT) & (GRE_HASH_SIZE - 1)]) #define GRE_HASH_SC(sc) GRE_HASH((sc)->gre_oip.ip_src.s_addr,\ (sc)->gre_oip.ip_dst.s_addr) @@ -96,17 +109,43 @@ in_gre_hashval(in_addr_t src, in_addr_t dst) return (fnv_32_buf(&dst, sizeof(dst), ret)); } +static struct gre_socket* +in_gre_lookup_socket(in_addr_t addr) +{ + struct gre_socket *gs; + struct in_gre_socket *s; + + CK_LIST_FOREACH(gs, &GRE_SOCKHASH(addr), chain) { + s = __containerof(gs, struct in_gre_socket, base); + if (s->addr == addr) + break; + } + return (gs); +} + static int -in_gre_checkdup(const struct gre_softc *sc, in_addr_t src, in_addr_t dst) +in_gre_checkdup(const struct gre_softc *sc, in_addr_t src, in_addr_t dst, + uint32_t opts) { + struct gre_list *head; struct gre_softc *tmp; + struct gre_socket *gs; if (sc->gre_family == AF_INET && sc->gre_oip.ip_src.s_addr == src && - sc->gre_oip.ip_dst.s_addr == dst) + sc->gre_oip.ip_dst.s_addr == dst && + (sc->gre_options & GRE_UDPENCAP) == (opts & GRE_UDPENCAP)) return (EEXIST); - CK_LIST_FOREACH(tmp, &GRE_HASH(src, dst), chain) { + if (opts & GRE_UDPENCAP) { + gs = in_gre_lookup_socket(src); + if (gs == NULL) + return (0); + head = &gs->list; + } else + head = &GRE_HASH(src, dst); + + CK_LIST_FOREACH(tmp, head, chain) { if (tmp == sc) continue; if (tmp->gre_oip.ip_src.s_addr == src && @@ -183,35 +222,228 @@ in_gre_srcaddr(void *arg __unused, const struct sockaddr *sa, } static void +in_gre_udp_input(struct mbuf *m, int off, struct inpcb *inp, + const struct sockaddr *sa, void *ctx) +{ + struct epoch_tracker et; + struct gre_socket *gs; + struct gre_softc *sc; + in_addr_t dst; + + NET_EPOCH_ENTER_ET(et); + /* + * udp_append() holds reference to inp, it is safe to check + * inp_flags2 without INP_RLOCK(). + * If socket was closed before we have entered NET_EPOCH section, + * INP_FREED flag should be set. Otherwise it should be safe to + * make access to ctx data, because gre_so will be freed by + * gre_sofree() via epoch_call(). + */ + if (__predict_false(inp->inp_flags2 & INP_FREED)) { + NET_EPOCH_EXIT_ET(et); + m_freem(m); + return; + } + + gs = (struct gre_socket *)ctx; + dst = ((const struct sockaddr_in *)sa)->sin_addr.s_addr; + CK_LIST_FOREACH(sc, &gs->list, chain) { + if (sc->gre_oip.ip_dst.s_addr == dst) + break; + } + if (sc != NULL && (GRE2IFP(sc)->if_flags & IFF_UP) != 0){ + gre_input(m, off + sizeof(struct udphdr), IPPROTO_UDP, sc); + NET_EPOCH_EXIT_ET(et); + return; + } + m_freem(m); + NET_EPOCH_EXIT_ET(et); +} + +static int +in_gre_setup_socket(struct gre_softc *sc) +{ + struct sockopt sopt; + struct sockaddr_in sin; + struct in_gre_socket *s; + struct gre_socket *gs; + in_addr_t addr; + int error, value; + + /* + * NOTE: we are protected with gre_ioctl_sx lock. + * + * First check that socket is already configured. + * If so, check that source addres was not changed. + * If address is different, check that there are no other tunnels + * and close socket. + */ + addr = sc->gre_oip.ip_src.s_addr; + gs = sc->gre_so; + if (gs != NULL) { + s = __containerof(gs, struct in_gre_socket, base); + if (s->addr != addr) { + if (CK_LIST_EMPTY(&gs->list)) { + CK_LIST_REMOVE(gs, chain); + soclose(gs->so); + epoch_call(net_epoch_preempt, &gs->epoch_ctx, + gre_sofree); + } + gs = sc->gre_so = NULL; + } + } + + if (gs == NULL) { + /* + * Check that socket for given address is already + * configured. + */ + gs = in_gre_lookup_socket(addr); + if (gs == NULL) { + s = malloc(sizeof(*s), M_GRE, M_WAITOK | M_ZERO); + s->addr = addr; + gs = &s->base; + + error = socreate(sc->gre_family, &gs->so, + SOCK_DGRAM, IPPROTO_UDP, curthread->td_ucred, + curthread); + if (error != 0) { + if_printf(GRE2IFP(sc), + "cannot create socket: %d\n", error); + free(s, M_GRE); + return (error); + } + + error = udp_set_kernel_tunneling(gs->so, + in_gre_udp_input, NULL, gs); + if (error != 0) { + if_printf(GRE2IFP(sc), + "cannot set UDP tunneling: %d\n", error); + goto fail; + } + + memset(&sopt, 0, sizeof(sopt)); + sopt.sopt_dir = SOPT_SET; + sopt.sopt_level = IPPROTO_IP; + sopt.sopt_name = IP_BINDANY; + sopt.sopt_val = &value; + sopt.sopt_valsize = sizeof(value); + value = 1; + error = sosetopt(gs->so, &sopt); + if (error != 0) { + if_printf(GRE2IFP(sc), + "cannot set IP_BINDANY opt: %d\n", error); + goto fail; + } + + memset(&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_len = sizeof(sin); + sin.sin_addr.s_addr = addr; + sin.sin_port = htons(GRE_UDPPORT); + error = sobind(gs->so, (struct sockaddr *)&sin, + curthread); + if (error != 0) { + if_printf(GRE2IFP(sc), + "cannot bind socket: %d\n", error); + goto fail; + } + /* Add socket to the chain */ + CK_LIST_INSERT_HEAD(&GRE_SOCKHASH(addr), gs, chain); + } + } + + /* Add softc to the socket's list */ + CK_LIST_INSERT_HEAD(&gs->list, sc, chain); + sc->gre_so = gs; + return (0); +fail: + soclose(gs->so); + free(s, M_GRE); + return (error); +} + +static int in_gre_attach(struct gre_softc *sc) { + struct grehdr *gh; + int error; - sc->gre_hlen = sizeof(struct greip); + if (sc->gre_options & GRE_UDPENCAP) { + sc->gre_csumflags = CSUM_UDP; + sc->gre_hlen = sizeof(struct greudp); + sc->gre_oip.ip_p = IPPROTO_UDP; + gh = &sc->gre_udphdr->gi_gre; + gre_update_udphdr(sc, &sc->gre_udp, + in_pseudo(sc->gre_oip.ip_src.s_addr, + sc->gre_oip.ip_dst.s_addr, 0)); + } else { + sc->gre_hlen = sizeof(struct greip); + sc->gre_oip.ip_p = IPPROTO_GRE; + gh = &sc->gre_iphdr->gi_gre; + } sc->gre_oip.ip_v = IPVERSION; sc->gre_oip.ip_hl = sizeof(struct ip) >> 2; - sc->gre_oip.ip_p = IPPROTO_GRE; - gre_updatehdr(sc, &sc->gre_gihdr->gi_gre); - CK_LIST_INSERT_HEAD(&GRE_HASH_SC(sc), sc, chain); + gre_update_hdr(sc, gh); + + /* + * If we return error, this means that sc is not linked, + * and caller should reset gre_family and free(sc->gre_hdr). + */ + if (sc->gre_options & GRE_UDPENCAP) { + error = in_gre_setup_socket(sc); + if (error != 0) + return (error); + } else + CK_LIST_INSERT_HEAD(&GRE_HASH_SC(sc), sc, chain); CK_LIST_INSERT_HEAD(&GRE_SRCHASH(sc->gre_oip.ip_src.s_addr), sc, srchash); + + /* Set IFF_DRV_RUNNING if interface is ready */ + in_gre_set_running(sc); + return (0); } -void +int in_gre_setopts(struct gre_softc *sc, u_long cmd, uint32_t value) { - - MPASS(cmd == GRESKEY || cmd == GRESOPTS); + int error; /* NOTE: we are protected with gre_ioctl_sx lock */ + MPASS(cmd == GRESKEY || cmd == GRESOPTS || cmd == GRESPORT); MPASS(sc->gre_family == AF_INET); + + /* + * If we are going to change encapsulation protocol, do check + * for duplicate tunnels. Return EEXIST here to do not confuse + * user. + */ + if (cmd == GRESOPTS && + (sc->gre_options & GRE_UDPENCAP) != (value & GRE_UDPENCAP) && + in_gre_checkdup(sc, sc->gre_oip.ip_src.s_addr, + sc->gre_oip.ip_dst.s_addr, value) == EADDRNOTAVAIL) + return (EEXIST); + CK_LIST_REMOVE(sc, chain); CK_LIST_REMOVE(sc, srchash); GRE_WAIT(); - if (cmd == GRESKEY) + switch (cmd) { + case GRESKEY: sc->gre_key = value; - else + break; + case GRESOPTS: sc->gre_options = value; - in_gre_attach(sc); + break; + case GRESPORT: + sc->gre_port = value; + break; + } + error = in_gre_attach(sc); + if (error != 0) { + sc->gre_family = 0; + free(sc->gre_hdr, M_GRE); + } + return (error); } int @@ -243,9 +475,10 @@ in_gre_ioctl(struct gre_softc *sc, u_long cmd, caddr_t data) if (V_ipv4_hashtbl == NULL) { V_ipv4_hashtbl = gre_hashinit(); V_ipv4_srchashtbl = gre_hashinit(); + V_ipv4_sockets = (struct gre_sockets *)gre_hashinit(); } error = in_gre_checkdup(sc, src->sin_addr.s_addr, - dst->sin_addr.s_addr); + dst->sin_addr.s_addr, sc->gre_options); if (error == EADDRNOTAVAIL) break; if (error == EEXIST) { @@ -253,7 +486,7 @@ in_gre_ioctl(struct gre_softc *sc, u_long cmd, caddr_t data) error = 0; break; } - ip = malloc(sizeof(struct greip) + 3 * sizeof(uint32_t), + ip = malloc(sizeof(struct greudp) + 3 * sizeof(uint32_t), M_GRE, M_WAITOK | M_ZERO); ip->ip_src.s_addr = src->sin_addr.s_addr; ip->ip_dst.s_addr = dst->sin_addr.s_addr; @@ -269,8 +502,11 @@ in_gre_ioctl(struct gre_softc *sc, u_long cmd, caddr_t data) sc->gre_hdr = ip; sc->gre_oseq = 0; sc->gre_iseq = UINT32_MAX; - in_gre_attach(sc); - in_gre_set_running(sc); + error = in_gre_attach(sc); + if (error != 0) { + sc->gre_family = 0; + free(sc->gre_hdr, M_GRE); + } break; case SIOCGIFPSRCADDR: case SIOCGIFPDSTADDR: @@ -356,5 +592,6 @@ in_gre_uninit(void) V_ipv4_hashtbl = NULL; GRE_WAIT(); gre_hashdestroy(V_ipv4_srchashtbl); + gre_hashdestroy((struct gre_list *)V_ipv4_sockets); } } diff --git a/freebsd/sys/netinet/ip_icmp.c b/freebsd/sys/netinet/ip_icmp.c index b7f0d3b1..970c680a 100644 --- a/freebsd/sys/netinet/ip_icmp.c +++ b/freebsd/sys/netinet/ip_icmp.c @@ -156,7 +156,7 @@ SYSCTL_INT(_net_inet_icmp, OID_AUTO, bmcastecho, CTLFLAG_VNET | CTLFLAG_RW, VNET_DEFINE_STATIC(int, icmptstamprepl) = 1; #define V_icmptstamprepl VNET(icmptstamprepl) -SYSCTL_INT(_net_inet_icmp, OID_AUTO, tstamprepl, CTLFLAG_RW, +SYSCTL_INT(_net_inet_icmp, OID_AUTO, tstamprepl, CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(icmptstamprepl), 0, "Respond to ICMP Timestamp packets"); diff --git a/freebsd/sys/netinet/ip_input.c b/freebsd/sys/netinet/ip_input.c index 136a774f..191b7867 100644 --- a/freebsd/sys/netinet/ip_input.c +++ b/freebsd/sys/netinet/ip_input.c @@ -503,10 +503,10 @@ ip_input(struct mbuf *m) IP_PROBE(receive, NULL, NULL, ip, m->m_pkthdr.rcvif, ip, NULL); - /* 127/8 must not appear on wire - RFC1122 */ + /* IN_LOOPBACK must not appear on the wire - RFC1122 */ ifp = m->m_pkthdr.rcvif; - if ((ntohl(ip->ip_dst.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET || - (ntohl(ip->ip_src.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) { + if (IN_LOOPBACK(ntohl(ip->ip_dst.s_addr)) || + IN_LOOPBACK(ntohl(ip->ip_src.s_addr))) { if ((ifp->if_flags & IFF_LOOPBACK) == 0) { IPSTAT_INC(ips_badaddr); goto bad; diff --git a/freebsd/sys/netinet/ip_output.c b/freebsd/sys/netinet/ip_output.c index bf83f31b..c9eb7aa3 100644 --- a/freebsd/sys/netinet/ip_output.c +++ b/freebsd/sys/netinet/ip_output.c @@ -590,9 +590,9 @@ sendit: } } - /* 127/8 must not appear on wire - RFC1122. */ - if ((ntohl(ip->ip_dst.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET || - (ntohl(ip->ip_src.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) { + /* IN_LOOPBACK must not appear on the wire - RFC1122. */ + if (IN_LOOPBACK(ntohl(ip->ip_dst.s_addr)) || + IN_LOOPBACK(ntohl(ip->ip_src.s_addr))) { if ((ifp->if_flags & IFF_LOOPBACK) == 0) { IPSTAT_INC(ips_badaddr); error = EADDRNOTAVAIL; diff --git a/freebsd/sys/netinet/raw_ip.c b/freebsd/sys/netinet/raw_ip.c index 1cac8d12..0760fa9e 100644 --- a/freebsd/sys/netinet/raw_ip.c +++ b/freebsd/sys/netinet/raw_ip.c @@ -456,6 +456,8 @@ rip_output(struct mbuf *m, struct socket *so, ...) u_long dst; int flags = ((so->so_options & SO_DONTROUTE) ? IP_ROUTETOIF : 0) | IP_ALLOWBROADCAST; + int cnt, hlen; + u_char opttype, optlen, *cp; va_start(ap, so); dst = va_arg(ap, u_long); @@ -510,26 +512,61 @@ rip_output(struct mbuf *m, struct socket *so, ...) m_freem(m); return(EMSGSIZE); } - INP_RLOCK(inp); ip = mtod(m, struct ip *); - error = prison_check_ip4(inp->inp_cred, &ip->ip_src); - if (error != 0) { - INP_RUNLOCK(inp); - m_freem(m); - return (error); + hlen = ip->ip_hl << 2; + if (m->m_len < hlen) { + m = m_pullup(m, hlen); + if (m == NULL) + return (EINVAL); + ip = mtod(m, struct ip *); } + INP_RLOCK(inp); /* * Don't allow both user specified and setsockopt options, * and don't allow packet length sizes that will crash. */ - if (((ip->ip_hl != (sizeof (*ip) >> 2)) && inp->inp_options) - || (ntohs(ip->ip_len) != m->m_pkthdr.len) - || (ntohs(ip->ip_len) < (ip->ip_hl << 2))) { + if ((hlen < sizeof (*ip)) + || ((hlen > sizeof (*ip)) && inp->inp_options) + || (ntohs(ip->ip_len) != m->m_pkthdr.len)) { INP_RUNLOCK(inp); m_freem(m); return (EINVAL); } + error = prison_check_ip4(inp->inp_cred, &ip->ip_src); + if (error != 0) { + INP_RUNLOCK(inp); + m_freem(m); + return (error); + } + /* + * Don't allow IP options which do not have the required + * structure as specified in section 3.1 of RFC 791 on + * pages 15-23. + */ + cp = (u_char *)(ip + 1); + cnt = hlen - sizeof (struct ip); + for (; cnt > 0; cnt -= optlen, cp += optlen) { + opttype = cp[IPOPT_OPTVAL]; + if (opttype == IPOPT_EOL) + break; + if (opttype == IPOPT_NOP) { + optlen = 1; + continue; + } + if (cnt < IPOPT_OLEN + sizeof(u_char)) { + INP_RUNLOCK(inp); + m_freem(m); + return (EINVAL); + } + optlen = cp[IPOPT_OLEN]; + if (optlen < IPOPT_OLEN + sizeof(u_char) || + optlen > cnt) { + INP_RUNLOCK(inp); + m_freem(m); + return (EINVAL); + } + } /* * This doesn't allow application to specify ID of zero, * but we got this limitation from the beginning of history. diff --git a/freebsd/sys/netinet/sctp.h b/freebsd/sys/netinet/sctp.h index 64fd5442..27e5fd49 100644 --- a/freebsd/sys/netinet/sctp.h +++ b/freebsd/sys/netinet/sctp.h @@ -491,6 +491,7 @@ struct sctp_error_auth_invalid_hmac { * time */ #define SCTP_SAT_NETWORK_BURST_INCR 2 /* how many times to multiply maxburst * in sat */ +#define SCTP_MAX_SENDALL_LIMIT 1024 /* Data Chuck Specific Flags */ #define SCTP_DATA_FRAG_MASK 0x03 @@ -516,6 +517,7 @@ struct sctp_error_auth_invalid_hmac { #define SCTP_PCB_FLAGS_BOUNDALL 0x00000004 #define SCTP_PCB_FLAGS_ACCEPTING 0x00000008 #define SCTP_PCB_FLAGS_UNBOUND 0x00000010 +#define SCTP_PCB_FLAGS_SND_ITERATOR_UP 0x00000020 #define SCTP_PCB_FLAGS_CLOSE_IP 0x00040000 #define SCTP_PCB_FLAGS_WAS_CONNECTED 0x00080000 #define SCTP_PCB_FLAGS_WAS_ABORTED 0x00100000 diff --git a/freebsd/sys/netinet/sctp_indata.c b/freebsd/sys/netinet/sctp_indata.c index 28e3f5b2..6c2658c3 100644 --- a/freebsd/sys/netinet/sctp_indata.c +++ b/freebsd/sys/netinet/sctp_indata.c @@ -949,6 +949,15 @@ sctp_inject_old_unordered_data(struct sctp_tcb *stcb, SCTPDBG(SCTP_DEBUG_XXX, "chunk is a first fsn: %u becomes fsn_included\n", chk->rec.data.fsn); + at = TAILQ_FIRST(&control->reasm); + if (at && SCTP_TSN_GT(chk->rec.data.fsn, at->rec.data.fsn)) { + /* + * The first chunk in the reassembly is a smaller + * TSN than this one, even though this has a first, + * it must be from a subsequent msg. + */ + goto place_chunk; + } if (control->first_frag_seen) { /* * In old un-ordered we can reassembly on one diff --git a/freebsd/sys/netinet/sctp_output.c b/freebsd/sys/netinet/sctp_output.c index 8d384748..cd4fcdc1 100644 --- a/freebsd/sys/netinet/sctp_output.c +++ b/freebsd/sys/netinet/sctp_output.c @@ -3735,6 +3735,7 @@ sctp_process_cmsgs_for_init(struct sctp_tcb *stcb, struct mbuf *control, int *er return (0); } +#if defined(INET) || defined(INET6) static struct sctp_tcb * sctp_findassociation_cmsgs(struct sctp_inpcb **inp_p, uint16_t port, @@ -3824,6 +3825,7 @@ sctp_findassociation_cmsgs(struct sctp_inpcb **inp_p, } return (NULL); } +#endif static struct mbuf * sctp_add_cookie(struct mbuf *init, int init_offset, @@ -4289,10 +4291,12 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp, if (net->port) { mtu -= sizeof(struct udphdr); } - if ((stcb != NULL) && (stcb->asoc.smallest_mtu > mtu)) { - sctp_mtu_size_reset(inp, &stcb->asoc, mtu); + if (mtu < net->mtu) { + if ((stcb != NULL) && (stcb->asoc.smallest_mtu > mtu)) { + sctp_mtu_size_reset(inp, &stcb->asoc, mtu); + } + net->mtu = mtu; } - net->mtu = mtu; } } else if (ro->ro_rt == NULL) { /* route was freed */ @@ -4647,10 +4651,12 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp, if (net->port) { mtu -= sizeof(struct udphdr); } - if ((stcb != NULL) && (stcb->asoc.smallest_mtu > mtu)) { - sctp_mtu_size_reset(inp, &stcb->asoc, mtu); + if (mtu < net->mtu) { + if ((stcb != NULL) && (stcb->asoc.smallest_mtu > mtu)) { + sctp_mtu_size_reset(inp, &stcb->asoc, mtu); + } + net->mtu = mtu; } - net->mtu = mtu; } } else if (ifp) { if (ND_IFINFO(ifp)->linkmtu && @@ -6800,15 +6806,19 @@ sctp_sendall_completes(void *ptr, uint32_t val SCTP_UNUSED) */ /* now free everything */ + if (ca->inp) { + /* Lets clear the flag to allow others to run. */ + ca->inp->sctp_flags &= ~SCTP_PCB_FLAGS_SND_ITERATOR_UP; + } sctp_m_freem(ca->m); SCTP_FREE(ca, SCTP_M_COPYAL); } static struct mbuf * -sctp_copy_out_all(struct uio *uio, int len) +sctp_copy_out_all(struct uio *uio, ssize_t len) { struct mbuf *ret, *at; - int left, willcpy, cancpy, error; + ssize_t left, willcpy, cancpy, error; ret = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_WAITOK, 1, MT_DATA); if (ret == NULL) { @@ -6823,17 +6833,17 @@ sctp_copy_out_all(struct uio *uio, int len) at = ret; while (left > 0) { /* Align data to the end */ - error = uiomove(mtod(at, caddr_t), willcpy, uio); + error = uiomove(mtod(at, caddr_t), (int)willcpy, uio); if (error) { err_out_now: sctp_m_freem(at); return (NULL); } - SCTP_BUF_LEN(at) = willcpy; + SCTP_BUF_LEN(at) = (int)willcpy; SCTP_BUF_NEXT_PKT(at) = SCTP_BUF_NEXT(at) = 0; left -= willcpy; if (left > 0) { - SCTP_BUF_NEXT(at) = sctp_get_mbuf_for_msg(left, 0, M_WAITOK, 1, MT_DATA); + SCTP_BUF_NEXT(at) = sctp_get_mbuf_for_msg((unsigned int)left, 0, M_WAITOK, 1, MT_DATA); if (SCTP_BUF_NEXT(at) == NULL) { goto err_out_now; } @@ -6853,6 +6863,14 @@ sctp_sendall(struct sctp_inpcb *inp, struct uio *uio, struct mbuf *m, int ret; struct sctp_copy_all *ca; + if (inp->sctp_flags & SCTP_PCB_FLAGS_SND_ITERATOR_UP) { + /* There is another. */ + return (EBUSY); + } + if (uio->uio_resid > SCTP_MAX_SENDALL_LIMIT) { + /* You must be less than the max! */ + return (EMSGSIZE); + } SCTP_MALLOC(ca, struct sctp_copy_all *, sizeof(struct sctp_copy_all), SCTP_M_COPYAL); if (ca == NULL) { @@ -6873,7 +6891,7 @@ sctp_sendall(struct sctp_inpcb *inp, struct uio *uio, struct mbuf *m, ca->sndrcv.sinfo_flags &= ~SCTP_SENDALL; /* get length and mbuf chain */ if (uio) { - ca->sndlen = (int)uio->uio_resid; + ca->sndlen = uio->uio_resid; ca->m = sctp_copy_out_all(uio, ca->sndlen); if (ca->m == NULL) { SCTP_FREE(ca, SCTP_M_COPYAL); @@ -6889,6 +6907,7 @@ sctp_sendall(struct sctp_inpcb *inp, struct uio *uio, struct mbuf *m, ca->sndlen += SCTP_BUF_LEN(mat); } } + inp->sctp_flags |= SCTP_PCB_FLAGS_SND_ITERATOR_UP; ret = sctp_initiate_iterator(NULL, sctp_sendall_iterator, NULL, SCTP_PCB_ANY_FLAGS, SCTP_PCB_ANY_FEATURES, SCTP_ASOC_ANY_STATE, @@ -12370,7 +12389,7 @@ sctp_copy_it_in(struct sctp_tcb *stcb, struct sctp_sndrcvinfo *srcv, struct uio *uio, struct sctp_nets *net, - int max_send_len, + ssize_t max_send_len, int user_marks_eor, int *error) { @@ -12516,7 +12535,7 @@ sctp_lower_sosend(struct socket *so, struct thread *p ) { - unsigned int sndlen = 0, max_len; + ssize_t sndlen = 0, max_len; int error, len; struct mbuf *top = NULL; int queue_only = 0, queue_only_for_init = 0; @@ -12538,7 +12557,8 @@ sctp_lower_sosend(struct socket *so, int got_all_of_the_send = 0; int hold_tcblock = 0; int non_blocking = 0; - uint32_t local_add_more, local_soresv = 0; + uint32_t local_add_more; + ssize_t local_soresv = 0; uint16_t port; uint16_t sinfo_flags; sctp_assoc_t sinfo_assoc_id; @@ -12568,12 +12588,12 @@ sctp_lower_sosend(struct socket *so, SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL); return (EINVAL); } - sndlen = (unsigned int)uio->uio_resid; + sndlen = uio->uio_resid; } else { top = SCTP_HEADER_TO_CHAIN(i_pak); sndlen = SCTP_HEADER_LEN(i_pak); } - SCTPDBG(SCTP_DEBUG_OUTPUT1, "Send called addr:%p send length %d\n", + SCTPDBG(SCTP_DEBUG_OUTPUT1, "Send called addr:%p send length %zu\n", (void *)addr, sndlen); if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) && @@ -12701,9 +12721,11 @@ sctp_lower_sosend(struct socket *so, SCTP_INP_WUNLOCK(inp); /* With the lock applied look again */ stcb = sctp_findassociation_ep_addr(&t_inp, addr, &net, NULL, NULL); +#if defined(INET) || defined(INET6) if ((stcb == NULL) && (control != NULL) && (port > 0)) { stcb = sctp_findassociation_cmsgs(&t_inp, port, control, &net, &error); } +#endif if (stcb == NULL) { SCTP_INP_WLOCK(inp); SCTP_INP_DECR_REF(inp); @@ -12840,7 +12862,7 @@ sctp_lower_sosend(struct socket *so, } /* would we block? */ if (non_blocking) { - uint32_t amount; + ssize_t amount; if (hold_tcblock == 0) { SCTP_TCB_LOCK(stcb); @@ -12861,7 +12883,7 @@ sctp_lower_sosend(struct socket *so, error = EWOULDBLOCK; goto out_unlocked; } - stcb->asoc.sb_send_resv += sndlen; + stcb->asoc.sb_send_resv += (uint32_t)sndlen; SCTP_TCB_UNLOCK(stcb); hold_tcblock = 0; } else { @@ -12927,7 +12949,7 @@ sctp_lower_sosend(struct socket *so, /* Are we aborting? */ if (srcv->sinfo_flags & SCTP_ABORT) { struct mbuf *mm; - int tot_demand, tot_out = 0, max_out; + ssize_t tot_demand, tot_out = 0, max_out; SCTP_STAT_INCR(sctps_sends_with_abort); if ((SCTP_GET_STATE(stcb) == SCTP_STATE_COOKIE_WAIT) || @@ -12961,7 +12983,7 @@ sctp_lower_sosend(struct socket *so, error = EMSGSIZE; goto out; } - mm = sctp_get_mbuf_for_msg(tot_demand, 0, M_WAITOK, 1, MT_DATA); + mm = sctp_get_mbuf_for_msg((unsigned int)tot_demand, 0, M_WAITOK, 1, MT_DATA); } if (mm == NULL) { SCTP_LTRACE_ERR_RET(NULL, stcb, net, SCTP_FROM_SCTP_OUTPUT, ENOMEM); @@ -12981,7 +13003,7 @@ sctp_lower_sosend(struct socket *so, ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT); ph->param_length = htons((uint16_t)(sizeof(struct sctp_paramhdr) + tot_out)); ph++; - SCTP_BUF_LEN(mm) = tot_out + sizeof(struct sctp_paramhdr); + SCTP_BUF_LEN(mm) = (int)(tot_out + sizeof(struct sctp_paramhdr)); if (top == NULL) { error = uiomove((caddr_t)ph, (int)tot_out, uio); if (error) { @@ -13022,12 +13044,7 @@ sctp_lower_sosend(struct socket *so, /* Calculate the maximum we can send */ inqueue_bytes = stcb->asoc.total_output_queue_size - (stcb->asoc.chunks_on_out_queue * SCTP_DATA_CHUNK_OVERHEAD(stcb)); if (SCTP_SB_LIMIT_SND(so) > inqueue_bytes) { - if (non_blocking) { - /* we already checked for non-blocking above. */ - max_len = sndlen; - } else { - max_len = SCTP_SB_LIMIT_SND(so) - inqueue_bytes; - } + max_len = SCTP_SB_LIMIT_SND(so) - inqueue_bytes; } else { max_len = 0; } @@ -13067,7 +13084,7 @@ sctp_lower_sosend(struct socket *so, * For non-eeor the whole message must fit in * the socket send buffer. */ - local_add_more = sndlen; + local_add_more = (uint32_t)sndlen; } len = 0; if (non_blocking) { @@ -13217,14 +13234,14 @@ skip_preblock: if ((max_len > SCTP_BASE_SYSCTL(sctp_add_more_threshold)) || (max_len && (SCTP_SB_LIMIT_SND(so) < SCTP_BASE_SYSCTL(sctp_add_more_threshold))) || - (uio->uio_resid && (uio->uio_resid <= (int)max_len))) { + (uio->uio_resid && (uio->uio_resid <= max_len))) { sndout = 0; new_tail = NULL; if (hold_tcblock) { SCTP_TCB_UNLOCK(stcb); hold_tcblock = 0; } - mm = sctp_copy_resume(uio, max_len, user_marks_eor, &error, &sndout, &new_tail); + mm = sctp_copy_resume(uio, (int)max_len, user_marks_eor, &error, &sndout, &new_tail); if ((mm == NULL) || error) { if (mm) { sctp_m_freem(mm); @@ -13287,7 +13304,7 @@ skip_preblock: SCTP_TCB_LOCK(stcb); hold_tcblock = 1; } - sctp_prune_prsctp(stcb, asoc, srcv, sndlen); + sctp_prune_prsctp(stcb, asoc, srcv, (int)sndlen); inqueue_bytes = stcb->asoc.total_output_queue_size - (stcb->asoc.chunks_on_out_queue * SCTP_DATA_CHUNK_OVERHEAD(stcb)); if (SCTP_SB_LIMIT_SND(so) > inqueue_bytes) max_len = SCTP_SB_LIMIT_SND(so) - inqueue_bytes; @@ -13409,7 +13426,7 @@ skip_preblock: min(SCTP_BASE_SYSCTL(sctp_add_more_threshold), SCTP_SB_LIMIT_SND(so)))) { if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_BLK_LOGGING_ENABLE) { sctp_log_block(SCTP_BLOCK_LOG_INTO_BLK, - asoc, (size_t)uio->uio_resid); + asoc, uio->uio_resid); } be.error = 0; stcb->block_entry = &be; diff --git a/freebsd/sys/netinet/sctp_pcb.c b/freebsd/sys/netinet/sctp_pcb.c index 782e5f1d..3d479149 100644 --- a/freebsd/sys/netinet/sctp_pcb.c +++ b/freebsd/sys/netinet/sctp_pcb.c @@ -4161,11 +4161,9 @@ sctp_aloc_a_assoc_id(struct sctp_inpcb *inp, struct sctp_tcb *stcb) struct sctpasochead *head; struct sctp_tcb *lstcb; - SCTP_INP_WLOCK(inp); try_again: if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) { /* TSNH */ - SCTP_INP_WUNLOCK(inp); return (0); } /* @@ -4184,8 +4182,7 @@ try_again: head = &inp->sctp_asocidhash[SCTP_PCBHASH_ASOC(id, inp->hashasocidmark)]; LIST_INSERT_HEAD(head, stcb, sctp_tcbasocidhash); stcb->asoc.in_asocid_hash = 1; - SCTP_INP_WUNLOCK(inp); - return id; + return (id); } /* @@ -4348,7 +4345,6 @@ sctp_aloc_assoc(struct sctp_inpcb *inp, struct sockaddr *firstaddr, memset(stcb, 0, sizeof(*stcb)); asoc = &stcb->asoc; - asoc->assoc_id = sctp_aloc_a_assoc_id(inp, stcb); SCTP_TCB_LOCK_INIT(stcb); SCTP_TCB_SEND_LOCK_INIT(stcb); stcb->rport = rport; @@ -4359,7 +4355,6 @@ sctp_aloc_assoc(struct sctp_inpcb *inp, struct sockaddr *firstaddr, /* failed */ SCTP_TCB_LOCK_DESTROY(stcb); SCTP_TCB_SEND_LOCK_DESTROY(stcb); - LIST_REMOVE(stcb, sctp_tcbasocidhash); SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_asoc), stcb); SCTP_DECR_ASOC_COUNT(); *error = err; @@ -4372,7 +4367,6 @@ sctp_aloc_assoc(struct sctp_inpcb *inp, struct sockaddr *firstaddr, /* inpcb freed while alloc going on */ SCTP_TCB_LOCK_DESTROY(stcb); SCTP_TCB_SEND_LOCK_DESTROY(stcb); - LIST_REMOVE(stcb, sctp_tcbasocidhash); SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_asoc), stcb); SCTP_INP_WUNLOCK(inp); SCTP_INP_INFO_WUNLOCK(); @@ -4383,6 +4377,7 @@ sctp_aloc_assoc(struct sctp_inpcb *inp, struct sockaddr *firstaddr, } SCTP_TCB_LOCK(stcb); + asoc->assoc_id = sctp_aloc_a_assoc_id(inp, stcb); /* now that my_vtag is set, add it to the hash */ head = &SCTP_BASE_INFO(sctp_asochash)[SCTP_PCBHASH_ASOC(stcb->asoc.my_vtag, SCTP_BASE_INFO(hashasocmark))]; /* put it in the bucket in the vtag hash of assoc's for the system */ @@ -4991,6 +4986,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre * in case. */ /* anything on the wheel needs to be removed */ + SCTP_TCB_SEND_LOCK(stcb); for (i = 0; i < asoc->streamoutcnt; i++) { struct sctp_stream_out *outs; @@ -4999,7 +4995,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre TAILQ_FOREACH_SAFE(sp, &outs->outqueue, next, nsp) { atomic_subtract_int(&asoc->stream_queue_cnt, 1); TAILQ_REMOVE(&outs->outqueue, sp, next); - stcb->asoc.ss_functions.sctp_ss_remove_from_stream(stcb, asoc, outs, sp, 0); + stcb->asoc.ss_functions.sctp_ss_remove_from_stream(stcb, asoc, outs, sp, 1); sctp_free_spbufspace(stcb, asoc, sp); if (sp->data) { if (so) { @@ -5021,6 +5017,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre sctp_free_a_strmoq(stcb, sp, SCTP_SO_LOCKED); } } + SCTP_TCB_SEND_UNLOCK(stcb); /* sa_ignore FREED_MEMORY */ TAILQ_FOREACH_SAFE(strrst, &asoc->resetHead, next_resp, nstrrst) { TAILQ_REMOVE(&asoc->resetHead, strrst, next_resp); diff --git a/freebsd/sys/netinet/sctp_structs.h b/freebsd/sys/netinet/sctp_structs.h index c4eafc26..451ae72b 100644 --- a/freebsd/sys/netinet/sctp_structs.h +++ b/freebsd/sys/netinet/sctp_structs.h @@ -166,7 +166,7 @@ struct sctp_copy_all { struct sctp_inpcb *inp; /* ep */ struct mbuf *m; struct sctp_sndrcvinfo sndrcv; - int sndlen; + ssize_t sndlen; int cnt_sent; int cnt_failed; }; diff --git a/freebsd/sys/netinet/sctp_usrreq.c b/freebsd/sys/netinet/sctp_usrreq.c index 54362ed5..39132719 100644 --- a/freebsd/sys/netinet/sctp_usrreq.c +++ b/freebsd/sys/netinet/sctp_usrreq.c @@ -632,7 +632,6 @@ connected_type: /* now what about control */ if (control) { if (inp->control) { - SCTP_PRINTF("huh? control set?\n"); sctp_m_freem(inp->control); inp->control = NULL; } @@ -1124,22 +1123,25 @@ sctp_fill_up_addresses_vrf(struct sctp_inpcb *inp, } #ifdef INET6 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) { + if (actual + sizeof(struct sockaddr_in6) > limit) { + return (actual); + } in6_sin_2_v4mapsin6(sin, (struct sockaddr_in6 *)sas); ((struct sockaddr_in6 *)sas)->sin6_port = inp->sctp_lport; sas = (struct sockaddr_storage *)((caddr_t)sas + sizeof(struct sockaddr_in6)); actual += sizeof(struct sockaddr_in6); } else { #endif - memcpy(sas, sin, sizeof(*sin)); + if (actual + sizeof(struct sockaddr_in) > limit) { + return (actual); + } + memcpy(sas, sin, sizeof(struct sockaddr_in)); ((struct sockaddr_in *)sas)->sin_port = inp->sctp_lport; - sas = (struct sockaddr_storage *)((caddr_t)sas + sizeof(*sin)); - actual += sizeof(*sin); + sas = (struct sockaddr_storage *)((caddr_t)sas + sizeof(struct sockaddr_in)); + actual += sizeof(struct sockaddr_in); #ifdef INET6 } #endif - if (actual >= limit) { - return (actual); - } } else { continue; } @@ -1184,13 +1186,13 @@ sctp_fill_up_addresses_vrf(struct sctp_inpcb *inp, (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))) { continue; } - memcpy(sas, sin6, sizeof(*sin6)); - ((struct sockaddr_in6 *)sas)->sin6_port = inp->sctp_lport; - sas = (struct sockaddr_storage *)((caddr_t)sas + sizeof(*sin6)); - actual += sizeof(*sin6); - if (actual >= limit) { + if (actual + sizeof(struct sockaddr_in6) > limit) { return (actual); } + memcpy(sas, sin6, sizeof(struct sockaddr_in6)); + ((struct sockaddr_in6 *)sas)->sin6_port = inp->sctp_lport; + sas = (struct sockaddr_storage *)((caddr_t)sas + sizeof(struct sockaddr_in6)); + actual += sizeof(struct sockaddr_in6); } else { continue; } @@ -1204,6 +1206,7 @@ sctp_fill_up_addresses_vrf(struct sctp_inpcb *inp, } } else { struct sctp_laddr *laddr; + size_t sa_len; LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) { if (stcb) { @@ -1211,6 +1214,10 @@ sctp_fill_up_addresses_vrf(struct sctp_inpcb *inp, continue; } } + sa_len = laddr->ifa->address.sa.sa_len; + if (actual + sa_len > limit) { + return (actual); + } if (sctp_fill_user_address(sas, &laddr->ifa->address.sa)) continue; switch (laddr->ifa->address.sa.sa_family) { @@ -1228,12 +1235,8 @@ sctp_fill_up_addresses_vrf(struct sctp_inpcb *inp, /* TSNH */ break; } - sas = (struct sockaddr_storage *)((caddr_t)sas + - laddr->ifa->address.sa.sa_len); - actual += laddr->ifa->address.sa.sa_len; - if (actual >= limit) { - return (actual); - } + sas = (struct sockaddr_storage *)((caddr_t)sas + sa_len); + actual += sa_len; } } return (actual); @@ -1351,13 +1354,12 @@ static int sctp_do_connect_x(struct socket *so, struct sctp_inpcb *inp, void *optval, size_t optsize, void *p, int delay) { - int error = 0; + int error; int creat_lock_on = 0; struct sctp_tcb *stcb = NULL; struct sockaddr *sa; unsigned int num_v6 = 0, num_v4 = 0, *totaddrp, totaddr; uint32_t vrf_id; - int bad_addresses = 0; sctp_assoc_t *a_id; SCTPDBG(SCTP_DEBUG_PCB1, "Connectx called\n"); @@ -1396,17 +1398,12 @@ sctp_do_connect_x(struct socket *so, struct sctp_inpcb *inp, void *optval, totaddrp = (unsigned int *)optval; totaddr = *totaddrp; sa = (struct sockaddr *)(totaddrp + 1); - stcb = sctp_connectx_helper_find(inp, sa, &totaddr, &num_v4, &num_v6, &error, (unsigned int)(optsize - sizeof(int)), &bad_addresses); - if ((stcb != NULL) || bad_addresses) { + error = sctp_connectx_helper_find(inp, sa, totaddr, &num_v4, &num_v6, (unsigned int)(optsize - sizeof(int))); + if (error != 0) { /* Already have or am bring up an association */ SCTP_ASOC_CREATE_UNLOCK(inp); creat_lock_on = 0; - if (stcb) - SCTP_TCB_UNLOCK(stcb); - if (bad_addresses == 0) { - SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY); - error = EALREADY; - } + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error); goto out_now; } #ifdef INET6 @@ -1480,8 +1477,6 @@ sctp_do_connect_x(struct socket *so, struct sctp_inpcb *inp, void *optval, sctp_connectx_helper_add(stcb, sa, (totaddr - 1), &error); /* Fill in the return id */ if (error) { - (void)sctp_free_assoc(inp, stcb, SCTP_PCBFREE_FORCE, - SCTP_FROM_SCTP_USRREQ + SCTP_LOC_7); goto out_now; } a_id = (sctp_assoc_t *)optval; @@ -2238,8 +2233,8 @@ flags_out: SCTP_FIND_STCB(inp, stcb, saddr->sget_assoc_id); if (stcb) { - left = (*optsize) - sizeof(struct sctp_getaddresses); - *optsize = sizeof(struct sctp_getaddresses); + left = (*optsize) - sizeof(sctp_assoc_t); + *optsize = sizeof(sctp_assoc_t); sas = (struct sockaddr_storage *)&saddr->addr[0]; TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { @@ -2313,7 +2308,7 @@ flags_out: if (stcb) { SCTP_TCB_UNLOCK(stcb); } - *optsize = sizeof(struct sockaddr_storage) + actual; + *optsize = sizeof(sctp_assoc_t) + actual; break; } case SCTP_PEER_ADDR_PARAMS: @@ -2642,42 +2637,47 @@ flags_out: sstat->sstat_instrms = stcb->asoc.streamincnt; sstat->sstat_outstrms = stcb->asoc.streamoutcnt; sstat->sstat_fragmentation_point = sctp_get_frag_point(stcb, &stcb->asoc); - memcpy(&sstat->sstat_primary.spinfo_address, - &stcb->asoc.primary_destination->ro._l_addr, - ((struct sockaddr *)(&stcb->asoc.primary_destination->ro._l_addr))->sa_len); net = stcb->asoc.primary_destination; - ((struct sockaddr_in *)&sstat->sstat_primary.spinfo_address)->sin_port = stcb->rport; - /* - * Again the user can get info from sctp_constants.h - * for what the state of the network is. - */ - if (net->dest_state & SCTP_ADDR_UNCONFIRMED) { - /* It's unconfirmed */ - sstat->sstat_primary.spinfo_state = SCTP_UNCONFIRMED; - } else if (net->dest_state & SCTP_ADDR_REACHABLE) { - /* It's active */ - sstat->sstat_primary.spinfo_state = SCTP_ACTIVE; - } else { - /* It's inactive */ - sstat->sstat_primary.spinfo_state = SCTP_INACTIVE; - } - sstat->sstat_primary.spinfo_cwnd = net->cwnd; - sstat->sstat_primary.spinfo_srtt = net->lastsa >> SCTP_RTT_SHIFT; - sstat->sstat_primary.spinfo_rto = net->RTO; - sstat->sstat_primary.spinfo_mtu = net->mtu; - switch (stcb->asoc.primary_destination->ro._l_addr.sa.sa_family) { + if (net != NULL) { + memcpy(&sstat->sstat_primary.spinfo_address, + &stcb->asoc.primary_destination->ro._l_addr, + ((struct sockaddr *)(&stcb->asoc.primary_destination->ro._l_addr))->sa_len); + ((struct sockaddr_in *)&sstat->sstat_primary.spinfo_address)->sin_port = stcb->rport; + /* + * Again the user can get info from + * sctp_constants.h for what the state of + * the network is. + */ + if (net->dest_state & SCTP_ADDR_UNCONFIRMED) { + /* It's unconfirmed */ + sstat->sstat_primary.spinfo_state = SCTP_UNCONFIRMED; + } else if (net->dest_state & SCTP_ADDR_REACHABLE) { + /* It's active */ + sstat->sstat_primary.spinfo_state = SCTP_ACTIVE; + } else { + /* It's inactive */ + sstat->sstat_primary.spinfo_state = SCTP_INACTIVE; + } + sstat->sstat_primary.spinfo_cwnd = net->cwnd; + sstat->sstat_primary.spinfo_srtt = net->lastsa >> SCTP_RTT_SHIFT; + sstat->sstat_primary.spinfo_rto = net->RTO; + sstat->sstat_primary.spinfo_mtu = net->mtu; + switch (stcb->asoc.primary_destination->ro._l_addr.sa.sa_family) { #if defined(INET) - case AF_INET: - sstat->sstat_primary.spinfo_mtu -= SCTP_MIN_V4_OVERHEAD; - break; + case AF_INET: + sstat->sstat_primary.spinfo_mtu -= SCTP_MIN_V4_OVERHEAD; + break; #endif #if defined(INET6) - case AF_INET6: - sstat->sstat_primary.spinfo_mtu -= SCTP_MIN_OVERHEAD; - break; + case AF_INET6: + sstat->sstat_primary.spinfo_mtu -= SCTP_MIN_OVERHEAD; + break; #endif - default: - break; + default: + break; + } + } else { + memset(&sstat->sstat_primary, 0, sizeof(struct sctp_paddrinfo)); } sstat->sstat_primary.spinfo_assoc_id = sctp_get_associd(stcb); SCTP_TCB_UNLOCK(stcb); @@ -3744,13 +3744,11 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, uint32_t vrf_id; if (optval == NULL) { - SCTP_PRINTF("optval is NULL\n"); SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); return (EINVAL); } inp = (struct sctp_inpcb *)so->so_pcb; if (inp == NULL) { - SCTP_PRINTF("inp is NULL?\n"); SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); return (EINVAL); } @@ -4065,10 +4063,12 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, } SCTP_FIND_STCB(inp, stcb, av->assoc_id); if (stcb) { + SCTP_TCB_SEND_LOCK(stcb); stcb->asoc.ss_functions.sctp_ss_clear(stcb, &stcb->asoc, 1, 1); stcb->asoc.ss_functions = sctp_ss_functions[av->assoc_value]; stcb->asoc.stream_scheduling_module = av->assoc_value; stcb->asoc.ss_functions.sctp_ss_init(stcb, &stcb->asoc, 1); + SCTP_TCB_SEND_UNLOCK(stcb); SCTP_TCB_UNLOCK(stcb); } else { if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || @@ -4084,10 +4084,12 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, SCTP_INP_RLOCK(inp); LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) { SCTP_TCB_LOCK(stcb); + SCTP_TCB_SEND_LOCK(stcb); stcb->asoc.ss_functions.sctp_ss_clear(stcb, &stcb->asoc, 1, 1); stcb->asoc.ss_functions = sctp_ss_functions[av->assoc_value]; stcb->asoc.stream_scheduling_module = av->assoc_value; stcb->asoc.ss_functions.sctp_ss_init(stcb, &stcb->asoc, 1); + SCTP_TCB_SEND_UNLOCK(stcb); SCTP_TCB_UNLOCK(stcb); } SCTP_INP_RUNLOCK(inp); @@ -4624,6 +4626,12 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, SCTP_TCB_UNLOCK(stcb); break; } + if (SCTP_GET_STATE(stcb) != SCTP_STATE_OPEN) { + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); + error = EINVAL; + SCTP_TCB_UNLOCK(stcb); + break; + } if (sizeof(struct sctp_reset_streams) + strrst->srs_number_streams * sizeof(uint16_t) > optsize) { error = EINVAL; @@ -4656,13 +4664,13 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, } for (i = 0; i < strrst->srs_number_streams; i++) { if ((send_in) && - (strrst->srs_stream_list[i] > stcb->asoc.streamincnt)) { + (strrst->srs_stream_list[i] >= stcb->asoc.streamincnt)) { SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); error = EINVAL; break; } if ((send_out) && - (strrst->srs_stream_list[i] > stcb->asoc.streamoutcnt)) { + (strrst->srs_stream_list[i] >= stcb->asoc.streamoutcnt)) { SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); error = EINVAL; break; @@ -4738,6 +4746,12 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, SCTP_TCB_UNLOCK(stcb); break; } + if (SCTP_GET_STATE(stcb) != SCTP_STATE_OPEN) { + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); + error = EINVAL; + SCTP_TCB_UNLOCK(stcb); + break; + } if (stcb->asoc.stream_reset_outstanding) { SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY); error = EALREADY; @@ -4808,6 +4822,12 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, SCTP_TCB_UNLOCK(stcb); break; } + if (SCTP_GET_STATE(stcb) != SCTP_STATE_OPEN) { + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); + error = EINVAL; + SCTP_TCB_UNLOCK(stcb); + break; + } if (stcb->asoc.stream_reset_outstanding) { SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY); error = EALREADY; @@ -5314,10 +5334,11 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, net->dest_state &= ~SCTP_ADDR_NOHB; } if (paddrp->spp_flags & SPP_HB_DEMAND) { - /* on demand HB */ - sctp_send_hb(stcb, net, SCTP_SO_LOCKED); - sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_SOCKOPT, SCTP_SO_LOCKED); - sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net); + if (SCTP_GET_STATE(stcb) == SCTP_STATE_OPEN) { + sctp_send_hb(stcb, net, SCTP_SO_LOCKED); + sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_SOCKOPT, SCTP_SO_LOCKED); + sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net); + } } if ((paddrp->spp_flags & SPP_PMTUD_DISABLE) && (paddrp->spp_pathmtu >= SCTP_SMALLEST_PMTU)) { if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) { @@ -6117,6 +6138,10 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, SCTP_INP_RUNLOCK(inp); } } + } else { + if (stcb) { + SCTP_TCB_UNLOCK(stcb); + } } break; } @@ -6211,6 +6236,9 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, SCTP_FIND_STCB(inp, stcb, info->pr_assoc_id); if (info->pr_policy > SCTP_PR_SCTP_MAX) { + if (stcb) { + SCTP_TCB_UNLOCK(stcb); + } SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); error = EINVAL; break; @@ -6330,6 +6358,9 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, } } if (thlds->spt_pathcpthld != 0xffff) { + if (stcb != NULL) { + SCTP_TCB_UNLOCK(stcb); + } error = EINVAL; SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error); break; diff --git a/freebsd/sys/netinet/sctputil.c b/freebsd/sys/netinet/sctputil.c index ddf136ef..ba7a43a0 100644 --- a/freebsd/sys/netinet/sctputil.c +++ b/freebsd/sys/netinet/sctputil.c @@ -548,7 +548,7 @@ sctp_wakeup_log(struct sctp_tcb *stcb, uint32_t wake_cnt, int from) } void -sctp_log_block(uint8_t from, struct sctp_association *asoc, size_t sendlen) +sctp_log_block(uint8_t from, struct sctp_association *asoc, ssize_t sendlen) { #if defined(SCTP_LOCAL_TRACE_BUF) struct sctp_cwnd_log sctp_clog; @@ -3948,7 +3948,7 @@ sctp_report_all_outbound(struct sctp_tcb *stcb, uint16_t error, int holds_lock, TAILQ_FOREACH_SAFE(sp, &outs->outqueue, next, nsp) { atomic_subtract_int(&asoc->stream_queue_cnt, 1); TAILQ_REMOVE(&outs->outqueue, sp, next); - stcb->asoc.ss_functions.sctp_ss_remove_from_stream(stcb, asoc, outs, sp, holds_lock); + stcb->asoc.ss_functions.sctp_ss_remove_from_stream(stcb, asoc, outs, sp, 1); sctp_free_spbufspace(stcb, asoc, sp); if (sp->data) { sctp_ulp_notify(SCTP_NOTIFY_SPECIAL_SP_FAIL, stcb, @@ -3997,7 +3997,7 @@ sctp_abort_notification(struct sctp_tcb *stcb, uint8_t from_peer, uint16_t error return; } /* Tell them we lost the asoc */ - sctp_report_all_outbound(stcb, error, 1, so_locked); + sctp_report_all_outbound(stcb, error, 0, so_locked); if (from_peer) { sctp_ulp_notify(SCTP_NOTIFY_ASSOC_REM_ABORTED, stcb, error, abort, so_locked); } else { @@ -5221,8 +5221,9 @@ sctp_sorecvmsg(struct socket *so, * */ struct sctp_inpcb *inp = NULL; - int my_len = 0; - int cp_len = 0, error = 0; + ssize_t my_len = 0; + ssize_t cp_len = 0; + int error = 0; struct sctp_queued_to_read *control = NULL, *ctl = NULL, *nxt = NULL; struct mbuf *m = NULL; struct sctp_tcb *stcb = NULL; @@ -5231,7 +5232,7 @@ sctp_sorecvmsg(struct socket *so, int out_flags = 0, in_flags = 0; int block_allowed = 1; uint32_t freed_so_far = 0; - uint32_t copied_so_far = 0; + ssize_t copied_so_far = 0; int in_eeor_mode = 0; int no_rcv_needed = 0; uint32_t rwnd_req = 0; @@ -5575,7 +5576,7 @@ found_one: * will go to the sctp_user_rcvd() that will not * lock until it KNOWs it MUST send a WUP-SACK. */ - freed_so_far = stcb->freed_by_sorcv_sincelast; + freed_so_far = (uint32_t)stcb->freed_by_sorcv_sincelast; stcb->freed_by_sorcv_sincelast = 0; } } @@ -5730,8 +5731,8 @@ get_more_data: m = control->data; while (m) { /* Move out all we can */ - cp_len = (int)uio->uio_resid; - my_len = (int)SCTP_BUF_LEN(m); + cp_len = uio->uio_resid; + my_len = SCTP_BUF_LEN(m); if (cp_len > my_len) { /* not enough in this buf */ cp_len = my_len; @@ -5741,7 +5742,7 @@ get_more_data: hold_rlock = 0; } if (cp_len > 0) - error = uiomove(mtod(m, char *), cp_len, uio); + error = uiomove(mtod(m, char *), (int)cp_len, uio); /* re-read */ if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { goto release; @@ -5786,7 +5787,7 @@ get_more_data: control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBRESULT, 0); } copied_so_far += cp_len; - freed_so_far += cp_len; + freed_so_far += (uint32_t)cp_len; freed_so_far += MSIZE; atomic_subtract_int(&control->length, cp_len); control->data = sctp_m_free(m); @@ -5826,9 +5827,9 @@ get_more_data: } if ((in_flags & MSG_PEEK) == 0) { SCTP_BUF_RESV_UF(m, cp_len); - SCTP_BUF_LEN(m) -= cp_len; + SCTP_BUF_LEN(m) -= (int)cp_len; if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) { - sctp_sblog(&so->so_rcv, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBFREE, cp_len); + sctp_sblog(&so->so_rcv, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBFREE, (int)cp_len); } atomic_subtract_int(&so->so_rcv.sb_cc, cp_len); if ((control->do_not_ref_stcb == 0) && @@ -5836,7 +5837,7 @@ get_more_data: atomic_subtract_int(&stcb->asoc.sb_cc, cp_len); } copied_so_far += cp_len; - freed_so_far += cp_len; + freed_so_far += (uint32_t)cp_len; freed_so_far += MSIZE; if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) { sctp_sblog(&so->so_rcv, control->do_not_ref_stcb ? NULL : stcb, @@ -6064,7 +6065,7 @@ wait_some_more: control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBFREE, SCTP_BUF_LEN(m)); } sctp_sbfree(control, stcb, &so->so_rcv, m); - freed_so_far += SCTP_BUF_LEN(m); + freed_so_far += (uint32_t)SCTP_BUF_LEN(m); freed_so_far += MSIZE; if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) { sctp_sblog(&so->so_rcv, @@ -6392,30 +6393,33 @@ out_now: return (added); } -struct sctp_tcb * +int sctp_connectx_helper_find(struct sctp_inpcb *inp, struct sockaddr *addr, - unsigned int *totaddr, - unsigned int *num_v4, unsigned int *num_v6, int *error, - unsigned int limit, int *bad_addr) + unsigned int totaddr, + unsigned int *num_v4, unsigned int *num_v6, + unsigned int limit) { struct sockaddr *sa; - struct sctp_tcb *stcb = NULL; + struct sctp_tcb *stcb; unsigned int incr, at, i; at = 0; sa = addr; - *error = *num_v6 = *num_v4 = 0; + *num_v6 = *num_v4 = 0; /* account and validate addresses */ - for (i = 0; i < *totaddr; i++) { + if (totaddr == 0) { + return (EINVAL); + } + for (i = 0; i < totaddr; i++) { + if (at + sizeof(struct sockaddr) > limit) { + return (EINVAL); + } switch (sa->sa_family) { #ifdef INET case AF_INET: incr = (unsigned int)sizeof(struct sockaddr_in); if (sa->sa_len != incr) { - SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); - *error = EINVAL; - *bad_addr = 1; - return (NULL); + return (EINVAL); } (*num_v4) += 1; break; @@ -6428,46 +6432,34 @@ sctp_connectx_helper_find(struct sctp_inpcb *inp, struct sockaddr *addr, sin6 = (struct sockaddr_in6 *)sa; if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { /* Must be non-mapped for connectx */ - SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); - *error = EINVAL; - *bad_addr = 1; - return (NULL); + return (EINVAL); } incr = (unsigned int)sizeof(struct sockaddr_in6); if (sa->sa_len != incr) { - SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); - *error = EINVAL; - *bad_addr = 1; - return (NULL); + return (EINVAL); } (*num_v6) += 1; break; } #endif default: - *totaddr = i; - incr = 0; - /* we are done */ - break; + return (EINVAL); } - if (i == *totaddr) { - break; + if ((at + incr) > limit) { + return (EINVAL); } SCTP_INP_INCR_REF(inp); stcb = sctp_findassociation_ep_addr(&inp, sa, NULL, NULL, NULL); if (stcb != NULL) { - /* Already have or am bring up an association */ - return (stcb); + SCTP_TCB_UNLOCK(stcb); + return (EALREADY); } else { SCTP_INP_DECR_REF(inp); } - if ((at + incr) > limit) { - *totaddr = i; - break; - } + at += incr; sa = (struct sockaddr *)((caddr_t)sa + incr); } - return ((struct sctp_tcb *)NULL); + return (0); } /* diff --git a/freebsd/sys/netinet/sctputil.h b/freebsd/sys/netinet/sctputil.h index c12fb210..690e6125 100644 --- a/freebsd/sys/netinet/sctputil.h +++ b/freebsd/sys/netinet/sctputil.h @@ -211,10 +211,9 @@ int sctp_connectx_helper_add(struct sctp_tcb *stcb, struct sockaddr *addr, int totaddr, int *error); -struct sctp_tcb * -sctp_connectx_helper_find(struct sctp_inpcb *inp, struct sockaddr *addr, - unsigned int *totaddr, unsigned int *num_v4, unsigned int *num_v6, - int *error, unsigned int limit, int *bad_addr); +int +sctp_connectx_helper_find(struct sctp_inpcb *, struct sockaddr *, + unsigned int, unsigned int *, unsigned int *, unsigned int); int sctp_is_there_an_abort_here(struct mbuf *, int, uint32_t *); #ifdef INET6 @@ -367,7 +366,7 @@ void sctp_log_closing(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int16_t loc void sctp_log_lock(struct sctp_inpcb *inp, struct sctp_tcb *stcb, uint8_t from); void sctp_log_maxburst(struct sctp_tcb *stcb, struct sctp_nets *, int, int, uint8_t); -void sctp_log_block(uint8_t, struct sctp_association *, size_t); +void sctp_log_block(uint8_t, struct sctp_association *, ssize_t); void sctp_log_rwnd(uint8_t, uint32_t, uint32_t, uint32_t); void sctp_log_rwnd_set(uint8_t, uint32_t, uint32_t, uint32_t, uint32_t); int sctp_fill_stat_log(void *, size_t *); diff --git a/freebsd/sys/netinet/tcp_input.c b/freebsd/sys/netinet/tcp_input.c index d00504dc..77d6fc3b 100644 --- a/freebsd/sys/netinet/tcp_input.c +++ b/freebsd/sys/netinet/tcp_input.c @@ -2029,7 +2029,8 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so, else tp->t_flags |= TF_ACKNOW; - if ((thflags & TH_ECE) && V_tcp_do_ecn) { + if (((thflags & (TH_CWR | TH_ECE)) == TH_ECE) && + V_tcp_do_ecn) { tp->t_flags |= TF_ECN_PERMIT; TCPSTAT_INC(tcps_ecn_shs); } @@ -2279,6 +2280,17 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so, TCPSTAT_INC(tcps_rcvpartduppack); TCPSTAT_ADD(tcps_rcvpartdupbyte, todrop); } + /* + * DSACK - add SACK block for dropped range + */ + if (tp->t_flags & TF_SACK_PERMIT) { + tcp_update_sack_list(tp, th->th_seq, th->th_seq+tlen); + /* + * ACK now, as the next in-sequence segment + * will clear the DSACK block again + */ + tp->t_flags |= TF_ACKNOW; + } drop_hdrlen += todrop; /* drop from the top afterwards */ th->th_seq += todrop; tlen -= todrop; @@ -2403,8 +2415,8 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so, if ((tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) == (TF_RCVD_SCALE|TF_REQ_SCALE)) { tp->rcv_scale = tp->request_r_scale; - tp->snd_wnd = tiwin; } + tp->snd_wnd = tiwin; /* * Make transitions: * SYN-RECEIVED -> ESTABLISHED @@ -3007,6 +3019,8 @@ dodata: /* XXX */ if ((tlen || (thflags & TH_FIN) || tfo_syn) && TCPS_HAVERCVDFIN(tp->t_state) == 0) { tcp_seq save_start = th->th_seq; + tcp_seq save_rnxt = tp->rcv_nxt; + int save_tlen = tlen; m_adj(m, drop_hdrlen); /* delayed header drop */ /* * Insert segment which includes th into TCP reassembly queue @@ -3046,11 +3060,34 @@ dodata: /* XXX */ * m_adj() doesn't actually frees any mbufs * when trimming from the head. */ - thflags = tcp_reass(tp, th, &save_start, &tlen, m); + tcp_seq temp = save_start; + thflags = tcp_reass(tp, th, &temp, &tlen, m); tp->t_flags |= TF_ACKNOW; } - if (tlen > 0 && (tp->t_flags & TF_SACK_PERMIT)) - tcp_update_sack_list(tp, save_start, save_start + tlen); + if (tp->t_flags & TF_SACK_PERMIT) { + if (((tlen == 0) && (save_tlen > 0) && + (SEQ_LT(save_start, save_rnxt)))) { + /* + * DSACK actually handled in the fastpath + * above. + */ + tcp_update_sack_list(tp, save_start, save_start + save_tlen); + } else + if ((tlen > 0) && SEQ_GT(tp->rcv_nxt, save_rnxt)) { + /* + * Cleaning sackblks by using zero length + * update. + */ + tcp_update_sack_list(tp, save_start, save_start); + } else + if ((tlen > 0) && (tlen >= save_tlen)) { + /* Update of sackblks. */ + tcp_update_sack_list(tp, save_start, save_start + save_tlen); + } else + if (tlen > 0) { + tcp_update_sack_list(tp, save_start, save_start+tlen); + } + } #if 0 /* * Note the amount of data that peer has sent into diff --git a/freebsd/sys/netinet/tcp_output.c b/freebsd/sys/netinet/tcp_output.c index 200ae8ad..3d0a78d0 100644 --- a/freebsd/sys/netinet/tcp_output.c +++ b/freebsd/sys/netinet/tcp_output.c @@ -1285,15 +1285,9 @@ send: m->m_pkthdr.tso_segsz = tp->t_maxseg - optlen; } -#if defined(IPSEC) || defined(IPSEC_SUPPORT) - KASSERT(len + hdrlen + ipoptlen - ipsec_optlen == m_length(m, NULL), - ("%s: mbuf chain shorter than expected: %d + %u + %u - %u != %u", - __func__, len, hdrlen, ipoptlen, ipsec_optlen, m_length(m, NULL))); -#else - KASSERT(len + hdrlen + ipoptlen == m_length(m, NULL), - ("%s: mbuf chain shorter than expected: %d + %u + %u != %u", - __func__, len, hdrlen, ipoptlen, m_length(m, NULL))); -#endif + KASSERT(len + hdrlen == m_length(m, NULL), + ("%s: mbuf chain shorter than expected: %d + %u != %u", + __func__, len, hdrlen, m_length(m, NULL))); #ifdef TCP_HHOOK /* Run HHOOK_TCP_ESTABLISHED_OUT helper hooks. */ diff --git a/freebsd/sys/netinet/tcp_sack.c b/freebsd/sys/netinet/tcp_sack.c index 91c032c8..0f536f6c 100644 --- a/freebsd/sys/netinet/tcp_sack.c +++ b/freebsd/sys/netinet/tcp_sack.c @@ -170,7 +170,7 @@ tcp_update_sack_list(struct tcpcb *tp, tcp_seq rcv_start, tcp_seq rcv_end) INP_WLOCK_ASSERT(tp->t_inpcb); /* Check arguments. */ - KASSERT(SEQ_LT(rcv_start, rcv_end), ("rcv_start < rcv_end")); + KASSERT(SEQ_LEQ(rcv_start, rcv_end), ("rcv_start <= rcv_end")); /* SACK block for the received segment. */ head_blk.start = rcv_start; @@ -195,12 +195,54 @@ tcp_update_sack_list(struct tcpcb *tp, tcp_seq rcv_start, tcp_seq rcv_end) * Merge this SACK block into head_blk. This SACK * block itself will be discarded. */ - if (SEQ_GT(head_blk.start, start)) + /* + * |-| + * |---| merge + * + * |-| + * |---| merge + * + * |-----| + * |-| DSACK smaller + * + * |-| + * |-----| DSACK smaller + */ + if (head_blk.start == end) head_blk.start = start; - if (SEQ_LT(head_blk.end, end)) + else if (head_blk.end == start) head_blk.end = end; + else { + if (SEQ_LT(head_blk.start, start)) { + tcp_seq temp = start; + start = head_blk.start; + head_blk.start = temp; + } + if (SEQ_GT(head_blk.end, end)) { + tcp_seq temp = end; + end = head_blk.end; + head_blk.end = temp; + } + if ((head_blk.start != start) || + (head_blk.end != end)) { + if ((num_saved >= 1) && + SEQ_GEQ(saved_blks[num_saved-1].start, start) && + SEQ_LEQ(saved_blks[num_saved-1].end, end)) + num_saved--; + saved_blks[num_saved].start = start; + saved_blks[num_saved].end = end; + num_saved++; + } + } } else { /* + * This block supercedes the prior block + */ + if ((num_saved >= 1) && + SEQ_GEQ(saved_blks[num_saved-1].start, start) && + SEQ_LEQ(saved_blks[num_saved-1].end, end)) + num_saved--; + /* * Save this SACK block. */ saved_blks[num_saved].start = start; @@ -213,7 +255,7 @@ tcp_update_sack_list(struct tcpcb *tp, tcp_seq rcv_start, tcp_seq rcv_end) * Update SACK list in tp->sackblks[]. */ num_head = 0; - if (SEQ_GT(head_blk.start, tp->rcv_nxt)) { + if (SEQ_LT(rcv_start, rcv_end)) { /* * The received data segment is an out-of-order segment. Put * head_blk at the top of SACK list. diff --git a/freebsd/sys/netinet/tcp_subr.c b/freebsd/sys/netinet/tcp_subr.c index 52d2ca2a..db2b2661 100644 --- a/freebsd/sys/netinet/tcp_subr.c +++ b/freebsd/sys/netinet/tcp_subr.c @@ -1088,6 +1088,9 @@ tcp_init(void) tcp_keepintvl = TCPTV_KEEPINTVL; tcp_maxpersistidle = TCPTV_KEEP_IDLE; tcp_msl = TCPTV_MSL; + tcp_rexmit_initial = TCPTV_RTOBASE; + if (tcp_rexmit_initial < 1) + tcp_rexmit_initial = 1; tcp_rexmit_min = TCPTV_MIN; if (tcp_rexmit_min < 1) tcp_rexmit_min = 1; @@ -1666,9 +1669,9 @@ tcp_newtcpcb(struct inpcb *inp) * reasonable initial retransmit time. */ tp->t_srtt = TCPTV_SRTTBASE; - tp->t_rttvar = ((TCPTV_RTOBASE - TCPTV_SRTTBASE) << TCP_RTTVAR_SHIFT) / 4; + tp->t_rttvar = ((tcp_rexmit_initial - TCPTV_SRTTBASE) << TCP_RTTVAR_SHIFT) / 4; tp->t_rttmin = tcp_rexmit_min; - tp->t_rxtcur = TCPTV_RTOBASE; + tp->t_rxtcur = tcp_rexmit_initial; tp->snd_cwnd = TCP_MAXWIN << TCP_MAX_WINSHIFT; tp->snd_ssthresh = TCP_MAXWIN << TCP_MAX_WINSHIFT; tp->t_rcvtime = ticks; diff --git a/freebsd/sys/netinet/tcp_syncache.c b/freebsd/sys/netinet/tcp_syncache.c index bfbf9f42..ffdab808 100644 --- a/freebsd/sys/netinet/tcp_syncache.c +++ b/freebsd/sys/netinet/tcp_syncache.c @@ -156,7 +156,12 @@ static int syncookie_cmp(struct in_conninfo *inc, struct syncache_head *sch, /* * Transmit the SYN,ACK fewer times than TCP_MAXRXTSHIFT specifies. - * 3 retransmits corresponds to a timeout of 3 * (1 + 2 + 4 + 8) == 45 seconds, + * 3 retransmits corresponds to a timeout with default values of + * tcp_rexmit_initial * ( 1 + + * tcp_backoff[1] + + * tcp_backoff[2] + + * tcp_backoff[3]) + 3 * tcp_rexmit_slop, + * 1000 ms * (1 + 2 + 4 + 8) + 3 * 200 ms = 15600 ms, * the odds are that the user has given up attempting to connect by then. */ #define SYNCACHE_MAXREXMTS 3 @@ -421,9 +426,10 @@ syncache_timeout(struct syncache *sc, struct syncache_head *sch, int docallout) int rexmt; if (sc->sc_rxmits == 0) - rexmt = TCPTV_RTOBASE; + rexmt = tcp_rexmit_initial; else - TCPT_RANGESET(rexmt, TCPTV_RTOBASE * tcp_syn_backoff[sc->sc_rxmits], + TCPT_RANGESET(rexmt, + tcp_rexmit_initial * tcp_backoff[sc->sc_rxmits], tcp_rexmit_min, TCPTV_REXMTMAX); sc->sc_rxttime = ticks + rexmt; sc->sc_rxmits++; @@ -1143,6 +1149,28 @@ syncache_expand(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th, } } #endif /* TCP_SIGNATURE */ + + /* + * RFC 7323 PAWS: If we have a timestamp on this segment and + * it's less than ts_recent, drop it. + * XXXMT: RFC 7323 also requires to send an ACK. + * In tcp_input.c this is only done for TCP segments + * with user data, so be consistent here and just drop + * the segment. + */ + if (sc->sc_flags & SCF_TIMESTAMP && to->to_flags & TOF_TS && + TSTMP_LT(to->to_tsval, sc->sc_tsreflect)) { + SCH_UNLOCK(sch); + if ((s = tcp_log_addrs(inc, th, NULL, NULL))) { + log(LOG_DEBUG, + "%s; %s: SEG.TSval %u < TS.Recent %u, " + "segment dropped\n", s, __func__, + to->to_tsval, sc->sc_tsreflect); + free(s, M_TCPLOG); + } + return (-1); /* Do not send RST */ + } + /* * Pull out the entry to unlock the bucket row. * diff --git a/freebsd/sys/netinet/tcp_timer.c b/freebsd/sys/netinet/tcp_timer.c index c50af2bb..cf6ceff5 100644 --- a/freebsd/sys/netinet/tcp_timer.c +++ b/freebsd/sys/netinet/tcp_timer.c @@ -112,6 +112,11 @@ int tcp_msl; SYSCTL_PROC(_net_inet_tcp, OID_AUTO, msl, CTLTYPE_INT|CTLFLAG_RW, &tcp_msl, 0, sysctl_msec_to_ticks, "I", "Maximum segment lifetime"); +int tcp_rexmit_initial; +SYSCTL_PROC(_net_inet_tcp, OID_AUTO, rexmit_initial, CTLTYPE_INT|CTLFLAG_RW, + &tcp_rexmit_initial, 0, sysctl_msec_to_ticks, "I", + "Initial Retransmission Timeout"); + int tcp_rexmit_min; SYSCTL_PROC(_net_inet_tcp, OID_AUTO, rexmit_min, CTLTYPE_INT|CTLFLAG_RW, &tcp_rexmit_min, 0, sysctl_msec_to_ticks, "I", @@ -235,9 +240,6 @@ tcp_slowtimo(void) VNET_LIST_RUNLOCK_NOSLEEP(); } -int tcp_syn_backoff[TCP_MAXRXTSHIFT + 1] = - { 1, 1, 1, 1, 1, 2, 4, 8, 16, 32, 64, 64, 64 }; - int tcp_backoff[TCP_MAXRXTSHIFT + 1] = { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 512, 512, 512 }; @@ -673,7 +675,7 @@ tcp_timer_rexmt(void * xtp) TCPSTAT_INC(tcps_rexmttimeo); if ((tp->t_state == TCPS_SYN_SENT) || (tp->t_state == TCPS_SYN_RECEIVED)) - rexmt = TCPTV_RTOBASE * tcp_syn_backoff[tp->t_rxtshift]; + rexmt = tcp_rexmit_initial * tcp_backoff[tp->t_rxtshift]; else rexmt = TCP_REXMTVAL(tp) * tcp_backoff[tp->t_rxtshift]; TCPT_RANGESET(tp->t_rxtcur, rexmt, diff --git a/freebsd/sys/netinet/tcp_timer.h b/freebsd/sys/netinet/tcp_timer.h index a2ab6ca5..3e985bdf 100644 --- a/freebsd/sys/netinet/tcp_timer.h +++ b/freebsd/sys/netinet/tcp_timer.h @@ -77,7 +77,7 @@ #define TCPTV_MSL ( 30*hz) /* max seg lifetime (hah!) */ #define TCPTV_SRTTBASE 0 /* base roundtrip time; if 0, no idea yet */ -#define TCPTV_RTOBASE ( 3*hz) /* assumed RTO if no info */ +#define TCPTV_RTOBASE ( 1*hz) /* assumed RTO if no info */ #define TCPTV_PERSMIN ( 5*hz) /* minimum persist interval */ #define TCPTV_PERSMAX ( 60*hz) /* maximum persist interval */ @@ -194,12 +194,12 @@ extern int tcp_keepintvl; /* time between keepalive probes */ extern int tcp_keepcnt; /* number of keepalives */ extern int tcp_delacktime; /* time before sending a delayed ACK */ extern int tcp_maxpersistidle; +extern int tcp_rexmit_initial; extern int tcp_rexmit_min; extern int tcp_rexmit_slop; extern int tcp_msl; extern int tcp_ttl; /* time to live for TCP segs */ extern int tcp_backoff[]; -extern int tcp_syn_backoff[]; extern int tcp_totbackoff; extern int tcp_rexmit_drop_options; diff --git a/freebsd/sys/netinet/tcp_timewait.c b/freebsd/sys/netinet/tcp_timewait.c index 8a28283f..6965d391 100644 --- a/freebsd/sys/netinet/tcp_timewait.c +++ b/freebsd/sys/netinet/tcp_timewait.c @@ -304,7 +304,7 @@ tcp_twstart(struct tcpcb *tp) if (SEQ_GT(tp->rcv_adv, tp->rcv_nxt) && recwin < (tp->rcv_adv - tp->rcv_nxt)) recwin = (tp->rcv_adv - tp->rcv_nxt); - tw->last_win = htons((u_short)(recwin >> tp->rcv_scale)); + tw->last_win = (u_short)(recwin >> tp->rcv_scale); /* * Set t_recent if timestamps are used on the connection. diff --git a/freebsd/sys/netinet6/in6.c b/freebsd/sys/netinet6/in6.c index 1331d2e5..078efe45 100644 --- a/freebsd/sys/netinet6/in6.c +++ b/freebsd/sys/netinet6/in6.c @@ -1947,26 +1947,14 @@ in6_if_up(struct ifnet *ifp) int in6if_do_dad(struct ifnet *ifp) { + if ((ifp->if_flags & IFF_LOOPBACK) != 0) return (0); - - if ((ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) || - (ND_IFINFO(ifp)->flags & ND6_IFF_NO_DAD)) + if ((ifp->if_flags & IFF_MULTICAST) == 0) + return (0); + if ((ND_IFINFO(ifp)->flags & + (ND6_IFF_IFDISABLED | ND6_IFF_NO_DAD)) != 0) return (0); - - /* - * Our DAD routine requires the interface up and running. - * However, some interfaces can be up before the RUNNING - * status. Additionally, users may try to assign addresses - * before the interface becomes up (or running). - * This function returns EAGAIN in that case. - * The caller should mark "tentative" on the address instead of - * performing DAD immediately. - */ - if (!((ifp->if_flags & IFF_UP) && - (ifp->if_drv_flags & IFF_DRV_RUNNING))) - return (EAGAIN); - return (1); } diff --git a/freebsd/sys/netinet6/in6_ifattach.c b/freebsd/sys/netinet6/in6_ifattach.c index 5f1128d4..956b7290 100644 --- a/freebsd/sys/netinet6/in6_ifattach.c +++ b/freebsd/sys/netinet6/in6_ifattach.c @@ -333,6 +333,14 @@ found: IF_ADDR_RUNLOCK(ifp); return -1; + case IFT_INFINIBAND: + if (addrlen != 20) { + IF_ADDR_RUNLOCK(ifp); + return -1; + } + bcopy(addr + 12, &in6->s6_addr[8], 8); + break; + default: IF_ADDR_RUNLOCK(ifp); return -1; @@ -700,6 +708,7 @@ in6_ifattach(struct ifnet *ifp, struct ifnet *altifp) * it is rather harmful to have one. */ ND_IFINFO(ifp)->flags &= ~ND6_IFF_AUTO_LINKLOCAL; + ND_IFINFO(ifp)->flags |= ND6_IFF_NO_DAD; break; default: break; diff --git a/freebsd/sys/netinet6/in6_mcast.c b/freebsd/sys/netinet6/in6_mcast.c index ceeca992..e16de99d 100644 --- a/freebsd/sys/netinet6/in6_mcast.c +++ b/freebsd/sys/netinet6/in6_mcast.c @@ -2472,10 +2472,14 @@ in6p_leave_group(struct inpcb *inp, struct sockopt *sopt) if (is_final) { /* Remove the gap in the membership array. */ + KASSERT(RB_EMPTY(&imf->im6f_sources), + ("%s: im6f_sources not empty", __func__)); for (++idx; idx < imo->im6o_num_memberships; ++idx) { - imo->im6o_membership[idx-1] = imo->im6o_membership[idx]; - imo->im6o_mfilters[idx-1] = imo->im6o_mfilters[idx]; + imo->im6o_membership[idx - 1] = imo->im6o_membership[idx]; + imo->im6o_mfilters[idx - 1] = imo->im6o_mfilters[idx]; } + im6f_init(&imo->im6o_mfilters[idx - 1], MCAST_UNDEFINED, + MCAST_EXCLUDE); imo->im6o_num_memberships--; } diff --git a/freebsd/sys/netinet6/in6_src.c b/freebsd/sys/netinet6/in6_src.c index 1cb71b88..170eaf18 100644 --- a/freebsd/sys/netinet6/in6_src.c +++ b/freebsd/sys/netinet6/in6_src.c @@ -726,6 +726,10 @@ selectroute(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts, if (ron->ro_rt == NULL || (ron->ro_rt->rt_flags & RTF_GATEWAY) != 0) error = EHOSTUNREACH; + else { + rt = ron->ro_rt; + ifp = rt->rt_ifp; + } goto done; } diff --git a/freebsd/sys/netinet6/ip6_output.c b/freebsd/sys/netinet6/ip6_output.c index a0ce4027..eaae72a1 100644 --- a/freebsd/sys/netinet6/ip6_output.c +++ b/freebsd/sys/netinet6/ip6_output.c @@ -2218,8 +2218,11 @@ ip6_raw_ctloutput(struct socket *so, struct sockopt *sopt) sizeof(optval)); if (error) break; - if ((optval % 2) != 0) { - /* the API assumes even offset values */ + if (optval < -1 || (optval % 2) != 0) { + /* + * The API assumes non-negative even offset + * values or -1 as a special value. + */ error = EINVAL; } else if (so->so_proto->pr_protocol == IPPROTO_ICMPV6) { diff --git a/freebsd/sys/netinet6/mld6.c b/freebsd/sys/netinet6/mld6.c index 3b1d1afa..5b90f0a3 100644 --- a/freebsd/sys/netinet6/mld6.c +++ b/freebsd/sys/netinet6/mld6.c @@ -1706,6 +1706,8 @@ mld_v2_cancel_link_timers(struct mld_ifsoftc *mli) * version, we need to release the final * reference held for issuing the INCLUDE {}. */ + if (inm->in6m_refcount == 1) + in6m_disconnect_locked(&inmh, inm); in6m_rele_locked(&inmh, inm); /* FALLTHROUGH */ case MLD_G_QUERY_PENDING_MEMBER: diff --git a/freebsd/sys/netinet6/nd6.c b/freebsd/sys/netinet6/nd6.c index f065815c..140dde59 100644 --- a/freebsd/sys/netinet6/nd6.c +++ b/freebsd/sys/netinet6/nd6.c @@ -898,6 +898,7 @@ nd6_timer(void *arg) struct nd_prhead prl; struct nd_defrouter *dr, *ndr; struct nd_prefix *pr, *npr; + struct ifnet *ifp; struct in6_ifaddr *ia6, *nia6; uint64_t genid; @@ -994,14 +995,15 @@ nd6_timer(void *arg) * Check status of the interface. If it is down, * mark the address as tentative for future DAD. */ - if ((ia6->ia_ifp->if_flags & IFF_UP) == 0 || - (ia6->ia_ifp->if_drv_flags & IFF_DRV_RUNNING) - == 0 || - (ND_IFINFO(ia6->ia_ifp)->flags & - ND6_IFF_IFDISABLED) != 0) { + ifp = ia6->ia_ifp; + if ((ND_IFINFO(ifp)->flags & ND6_IFF_NO_DAD) == 0 && + ((ifp->if_flags & IFF_UP) == 0 || + (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || + (ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) != 0)){ ia6->ia6_flags &= ~IN6_IFF_DUPLICATED; ia6->ia6_flags |= IN6_IFF_TENTATIVE; } + /* * A new RA might have made a deprecated address * preferred. diff --git a/freebsd/sys/netinet6/raw_ip6.c b/freebsd/sys/netinet6/raw_ip6.c index 73d0832a..aa62b7e1 100644 --- a/freebsd/sys/netinet6/raw_ip6.c +++ b/freebsd/sys/netinet6/raw_ip6.c @@ -241,9 +241,16 @@ rip6_input(struct mbuf **mp, int *offp, int proto) } if (in6p->in6p_cksum != -1) { RIP6STAT_INC(rip6s_isum); - if (in6_cksum(m, proto, *offp, + if (m->m_pkthdr.len - (*offp + in6p->in6p_cksum) < 2 || + in6_cksum(m, proto, *offp, m->m_pkthdr.len - *offp)) { RIP6STAT_INC(rip6s_badsum); + /* + * Drop the received message, don't send an + * ICMP6 message. Set proto to IPPROTO_NONE + * to achieve that. + */ + proto = IPPROTO_NONE; goto skip_2; } } @@ -497,7 +504,7 @@ rip6_output(struct mbuf *m, struct socket *so, ...) off = offsetof(struct icmp6_hdr, icmp6_cksum); else off = in6p->in6p_cksum; - if (plen < off + 1) { + if (plen < off + 2) { error = EINVAL; goto bad; } diff --git a/freebsd/sys/netipsec/xform_ah.c b/freebsd/sys/netipsec/xform_ah.c index 84ba6c16..88e51306 100644 --- a/freebsd/sys/netipsec/xform_ah.c +++ b/freebsd/sys/netipsec/xform_ah.c @@ -110,6 +110,8 @@ SYSCTL_VNET_PCPUSTAT(_net_inet_ah, IPSECCTL_STATS, stats, struct ahstat, #endif static unsigned char ipseczeroes[256]; /* larger than an ip6 extension hdr */ +static struct timeval md5warn, ripewarn, kpdkmd5warn, kpdksha1warn; +static struct timeval warninterval = { .tv_sec = 1, .tv_usec = 0 }; static int ah_input_cb(struct cryptop*); static int ah_output_cb(struct cryptop*); @@ -186,6 +188,26 @@ ah_init0(struct secasvar *sav, struct xformsw *xsp, struct cryptoini *cria) __func__, sav->alg_auth)); return EINVAL; } + + switch (sav->alg_auth) { + case SADB_AALG_MD5HMAC: + if (ratecheck(&md5warn, &warninterval)) + gone_in(13, "MD5-HMAC authenticator for IPsec"); + break; + case SADB_X_AALG_RIPEMD160HMAC: + if (ratecheck(&ripewarn, &warninterval)) + gone_in(13, "RIPEMD160-HMAC authenticator for IPsec"); + break; + case SADB_X_AALG_MD5: + if (ratecheck(&kpdkmd5warn, &warninterval)) + gone_in(13, "Keyed-MD5 authenticator for IPsec"); + break; + case SADB_X_AALG_SHA: + if (ratecheck(&kpdksha1warn, &warninterval)) + gone_in(13, "Keyed-SHA1 authenticator for IPsec"); + break; + } + /* * Verify the replay state block allocation is consistent with * the protocol type. We check here so we can make assumptions diff --git a/freebsd/sys/netipsec/xform_esp.c b/freebsd/sys/netipsec/xform_esp.c index f8473575..d1a8a50a 100644 --- a/freebsd/sys/netipsec/xform_esp.c +++ b/freebsd/sys/netipsec/xform_esp.c @@ -96,6 +96,9 @@ SYSCTL_VNET_PCPUSTAT(_net_inet_esp, IPSECCTL_STATS, stats, struct espstat, espstat, "ESP statistics (struct espstat, netipsec/esp_var.h"); +static struct timeval deswarn, blfwarn, castwarn, camelliawarn; +static struct timeval warninterval = { .tv_sec = 1, .tv_usec = 0 }; + static int esp_input_cb(struct cryptop *op); static int esp_output_cb(struct cryptop *crp); @@ -158,6 +161,26 @@ esp_init(struct secasvar *sav, struct xformsw *xsp) __func__)); return EINVAL; } + + switch (sav->alg_enc) { + case SADB_EALG_DESCBC: + if (ratecheck(&deswarn, &warninterval)) + gone_in(13, "DES cipher for IPsec"); + break; + case SADB_X_EALG_BLOWFISHCBC: + if (ratecheck(&blfwarn, &warninterval)) + gone_in(13, "Blowfish cipher for IPsec"); + break; + case SADB_X_EALG_CAST128CBC: + if (ratecheck(&castwarn, &warninterval)) + gone_in(13, "CAST cipher for IPsec"); + break; + case SADB_X_EALG_CAMELLIACBC: + if (ratecheck(&camelliawarn, &warninterval)) + gone_in(13, "Camellia cipher for IPsec"); + break; + } + /* subtract off the salt, RFC4106, 8.1 and RFC3686, 5.1 */ keylen = _KEYLEN(sav->key_enc) - SAV_ISCTRORGCM(sav) * 4; if (txform->minkey > keylen || keylen > txform->maxkey) { diff --git a/freebsd/sys/netpfil/pf/pf.c b/freebsd/sys/netpfil/pf/pf.c index 015b2571..4f9da55b 100644 --- a/freebsd/sys/netpfil/pf/pf.c +++ b/freebsd/sys/netpfil/pf/pf.c @@ -6184,7 +6184,7 @@ done: pd.proto == IPPROTO_UDP) && s != NULL && s->nat_rule.ptr != NULL && (s->nat_rule.ptr->action == PF_RDR || s->nat_rule.ptr->action == PF_BINAT) && - (ntohl(pd.dst->v4.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) + IN_LOOPBACK(ntohl(pd.dst->v4.s_addr))) m->m_flags |= M_SKIP_FIREWALL; if (action == PF_PASS && r->divert.port && ip_divert_ptr != NULL && diff --git a/freebsd/sys/netpfil/pf/pf_ioctl.c b/freebsd/sys/netpfil/pf/pf_ioctl.c index 05cb3ccd..855ef699 100644 --- a/freebsd/sys/netpfil/pf/pf_ioctl.c +++ b/freebsd/sys/netpfil/pf/pf_ioctl.c @@ -3115,24 +3115,20 @@ DIOCCHANGEADDR_error: break; } - PF_RULES_WLOCK(); + PF_RULES_RLOCK(); n = pfr_table_count(&io->pfrio_table, io->pfrio_flags); io->pfrio_size = min(io->pfrio_size, n); + PF_RULES_RUNLOCK(); totlen = io->pfrio_size * sizeof(struct pfr_table); pfrts = mallocarray(io->pfrio_size, sizeof(struct pfr_table), - M_TEMP, M_NOWAIT); - if (pfrts == NULL) { - error = ENOMEM; - PF_RULES_WUNLOCK(); - break; - } + M_TEMP, M_WAITOK); error = copyin(io->pfrio_buffer, pfrts, totlen); if (error) { free(pfrts, M_TEMP); - PF_RULES_WUNLOCK(); break; } + PF_RULES_WLOCK(); error = pfr_set_tflags(pfrts, io->pfrio_size, io->pfrio_setflag, io->pfrio_clrflag, &io->pfrio_nchange, &io->pfrio_ndel, io->pfrio_flags | PFR_FLAG_USERIOCTL); diff --git a/freebsd/sys/netpfil/pf/pf_table.c b/freebsd/sys/netpfil/pf/pf_table.c index 6f418985..96ed849c 100644 --- a/freebsd/sys/netpfil/pf/pf_table.c +++ b/freebsd/sys/netpfil/pf/pf_table.c @@ -115,6 +115,7 @@ struct pfr_walktree { struct pfi_dynaddr *pfrw1_dyn; } pfrw_1; int pfrw_free; + int pfrw_flags; }; #define pfrw_addr pfrw_1.pfrw1_addr #define pfrw_astats pfrw_1.pfrw1_astats @@ -128,15 +129,16 @@ struct pfr_walktree { static MALLOC_DEFINE(M_PFTABLE, "pf_table", "pf(4) tables structures"); VNET_DEFINE_STATIC(uma_zone_t, pfr_kentry_z); #define V_pfr_kentry_z VNET(pfr_kentry_z) -VNET_DEFINE_STATIC(uma_zone_t, pfr_kcounters_z); -#define V_pfr_kcounters_z VNET(pfr_kcounters_z) static struct pf_addr pfr_ffaddr = { .addr32 = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff } }; +static void pfr_copyout_astats(struct pfr_astats *, + const struct pfr_kentry *, + const struct pfr_walktree *); static void pfr_copyout_addr(struct pfr_addr *, - struct pfr_kentry *ke); + const struct pfr_kentry *ke); static int pfr_validate_addr(struct pfr_addr *); static void pfr_enqueue_addrs(struct pfr_ktable *, struct pfr_kentryworkq *, int *, int); @@ -144,8 +146,12 @@ static void pfr_mark_addrs(struct pfr_ktable *); static struct pfr_kentry *pfr_lookup_addr(struct pfr_ktable *, struct pfr_addr *, int); +static bool pfr_create_kentry_counter(struct pfr_kcounters *, + int, int); static struct pfr_kentry *pfr_create_kentry(struct pfr_addr *); static void pfr_destroy_kentries(struct pfr_kentryworkq *); +static void pfr_destroy_kentry_counter(struct pfr_kcounters *, + int, int); static void pfr_destroy_kentry(struct pfr_kentry *); static void pfr_insert_kentries(struct pfr_ktable *, struct pfr_kentryworkq *, long); @@ -204,9 +210,6 @@ pfr_initialize(void) V_pfr_kentry_z = uma_zcreate("pf table entries", sizeof(struct pfr_kentry), NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); - V_pfr_kcounters_z = uma_zcreate("pf table counters", - sizeof(struct pfr_kcounters), NULL, NULL, NULL, NULL, - UMA_ALIGN_PTR, 0); V_pf_limits[PF_LIMIT_TABLE_ENTRIES].zone = V_pfr_kentry_z; V_pf_limits[PF_LIMIT_TABLE_ENTRIES].limit = PFR_KENTRY_HIWAT; } @@ -216,7 +219,6 @@ pfr_cleanup(void) { uma_zdestroy(V_pfr_kentry_z); - uma_zdestroy(V_pfr_kcounters_z); } int @@ -610,6 +612,13 @@ pfr_get_astats(struct pfr_table *tbl, struct pfr_astats *addr, int *size, w.pfrw_op = PFRW_GET_ASTATS; w.pfrw_astats = addr; w.pfrw_free = kt->pfrkt_cnt; + /* + * Flags below are for backward compatibility. It was possible to have + * a table without per-entry counters. Now they are always allocated, + * we just discard data when reading it if table is not configured to + * have counters. + */ + w.pfrw_flags = kt->pfrkt_flags; rv = kt->pfrkt_ip4->rnh_walktree(&kt->pfrkt_ip4->rh, pfr_walktree, &w); if (!rv) rv = kt->pfrkt_ip6->rnh_walktree(&kt->pfrkt_ip6->rh, @@ -776,10 +785,30 @@ pfr_lookup_addr(struct pfr_ktable *kt, struct pfr_addr *ad, int exact) return (ke); } +static bool +pfr_create_kentry_counter(struct pfr_kcounters *kc, int pfr_dir, int pfr_op) +{ + kc->pfrkc_packets[pfr_dir][pfr_op] = counter_u64_alloc(M_NOWAIT); + if (! kc->pfrkc_packets[pfr_dir][pfr_op]) + return (false); + + kc->pfrkc_bytes[pfr_dir][pfr_op] = counter_u64_alloc(M_NOWAIT); + if (! kc->pfrkc_bytes[pfr_dir][pfr_op]) { + /* Previous allocation will be freed through + * pfr_destroy_kentry() */ + return (false); + } + + kc->pfrkc_tzero = 0; + + return (true); +} + static struct pfr_kentry * pfr_create_kentry(struct pfr_addr *ad) { struct pfr_kentry *ke; + int pfr_dir, pfr_op; ke = uma_zalloc(V_pfr_kentry_z, M_NOWAIT | M_ZERO); if (ke == NULL) @@ -792,6 +821,14 @@ pfr_create_kentry(struct pfr_addr *ad) ke->pfrke_af = ad->pfra_af; ke->pfrke_net = ad->pfra_net; ke->pfrke_not = ad->pfra_not; + for (pfr_dir = 0; pfr_dir < PFR_DIR_MAX; pfr_dir ++) + for (pfr_op = 0; pfr_op < PFR_OP_ADDR_MAX; pfr_op ++) { + if (! pfr_create_kentry_counter(&ke->pfrke_counters, + pfr_dir, pfr_op)) { + pfr_destroy_kentry(ke); + return (NULL); + } + } return (ke); } @@ -807,10 +844,22 @@ pfr_destroy_kentries(struct pfr_kentryworkq *workq) } static void +pfr_destroy_kentry_counter(struct pfr_kcounters *kc, int pfr_dir, int pfr_op) +{ + counter_u64_free(kc->pfrkc_packets[pfr_dir][pfr_op]); + counter_u64_free(kc->pfrkc_bytes[pfr_dir][pfr_op]); +} + +static void pfr_destroy_kentry(struct pfr_kentry *ke) { - if (ke->pfrke_counters) - uma_zfree(V_pfr_kcounters_z, ke->pfrke_counters); + int pfr_dir, pfr_op; + + for (pfr_dir = 0; pfr_dir < PFR_DIR_MAX; pfr_dir ++) + for (pfr_op = 0; pfr_op < PFR_OP_ADDR_MAX; pfr_op ++) + pfr_destroy_kentry_counter(&ke->pfrke_counters, + pfr_dir, pfr_op); + uma_zfree(V_pfr_kentry_z, ke); } @@ -828,7 +877,7 @@ pfr_insert_kentries(struct pfr_ktable *kt, "(code=%d).\n", rv); break; } - p->pfrke_tzero = tzero; + p->pfrke_counters.pfrkc_tzero = tzero; n++; } kt->pfrkt_cnt += n; @@ -851,7 +900,7 @@ pfr_insert_kentry(struct pfr_ktable *kt, struct pfr_addr *ad, long tzero) if (rv) return (rv); - p->pfrke_tzero = tzero; + p->pfrke_counters.pfrkc_tzero = tzero; kt->pfrkt_cnt++; return (0); @@ -886,15 +935,20 @@ static void pfr_clstats_kentries(struct pfr_kentryworkq *workq, long tzero, int negchange) { struct pfr_kentry *p; + int pfr_dir, pfr_op; SLIST_FOREACH(p, workq, pfrke_workq) { if (negchange) p->pfrke_not = !p->pfrke_not; - if (p->pfrke_counters) { - uma_zfree(V_pfr_kcounters_z, p->pfrke_counters); - p->pfrke_counters = NULL; + for (pfr_dir = 0; pfr_dir < PFR_DIR_MAX; pfr_dir ++) { + for (pfr_op = 0; pfr_op < PFR_OP_ADDR_MAX; pfr_op ++) { + counter_u64_zero(p->pfrke_counters. + pfrkc_packets[pfr_dir][pfr_op]); + counter_u64_zero(p->pfrke_counters. + pfrkc_bytes[pfr_dir][pfr_op]); + } } - p->pfrke_tzero = tzero; + p->pfrke_counters.pfrkc_tzero = tzero; } } @@ -983,7 +1037,7 @@ pfr_unroute_kentry(struct pfr_ktable *kt, struct pfr_kentry *ke) } static void -pfr_copyout_addr(struct pfr_addr *ad, struct pfr_kentry *ke) +pfr_copyout_addr(struct pfr_addr *ad, const struct pfr_kentry *ke) { bzero(ad, sizeof(*ad)); if (ke == NULL) @@ -997,6 +1051,33 @@ pfr_copyout_addr(struct pfr_addr *ad, struct pfr_kentry *ke) ad->pfra_ip6addr = ke->pfrke_sa.sin6.sin6_addr; } +static void +pfr_copyout_astats(struct pfr_astats *as, const struct pfr_kentry *ke, + const struct pfr_walktree *w) +{ + int dir, op; + const struct pfr_kcounters *kc = &ke->pfrke_counters; + + pfr_copyout_addr(&as->pfras_a, ke); + as->pfras_tzero = kc->pfrkc_tzero; + + if (! (w->pfrw_flags & PFR_TFLAG_COUNTERS)) { + bzero(as->pfras_packets, sizeof(as->pfras_packets)); + bzero(as->pfras_bytes, sizeof(as->pfras_bytes)); + as->pfras_a.pfra_fback = PFR_FB_NOCOUNT; + return; + } + + for (dir = 0; dir < PFR_DIR_MAX; dir ++) { + for (op = 0; op < PFR_OP_ADDR_MAX; op ++) { + as->pfras_packets[dir][op] = + counter_u64_fetch(kc->pfrkc_packets[dir][op]); + as->pfras_bytes[dir][op] = + counter_u64_fetch(kc->pfrkc_bytes[dir][op]); + } + } +} + static int pfr_walktree(struct radix_node *rn, void *arg) { @@ -1025,19 +1106,7 @@ pfr_walktree(struct radix_node *rn, void *arg) if (w->pfrw_free-- > 0) { struct pfr_astats as; - pfr_copyout_addr(&as.pfras_a, ke); - - if (ke->pfrke_counters) { - bcopy(ke->pfrke_counters->pfrkc_packets, - as.pfras_packets, sizeof(as.pfras_packets)); - bcopy(ke->pfrke_counters->pfrkc_bytes, - as.pfras_bytes, sizeof(as.pfras_bytes)); - } else { - bzero(as.pfras_packets, sizeof(as.pfras_packets)); - bzero(as.pfras_bytes, sizeof(as.pfras_bytes)); - as.pfras_a.pfra_fback = PFR_FB_NOCOUNT; - } - as.pfras_tzero = ke->pfrke_tzero; + pfr_copyout_astats(&as, ke, w); bcopy(&as, w->pfrw_astats, sizeof(as)); w->pfrw_astats++; @@ -1262,6 +1331,7 @@ pfr_get_tstats(struct pfr_table *filter, struct pfr_tstats *tbl, int *size, struct pfr_ktableworkq workq; int n, nn; long tzero = time_second; + int pfr_dir, pfr_op; /* XXX PFR_FLAG_CLSTATS disabled */ ACCEPT_FLAGS(flags, PFR_FLAG_ALLRSETS); @@ -1280,7 +1350,25 @@ pfr_get_tstats(struct pfr_table *filter, struct pfr_tstats *tbl, int *size, continue; if (n-- <= 0) continue; - bcopy(&p->pfrkt_ts, tbl++, sizeof(*tbl)); + bcopy(&p->pfrkt_kts.pfrts_t, &tbl->pfrts_t, + sizeof(struct pfr_table)); + for (pfr_dir = 0; pfr_dir < PFR_DIR_MAX; pfr_dir ++) { + for (pfr_op = 0; pfr_op < PFR_OP_TABLE_MAX; pfr_op ++) { + tbl->pfrts_packets[pfr_dir][pfr_op] = + counter_u64_fetch( + p->pfrkt_packets[pfr_dir][pfr_op]); + tbl->pfrts_bytes[pfr_dir][pfr_op] = + counter_u64_fetch( + p->pfrkt_bytes[pfr_dir][pfr_op]); + } + } + tbl->pfrts_match = counter_u64_fetch(p->pfrkt_match); + tbl->pfrts_nomatch = counter_u64_fetch(p->pfrkt_nomatch); + tbl->pfrts_tzero = p->pfrkt_tzero; + tbl->pfrts_cnt = p->pfrkt_cnt; + for (pfr_op = 0; pfr_op < PFR_REFCNT_MAX; pfr_op++) + tbl->pfrts_refcnt[pfr_op] = p->pfrkt_refcnt[pfr_op]; + tbl++; SLIST_INSERT_HEAD(&workq, p, pfrkt_workq); } if (flags & PFR_FLAG_CLSTATS) @@ -1614,7 +1702,7 @@ pfr_commit_ktable(struct pfr_ktable *kt, long tzero) q->pfrke_mark = 1; SLIST_INSERT_HEAD(&garbageq, p, pfrke_workq); } else { - p->pfrke_tzero = tzero; + p->pfrke_counters.pfrkc_tzero = tzero; SLIST_INSERT_HEAD(&addq, p, pfrke_workq); } } @@ -1798,14 +1886,20 @@ static void pfr_clstats_ktable(struct pfr_ktable *kt, long tzero, int recurse) { struct pfr_kentryworkq addrq; + int pfr_dir, pfr_op; if (recurse) { pfr_enqueue_addrs(kt, &addrq, NULL, 0); pfr_clstats_kentries(&addrq, tzero, 0); } - bzero(kt->pfrkt_packets, sizeof(kt->pfrkt_packets)); - bzero(kt->pfrkt_bytes, sizeof(kt->pfrkt_bytes)); - kt->pfrkt_match = kt->pfrkt_nomatch = 0; + for (pfr_dir = 0; pfr_dir < PFR_DIR_MAX; pfr_dir ++) { + for (pfr_op = 0; pfr_op < PFR_OP_TABLE_MAX; pfr_op ++) { + counter_u64_zero(kt->pfrkt_packets[pfr_dir][pfr_op]); + counter_u64_zero(kt->pfrkt_bytes[pfr_dir][pfr_op]); + } + } + counter_u64_zero(kt->pfrkt_match); + counter_u64_zero(kt->pfrkt_nomatch); kt->pfrkt_tzero = tzero; } @@ -1814,6 +1908,7 @@ pfr_create_ktable(struct pfr_table *tbl, long tzero, int attachruleset) { struct pfr_ktable *kt; struct pf_ruleset *rs; + int pfr_dir, pfr_op; PF_RULES_WASSERT(); @@ -1832,6 +1927,34 @@ pfr_create_ktable(struct pfr_table *tbl, long tzero, int attachruleset) rs->tables++; } + for (pfr_dir = 0; pfr_dir < PFR_DIR_MAX; pfr_dir ++) { + for (pfr_op = 0; pfr_op < PFR_OP_TABLE_MAX; pfr_op ++) { + kt->pfrkt_packets[pfr_dir][pfr_op] = + counter_u64_alloc(M_NOWAIT); + if (! kt->pfrkt_packets[pfr_dir][pfr_op]) { + pfr_destroy_ktable(kt, 0); + return (NULL); + } + kt->pfrkt_bytes[pfr_dir][pfr_op] = + counter_u64_alloc(M_NOWAIT); + if (! kt->pfrkt_bytes[pfr_dir][pfr_op]) { + pfr_destroy_ktable(kt, 0); + return (NULL); + } + } + } + kt->pfrkt_match = counter_u64_alloc(M_NOWAIT); + if (! kt->pfrkt_match) { + pfr_destroy_ktable(kt, 0); + return (NULL); + } + + kt->pfrkt_nomatch = counter_u64_alloc(M_NOWAIT); + if (! kt->pfrkt_nomatch) { + pfr_destroy_ktable(kt, 0); + return (NULL); + } + if (!rn_inithead((void **)&kt->pfrkt_ip4, offsetof(struct sockaddr_in, sin_addr) * 8) || !rn_inithead((void **)&kt->pfrkt_ip6, @@ -1859,6 +1982,7 @@ static void pfr_destroy_ktable(struct pfr_ktable *kt, int flushaddr) { struct pfr_kentryworkq addrq; + int pfr_dir, pfr_op; if (flushaddr) { pfr_enqueue_addrs(kt, &addrq, NULL, 0); @@ -1875,6 +1999,15 @@ pfr_destroy_ktable(struct pfr_ktable *kt, int flushaddr) kt->pfrkt_rs->tables--; pf_remove_if_empty_ruleset(kt->pfrkt_rs); } + for (pfr_dir = 0; pfr_dir < PFR_DIR_MAX; pfr_dir ++) { + for (pfr_op = 0; pfr_op < PFR_OP_TABLE_MAX; pfr_op ++) { + counter_u64_free(kt->pfrkt_packets[pfr_dir][pfr_op]); + counter_u64_free(kt->pfrkt_bytes[pfr_dir][pfr_op]); + } + } + counter_u64_free(kt->pfrkt_match); + counter_u64_free(kt->pfrkt_nomatch); + free(kt, M_PFTABLE); } @@ -1943,9 +2076,9 @@ pfr_match_addr(struct pfr_ktable *kt, struct pf_addr *a, sa_family_t af) } match = (ke && !ke->pfrke_not); if (match) - kt->pfrkt_match++; + counter_u64_add(kt->pfrkt_match, 1); else - kt->pfrkt_nomatch++; + counter_u64_add(kt->pfrkt_nomatch, 1); return (match); } @@ -2000,17 +2133,14 @@ pfr_update_stats(struct pfr_ktable *kt, struct pf_addr *a, sa_family_t af, ("pfr_update_stats: assertion failed.\n")); op_pass = PFR_OP_XPASS; } - kt->pfrkt_packets[dir_out][op_pass]++; - kt->pfrkt_bytes[dir_out][op_pass] += len; + counter_u64_add(kt->pfrkt_packets[dir_out][op_pass], 1); + counter_u64_add(kt->pfrkt_bytes[dir_out][op_pass], len); if (ke != NULL && op_pass != PFR_OP_XPASS && (kt->pfrkt_flags & PFR_TFLAG_COUNTERS)) { - if (ke->pfrke_counters == NULL) - ke->pfrke_counters = uma_zalloc(V_pfr_kcounters_z, - M_NOWAIT | M_ZERO); - if (ke->pfrke_counters != NULL) { - ke->pfrke_counters->pfrkc_packets[dir_out][op_pass]++; - ke->pfrke_counters->pfrkc_bytes[dir_out][op_pass] += len; - } + counter_u64_add(ke->pfrke_counters. + pfrkc_packets[dir_out][op_pass], 1); + counter_u64_add(ke->pfrke_counters. + pfrkc_bytes[dir_out][op_pass], len); } } @@ -2100,7 +2230,7 @@ pfr_pool_get(struct pfr_ktable *kt, int *pidx, struct pf_addr *counter, _next_block: ke = pfr_kentry_byidx(kt, idx, af); if (ke == NULL) { - kt->pfrkt_nomatch++; + counter_u64_add(kt->pfrkt_nomatch, 1); return (1); } pfr_prepare_network(&umask, af, ke->pfrke_net); @@ -2125,7 +2255,7 @@ _next_block: /* this is a single IP address - no possible nested block */ PF_ACPY(counter, addr, af); *pidx = idx; - kt->pfrkt_match++; + counter_u64_add(kt->pfrkt_match, 1); return (0); } for (;;) { @@ -2145,7 +2275,7 @@ _next_block: /* lookup return the same block - perfect */ PF_ACPY(counter, addr, af); *pidx = idx; - kt->pfrkt_match++; + counter_u64_add(kt->pfrkt_match, 1); return (0); } diff --git a/freebsd/sys/opencrypto/cbc_mac.c b/freebsd/sys/opencrypto/cbc_mac.c index e68525ef..1bcf356a 100644 --- a/freebsd/sys/opencrypto/cbc_mac.c +++ b/freebsd/sys/opencrypto/cbc_mac.c @@ -84,9 +84,6 @@ AES_CBC_MAC_Reinit(struct aes_cbc_mac_ctx *ctx, const uint8_t *nonce, uint16_t n uint8_t *bp = b0, flags = 0; uint8_t L = 0; uint64_t dataLength = ctx->cryptDataLength; - - KASSERT(ctx->authDataLength != 0 || ctx->cryptDataLength != 0, - ("Auth Data and Data lengths cannot both be 0")); KASSERT(nonceLen >= 7 && nonceLen <= 13, ("nonceLen must be between 7 and 13 bytes")); diff --git a/freebsd/sys/powerpc/include/machine/spr.h b/freebsd/sys/powerpc/include/machine/spr.h index 8fa828e1..9b13c291 100644 --- a/freebsd/sys/powerpc/include/machine/spr.h +++ b/freebsd/sys/powerpc/include/machine/spr.h @@ -242,6 +242,8 @@ #define LPCR_PECE_ME (1ULL << 12) /* Machine Check and Hypervisor */ /* Maintenance exceptions */ #define SPR_LPID 0x13f /* Logical Partitioning Control */ +#define SPR_HMER 0x150 /* Hypervisor Maintenance Exception Register */ +#define SPR_HMEER 0x151 /* Hypervisor Maintenance Exception Enable Register */ #define SPR_PTCR 0x1d0 /* Partition Table Control Register */ #define SPR_SPEFSCR 0x200 /* ..8 Signal Processing Engine FSCR. */ diff --git a/freebsd/sys/sys/ata.h b/freebsd/sys/sys/ata.h index f8a332c3..0559b35d 100644 --- a/freebsd/sys/sys/ata.h +++ b/freebsd/sys/sys/ata.h @@ -393,6 +393,12 @@ struct ata_params { #define ATA_READ_LOG_DMA_EXT 0x47 /* read log DMA ext - PIO Data-In */ #define ATA_ZAC_MANAGEMENT_IN 0x4a /* ZAC management in */ #define ATA_ZM_REPORT_ZONES 0x00 /* report zones */ +#define ATA_WRITE_LOG_DMA_EXT 0x57 /* WRITE LOG DMA EXT */ +#define ATA_TRUSTED_NON_DATA 0x5b /* TRUSTED NON-DATA */ +#define ATA_TRUSTED_RECEIVE 0x5c /* TRUSTED RECEIVE */ +#define ATA_TRUSTED_RECEIVE_DMA 0x5d /* TRUSTED RECEIVE DMA */ +#define ATA_TRUSTED_SEND 0x5e /* TRUSTED SEND */ +#define ATA_TRUSTED_SEND_DMA 0x5f /* TRUSTED SEND DMA */ #define ATA_READ_FPDMA_QUEUED 0x60 /* read DMA NCQ */ #define ATA_WRITE_FPDMA_QUEUED 0x61 /* write DMA NCQ */ #define ATA_NCQ_NON_DATA 0x63 /* NCQ non-data command */ @@ -417,6 +423,8 @@ struct ata_params { #define ATA_ZM_FINISH_ZONE 0x02 /* finish zone */ #define ATA_ZM_OPEN_ZONE 0x03 /* open zone */ #define ATA_ZM_RWP 0x04 /* reset write pointer */ +#define ATA_DOWNLOAD_MICROCODE 0x92 /* DOWNLOAD MICROCODE */ +#define ATA_DOWNLOAD_MICROCODE_DMA 0x93 /* DOWNLOAD MICROCODE DMA */ #define ATA_PACKET_CMD 0xa0 /* packet command */ #define ATA_ATAPI_IDENTIFY 0xa1 /* get ATAPI params*/ #define ATA_SERVICE 0xa2 /* service command */ @@ -439,8 +447,11 @@ struct ata_params { #define ATA_CHECK_POWER_MODE 0xe5 /* device power mode */ #define ATA_SLEEP 0xe6 /* sleep */ #define ATA_FLUSHCACHE 0xe7 /* flush cache to disk */ +#define ATA_WRITE_BUFFER 0xe8 /* write buffer */ #define ATA_WRITE_PM 0xe8 /* write portmultiplier */ +#define ATA_READ_BUFFER_DMA 0xe9 /* read buffer DMA */ #define ATA_FLUSHCACHE48 0xea /* flush cache to disk */ +#define ATA_WRITE_BUFFER_DMA 0xeb /* write buffer DMA */ #define ATA_ATA_IDENTIFY 0xec /* get ATA params */ #define ATA_SETFEATURES 0xef /* features command */ #define ATA_SF_ENAB_WCACHE 0x02 /* enable write cache */ diff --git a/freebsd/sys/sys/bus.h b/freebsd/sys/sys/bus.h index 0159b829..e2c4fe1a 100644 --- a/freebsd/sys/sys/bus.h +++ b/freebsd/sys/sys/bus.h @@ -130,6 +130,7 @@ struct devreq { #define DEV_DELETE _IOW('D', 10, struct devreq) #define DEV_FREEZE _IOW('D', 11, struct devreq) #define DEV_THAW _IOW('D', 12, struct devreq) +#define DEV_RESET _IOW('D', 13, struct devreq) /* Flags for DEV_DETACH and DEV_DISABLE. */ #define DEVF_FORCE_DETACH 0x0000001 @@ -143,6 +144,10 @@ struct devreq { /* Flags for DEV_DELETE. */ #define DEVF_FORCE_DELETE 0x0000001 +/* Flags for DEV_RESET */ +#define DEVF_RESET_DETACH 0x0000001 /* Detach drivers vs suspend + device */ + #ifdef _KERNEL #include <sys/eventhandler.h> @@ -494,6 +499,8 @@ int bus_generic_unmap_resource(device_t dev, device_t child, int type, struct resource_map *map); int bus_generic_write_ivar(device_t dev, device_t child, int which, uintptr_t value); +int bus_helper_reset_post(device_t dev, int flags); +int bus_helper_reset_prepare(device_t dev, int flags); int bus_null_rescan(device_t dev); /* diff --git a/freebsd/sys/sys/capsicum.h b/freebsd/sys/sys/capsicum.h index d40b8572..ee5e4267 100644 --- a/freebsd/sys/sys/capsicum.h +++ b/freebsd/sys/sys/capsicum.h @@ -246,7 +246,12 @@ /* Process management via process descriptors. */ /* Allows for pdgetpid(2). */ #define CAP_PDGETPID CAPRIGHT(1, 0x0000000000000200ULL) -/* Allows for pdwait4(2). */ +/* + * Allows for pdwait4(2). + * + * XXX: this constant was imported unused, but is targeted to be implemented + * in the future (bug 235871). + */ #define CAP_PDWAIT CAPRIGHT(1, 0x0000000000000400ULL) /* Allows for pdkill(2). */ #define CAP_PDKILL CAPRIGHT(1, 0x0000000000000800ULL) diff --git a/freebsd/sys/sys/ctype.h b/freebsd/sys/sys/ctype.h index b2a1fa93..d542e45a 100644 --- a/freebsd/sys/sys/ctype.h +++ b/freebsd/sys/sys/ctype.h @@ -41,19 +41,65 @@ #ifdef _KERNEL -#define isspace(c) ((c) == ' ' || ((c) >= '\t' && (c) <= '\r')) -#define isascii(c) (((c) & ~0x7f) == 0) -#define isupper(c) ((c) >= 'A' && (c) <= 'Z') -#define islower(c) ((c) >= 'a' && (c) <= 'z') -#define isalpha(c) (isupper(c) || islower(c)) -#define isdigit(c) ((c) >= '0' && (c) <= '9') -#define isxdigit(c) (isdigit(c) \ - || ((c) >= 'A' && (c) <= 'F') \ - || ((c) >= 'a' && (c) <= 'f')) -#define isprint(c) ((c) >= ' ' && (c) <= '~') - -#define toupper(c) ((c) - 0x20 * (((c) >= 'a') && ((c) <= 'z'))) -#define tolower(c) ((c) + 0x20 * (((c) >= 'A') && ((c) <= 'Z'))) +static __inline int +isspace(int c) +{ + return (c == ' ' || (c >= '\t' && c <= '\r')); +} + +static __inline int +isascii(int c) +{ + return ((c & ~0x7f) == 0); +} + +static __inline int +isupper(int c) +{ + return (c >= 'A' && c <= 'Z'); +} + +static __inline int +islower(int c) +{ + return (c >= 'a' && c <= 'z'); +} + +static __inline int +isalpha(int c) +{ + return (isupper(c) || islower(c)); +} + +static __inline int +isdigit(int c) +{ + return (c >= '0' && c <= '9'); +} + +static __inline int +isxdigit(int c) +{ + return (isdigit(c) || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f')); +} + +static __inline int +isprint(int c) +{ + return (c >= ' ' && c <= '~'); +} + +static __inline int +toupper(int c) +{ + return (c - 0x20 * ((c >= 'a') && (c <= 'z'))); +} + +static __inline int +tolower(int c) +{ + return (c + 0x20 * ((c >= 'A') && (c <= 'Z'))); +} #endif #endif /* !_SYS_CTYPE_H_ */ diff --git a/freebsd/sys/sys/libkern.h b/freebsd/sys/sys/libkern.h index 28da25ca..8e63fa2d 100644 --- a/freebsd/sys/sys/libkern.h +++ b/freebsd/sys/sys/libkern.h @@ -230,6 +230,7 @@ char *strchr(const char *, int); int strcmp(const char *, const char *); char *strcpy(char * __restrict, const char * __restrict); size_t strcspn(const char * __restrict, const char * __restrict) __pure; +char *strdup_flags(const char *__restrict, struct malloc_type *, int); #ifdef __rtems__ #include <string.h> #define strdup _bsd_strdup diff --git a/freebsd/sys/sys/random.h b/freebsd/sys/sys/random.h index 32d8122d..866d658b 100644 --- a/freebsd/sys/sys/random.h +++ b/freebsd/sys/sys/random.h @@ -100,6 +100,7 @@ enum random_entropy_source { RANDOM_PURE_BROADCOM, RANDOM_PURE_CCP, RANDOM_PURE_DARN, + RANDOM_PURE_TPM, ENTROPYSOURCE }; diff --git a/freebsd/sys/sys/seq.h b/freebsd/sys/sys/seq.h index c5f00bcb..657edf4d 100644 --- a/freebsd/sys/sys/seq.h +++ b/freebsd/sys/sys/seq.h @@ -121,7 +121,7 @@ seq_write_end(seq_t *seqp) } static __inline seq_t -seq_read(const seq_t *seqp) +seq_load(const seq_t *seqp) { seq_t ret; diff --git a/freebsd/sys/sys/slicer.h b/freebsd/sys/sys/slicer.h index 1565ecce..675b5acc 100644 --- a/freebsd/sys/sys/slicer.h +++ b/freebsd/sys/sys/slicer.h @@ -58,7 +58,7 @@ typedef int (*flash_slicer_t)(device_t dev, const char *provider, #define FLASH_SLICES_TYPE_SPI 2 #define FLASH_SLICES_TYPE_MMC 3 -/* Use NULL for deregistering a slicer */ +/* Use NULL and set force to true for deregistering a slicer */ void flash_register_slicer(flash_slicer_t slicer, u_int type, bool force); #endif /* _KERNEL */ diff --git a/freebsd/sys/sys/sysctl.h b/freebsd/sys/sys/sysctl.h index a0aa8f75..4b2bfd76 100644 --- a/freebsd/sys/sys/sysctl.h +++ b/freebsd/sys/sys/sysctl.h @@ -388,6 +388,25 @@ TAILQ_HEAD(sysctl_ctx_list, sysctl_ctx_entry); NULL); \ }) +/* Oid for a constant '\0' terminated string. */ +#define SYSCTL_CONST_STRING(parent, nbr, name, access, arg, descr) \ + SYSCTL_OID(parent, nbr, name, CTLTYPE_STRING|(access), \ + __DECONST(char *, arg), 0, sysctl_handle_string, "A", descr); \ + CTASSERT(!(access & CTLFLAG_WR)); \ + CTASSERT(((access) & CTLTYPE) == 0 || \ + ((access) & SYSCTL_CT_ASSERT_MASK) == CTLTYPE_STRING) + +#define SYSCTL_ADD_CONST_STRING(ctx, parent, nbr, name, access, arg, descr) \ +({ \ + char *__arg = __DECONST(char *, arg); \ + CTASSERT(!(access & CTLFLAG_WR)); \ + CTASSERT(((access) & CTLTYPE) == 0 || \ + ((access) & SYSCTL_CT_ASSERT_MASK) == CTLTYPE_STRING); \ + sysctl_add_oid(ctx, parent, nbr, name, CTLTYPE_STRING|(access), \ + __arg, 0, sysctl_handle_string, "A", __DESCR(descr), \ + NULL); \ +}) + /* Oid for a bool. If ptr is NULL, val is returned. */ #define SYSCTL_NULL_BOOL_PTR ((bool *)NULL) #define SYSCTL_BOOL(parent, nbr, name, access, ptr, val, descr) \ diff --git a/freebsd/sys/sys/systm.h b/freebsd/sys/sys/systm.h index cbd9a7e8..ae25b843 100644 --- a/freebsd/sys/sys/systm.h +++ b/freebsd/sys/sys/systm.h @@ -688,6 +688,7 @@ void counted_warning(unsigned *counter, const char *msg); /* * APIs to manage deprecation and obsolescence. */ +#ifndef __rtems__ struct device; void _gone_in(int major, const char *msg); void _gone_in_dev(struct device *dev, int major, const char *msg); @@ -703,6 +704,10 @@ void _gone_in_dev(struct device *dev, int major, const char *msg); #define gone_by_fcp101_dev(dev) \ gone_in_dev((dev), 13, \ "see https://github.com/freebsd/fcp/blob/master/fcp-0101.md") +#else /* __rtems__ */ +#define gone_in(major, msg) do { } while (0) +#define gone_in_dev(dev, major, msg) do { } while (0) +#endif /* __rtems__ */ __NULLABILITY_PRAGMA_POP diff --git a/freebsd/sys/sys/user.h b/freebsd/sys/sys/user.h index a46ecd87..b2338f01 100644 --- a/freebsd/sys/sys/user.h +++ b/freebsd/sys/sys/user.h @@ -614,6 +614,7 @@ int kern_proc_vmmap_out(struct proc *p, struct sbuf *sb, ssize_t maxlen, int flags); int vntype_to_kinfo(int vtype); +void pack_kinfo(struct kinfo_file *kif); #endif /* !_KERNEL */ #endif diff --git a/freebsd/sys/sys/vnode.h b/freebsd/sys/sys/vnode.h index ac6f4f4e..1cc67ecf 100644 --- a/freebsd/sys/sys/vnode.h +++ b/freebsd/sys/sys/vnode.h @@ -670,6 +670,7 @@ int vn_close(struct vnode *vp, int flags, struct ucred *file_cred, struct thread *td); void vn_finished_write(struct mount *mp); void vn_finished_secondary_write(struct mount *mp); +int vn_fsync_buf(struct vnode *vp, int waitfor); int vn_isdisk(struct vnode *vp, int *errp); int _vn_lock(struct vnode *vp, int flags, char *file, int line); #define vn_lock(vp, flags) _vn_lock(vp, flags, __FILE__, __LINE__) diff --git a/freebsd/sys/x86/include/machine/bus.h b/freebsd/sys/x86/include/machine/bus.h index 297b5edc..2427ae51 100644 --- a/freebsd/sys/x86/include/machine/bus.h +++ b/freebsd/sys/x86/include/machine/bus.h @@ -114,7 +114,11 @@ #define BUS_SPACE_MAXSIZE_24BIT 0xFFFFFF #define BUS_SPACE_MAXSIZE_32BIT 0xFFFFFFFF +#if defined(__amd64__) +#define BUS_SPACE_MAXSIZE 0xFFFFFFFFFFFFFFFFULL +#else #define BUS_SPACE_MAXSIZE 0xFFFFFFFF +#endif #define BUS_SPACE_MAXADDR_24BIT 0xFFFFFF #define BUS_SPACE_MAXADDR_32BIT 0xFFFFFFFF #if defined(__amd64__) || defined(PAE) diff --git a/freebsd/sys/x86/include/machine/pci_cfgreg.h b/freebsd/sys/x86/include/machine/pci_cfgreg.h index 8083eb0e..85d6485c 100644 --- a/freebsd/sys/x86/include/machine/pci_cfgreg.h +++ b/freebsd/sys/x86/include/machine/pci_cfgreg.h @@ -48,6 +48,15 @@ #define CONF2_ENABLE_CHK 0x0e #define CONF2_ENABLE_RES 0x0e +enum { + CFGMECH_NONE = 0, + CFGMECH_1, + CFGMECH_2, + CFGMECH_PCIE, +}; + +extern int cfgmech; + rman_res_t hostb_alloc_start(int type, rman_res_t start, rman_res_t end, rman_res_t count); int pcie_cfgregopen(uint64_t base, uint8_t minbus, uint8_t maxbus); int pci_cfgregopen(void); diff --git a/freebsd/usr.bin/netstat/inet.c b/freebsd/usr.bin/netstat/inet.c index 4eb80816..73d3ec65 100644 --- a/freebsd/usr.bin/netstat/inet.c +++ b/freebsd/usr.bin/netstat/inet.c @@ -97,8 +97,10 @@ __FBSDID("$FreeBSD$"); #include "rtems-bsd-netstat-inet-data.h" #endif /* __rtems__ */ -void inetprint(const char *, struct in_addr *, int, const char *, int, +#ifdef INET +static void inetprint(const char *, struct in_addr *, int, const char *, int, const int); +#endif #ifdef INET6 static int udp_done, tcp_done, sdp_done; #endif /* INET6 */ @@ -412,6 +414,7 @@ protopr(u_long off, const char *name, int af1, int proto) so->so_rcv.sb_cc, so->so_snd.sb_cc); } if (numeric_port) { +#ifdef INET if (inp->inp_vflag & INP_IPV4) { inetprint("local", &inp->inp_laddr, (int)inp->inp_lport, name, 1, af1); @@ -419,8 +422,12 @@ protopr(u_long off, const char *name, int af1, int proto) inetprint("remote", &inp->inp_faddr, (int)inp->inp_fport, name, 1, af1); } +#endif +#if defined(INET) && defined(INET6) + else +#endif #ifdef INET6 - else if (inp->inp_vflag & INP_IPV6) { + if (inp->inp_vflag & INP_IPV6) { inet6print("local", &inp->in6p_laddr, (int)inp->inp_lport, name, 1); if (!Lflag) @@ -429,6 +436,7 @@ protopr(u_long off, const char *name, int af1, int proto) } /* else nothing printed now */ #endif /* INET6 */ } else if (inp->inp_flags & INP_ANONPORT) { +#ifdef INET if (inp->inp_vflag & INP_IPV4) { inetprint("local", &inp->inp_laddr, (int)inp->inp_lport, name, 1, af1); @@ -436,8 +444,12 @@ protopr(u_long off, const char *name, int af1, int proto) inetprint("remote", &inp->inp_faddr, (int)inp->inp_fport, name, 0, af1); } +#endif +#if defined(INET) && defined(INET6) + else +#endif #ifdef INET6 - else if (inp->inp_vflag & INP_IPV6) { + if (inp->inp_vflag & INP_IPV6) { inet6print("local", &inp->in6p_laddr, (int)inp->inp_lport, name, 1); if (!Lflag) @@ -446,6 +458,7 @@ protopr(u_long off, const char *name, int af1, int proto) } /* else nothing printed now */ #endif /* INET6 */ } else { +#ifdef INET if (inp->inp_vflag & INP_IPV4) { inetprint("local", &inp->inp_laddr, (int)inp->inp_lport, name, 0, af1); @@ -455,8 +468,12 @@ protopr(u_long off, const char *name, int af1, int proto) inp->inp_lport != inp->inp_fport, af1); } +#endif +#if defined(INET) && defined(INET6) + else +#endif #ifdef INET6 - else if (inp->inp_vflag & INP_IPV6) { + if (inp->inp_vflag & INP_IPV6) { inet6print("local", &inp->in6p_laddr, (int)inp->inp_lport, name, 0); if (!Lflag) @@ -1340,10 +1357,11 @@ pim_stats(u_long off __unused, const char *name, int af1 __unused, xo_close_container(name); } +#ifdef INET /* * Pretty print an Internet address (net address + port). */ -void +static void inetprint(const char *container, struct in_addr *in, int port, const char *proto, int num_port, const int af1) { @@ -1430,3 +1448,4 @@ inetname(struct in_addr *inp) } return (line); } +#endif @@ -1643,6 +1643,7 @@ class net(builder.Module): 'sys/net/ethernet.h', 'sys/net/firewire.h', 'sys/net/ieee8023ad_lacp.h', + 'sys/net/ieee_oui.h', 'sys/net/if_arp.h', 'sys/net/if_bridgevar.h', 'sys/net/if_clone.h', @@ -4445,17 +4446,22 @@ class usr_sbin_wpa_supplicant(builder.Module): 'contrib/wpa/src/ap/wpa_auth_i.h', 'contrib/wpa/src/common/ctrl_iface_common.h', 'contrib/wpa/src/common/defs.h', + 'contrib/wpa/src/common/dpp.h', 'contrib/wpa/src/common/eapol_common.h', 'contrib/wpa/src/common/gas.h', + 'contrib/wpa/src/common/gas_server.h', 'contrib/wpa/src/common/hw_features_common.h', 'contrib/wpa/src/common/ieee802_11_common.h', 'contrib/wpa/src/common/ieee802_11_defs.h', + 'contrib/wpa/src/common/ieee802_1x_defs.h', + 'contrib/wpa/src/common/ocv.h', 'contrib/wpa/src/common/qca-vendor.h', 'contrib/wpa/src/common/sae.h', 'contrib/wpa/src/common/version.h', 'contrib/wpa/src/common/wpa_common.h', 'contrib/wpa/src/common/wpa_ctrl.h', 'contrib/wpa/src/crypto/aes.h', + 'contrib/wpa/src/crypto/aes_siv.h', 'contrib/wpa/src/crypto/aes_wrap.h', 'contrib/wpa/src/crypto/crypto.h', 'contrib/wpa/src/crypto/dh_group5.h', @@ -4466,10 +4472,12 @@ class usr_sbin_wpa_supplicant(builder.Module): 'contrib/wpa/src/crypto/sha256.h', 'contrib/wpa/src/crypto/sha256_i.h', 'contrib/wpa/src/crypto/sha384.h', + 'contrib/wpa/src/crypto/sha512.h', 'contrib/wpa/src/crypto/tls.h', 'contrib/wpa/src/drivers/driver.h', 'contrib/wpa/src/drivers/driver_ndis.h', 'contrib/wpa/src/drivers/driver_nl80211.h', + 'contrib/wpa/src/drivers/driver_wired_common.h', 'contrib/wpa/src/drivers/linux_defines.h', 'contrib/wpa/src/eap_common/chap.h', 'contrib/wpa/src/eap_common/eap_common.h', @@ -4496,7 +4504,6 @@ class usr_sbin_wpa_supplicant(builder.Module): 'contrib/wpa/src/l2_packet/l2_packet.h', 'contrib/wpa/src/p2p/p2p.h', 'contrib/wpa/src/radius/radius.h', - 'contrib/wpa/src/rsn_supp/peerkey.h', 'contrib/wpa/src/rsn_supp/pmksa_cache.h', 'contrib/wpa/src/rsn_supp/preauth.h', 'contrib/wpa/src/rsn_supp/wpa.h', @@ -4509,6 +4516,7 @@ class usr_sbin_wpa_supplicant(builder.Module): 'contrib/wpa/src/utils/bitfield.h', 'contrib/wpa/src/utils/build_config.h', 'contrib/wpa/src/utils/common.h', + 'contrib/wpa/src/utils/const_time.h', 'contrib/wpa/src/utils/eloop.h', 'contrib/wpa/src/utils/ext_password.h', 'contrib/wpa/src/utils/includes.h', @@ -4547,7 +4555,7 @@ class usr_sbin_wpa_supplicant(builder.Module): 'contrib/wpa/wpa_supplicant/ctrl_iface.h', 'contrib/wpa/wpa_supplicant/dbus/dbus_common.h', 'contrib/wpa/wpa_supplicant/dbus/dbus_new.h', - 'contrib/wpa/wpa_supplicant/dbus/dbus_old.h', + 'contrib/wpa/wpa_supplicant/dpp_supplicant.h', 'contrib/wpa/wpa_supplicant/driver_i.h', 'contrib/wpa/wpa_supplicant/gas_query.h', 'contrib/wpa/wpa_supplicant/hs20_supplicant.h', @@ -4588,10 +4596,12 @@ class usr_sbin_wpa_supplicant(builder.Module): 'contrib/wpa/wpa_supplicant/main.c', 'contrib/wpa/wpa_supplicant/notify.c', 'contrib/wpa/wpa_supplicant/offchannel.c', + 'contrib/wpa/wpa_supplicant/op_classes.c', + 'contrib/wpa/wpa_supplicant/rrm.c', 'contrib/wpa/wpa_supplicant/scan.c', 'contrib/wpa/wpa_supplicant/wmm_ac.c', - 'contrib/wpa/wpa_supplicant/wpa_supplicant.c', 'contrib/wpa/wpa_supplicant/wpas_glue.c', + 'contrib/wpa/wpa_supplicant/wpa_supplicant.c', 'contrib/wpa/wpa_supplicant/wps_supplicant.c', 'contrib/wpa/src/ap/ap_drv_ops.c', 'contrib/wpa/src/ap/hs20.c', @@ -4599,6 +4609,7 @@ class usr_sbin_wpa_supplicant(builder.Module): 'contrib/wpa/src/ap/wpa_auth.c', 'contrib/wpa/src/ap/wpa_auth_ft.c', 'contrib/wpa/src/utils/base64.c', + 'contrib/wpa/src/utils/bitfield.c', 'contrib/wpa/src/utils/common.c', 'contrib/wpa/src/utils/eloop.c', 'contrib/wpa/src/utils/os_unix.c', @@ -4614,6 +4625,7 @@ class usr_sbin_wpa_supplicant(builder.Module): 'contrib/wpa/src/drivers/driver_common.c', 'contrib/wpa/src/drivers/driver_ndis.c', 'contrib/wpa/src/drivers/driver_wired.c', + 'contrib/wpa/src/drivers/driver_wired_common.c', 'contrib/wpa/src/drivers/drivers.c', 'contrib/wpa/src/wps/http_client.c', 'contrib/wpa/src/wps/http_server.c', @@ -4633,7 +4645,6 @@ class usr_sbin_wpa_supplicant(builder.Module): 'contrib/wpa/src/wps/wps_upnp_ssdp.c', 'contrib/wpa/src/wps/wps_upnp_web.c', 'contrib/wpa/src/l2_packet/l2_packet_freebsd.c', - 'contrib/wpa/src/rsn_supp/peerkey.c', 'contrib/wpa/src/rsn_supp/pmksa_cache.c', 'contrib/wpa/src/rsn_supp/preauth.c', 'contrib/wpa/src/rsn_supp/wpa.c', diff --git a/rtemsbsd/include/machine/rtems-bsd-kernel-namespace.h b/rtemsbsd/include/machine/rtems-bsd-kernel-namespace.h index 30272306..bcf195af 100644 --- a/rtemsbsd/include/machine/rtems-bsd-kernel-namespace.h +++ b/rtemsbsd/include/machine/rtems-bsd-kernel-namespace.h @@ -358,7 +358,6 @@ #define bridge_control_table_size _bsd_bridge_control_table_size #define bridge_dn_p _bsd_bridge_dn_p #define bridge_rtable_prune_period _bsd_bridge_rtable_prune_period -#define bridge_rtnode_zone _bsd_bridge_rtnode_zone #define bstp_attach _bsd_bstp_attach #define bstp_create _bsd_bstp_create #define bstp_destroy _bsd_bstp_destroy @@ -462,6 +461,8 @@ #define bus_get_resource _bsd_bus_get_resource #define bus_get_resource_count _bsd_bus_get_resource_count #define bus_get_resource_start _bsd_bus_get_resource_start +#define bus_helper_reset_post _bsd_bus_helper_reset_post +#define bus_helper_reset_prepare _bsd_bus_helper_reset_prepare #define bus_map_resource _bsd_bus_map_resource #define bus_null_rescan _bsd_bus_null_rescan #define bus_print_child_domain _bsd_bus_print_child_domain @@ -1139,6 +1140,7 @@ #define ether_crc32_be _bsd_ether_crc32_be #define ether_crc32_le _bsd_ether_crc32_le #define ether_demux _bsd_ether_demux +#define ether_gen_addr _bsd_ether_gen_addr #define ether_ifattach _bsd_ether_ifattach #define ether_ifdetach _bsd_ether_ifdetach #define ether_ioctl _bsd_ether_ioctl @@ -1326,7 +1328,9 @@ #define gre_hashdestroy _bsd_gre_hashdestroy #define gre_hashinit _bsd_gre_hashinit #define gre_input _bsd_gre_input -#define gre_updatehdr _bsd_gre_updatehdr +#define gre_sofree _bsd_gre_sofree +#define gre_update_hdr _bsd_gre_update_hdr +#define gre_update_udphdr _bsd_gre_update_udphdr #define grouptask_block _bsd_grouptask_block #define grouptaskqueue_enqueue _bsd_grouptaskqueue_enqueue #define grouptask_unblock _bsd_grouptask_unblock @@ -3101,6 +3105,7 @@ #define pci_ea_is_enabled _bsd_pci_ea_is_enabled #define pcie_flr _bsd_pcie_flr #define pcie_get_max_completion_timeout _bsd_pcie_get_max_completion_timeout +#define pcie_link_reset _bsd_pcie_link_reset #define pci_enable_busmaster_method _bsd_pci_enable_busmaster_method #define pci_enable_io_method _bsd_pci_enable_io_method #define pci_enable_msi_method _bsd_pci_enable_msi_method @@ -3140,6 +3145,7 @@ #define pci_msix_table_bar_method _bsd_pci_msix_table_bar_method #define pci_numdevs _bsd_pci_numdevs #define pci_pending_msix _bsd_pci_pending_msix +#define pci_power_reset _bsd_pci_power_reset #define pci_print_child _bsd_pci_print_child #define pci_print_faulted_dev _bsd_pci_print_faulted_dev #define pci_print_verbose _bsd_pci_print_verbose @@ -4882,6 +4888,7 @@ #define tcp_recvspace _bsd_tcp_recvspace #define tcp_respond _bsd_tcp_respond #define tcp_rexmit_drop_options _bsd_tcp_rexmit_drop_options +#define tcp_rexmit_initial _bsd_tcp_rexmit_initial #define tcp_rexmit_min _bsd_tcp_rexmit_min #define tcp_rexmit_slop _bsd_tcp_rexmit_slop #define tcprexmtthresh _bsd_tcprexmtthresh @@ -4902,7 +4909,6 @@ #define tcpstat _bsd_tcpstat #define tcp_state_change _bsd_tcp_state_change #define tcp_switch_back_to_default _bsd_tcp_switch_back_to_default -#define tcp_syn_backoff _bsd_tcp_syn_backoff #define tcp_timer_2msl _bsd_tcp_timer_2msl #define tcp_timer_activate _bsd_tcp_timer_activate #define tcp_timer_active _bsd_tcp_timer_active diff --git a/rtemsbsd/include/rtems/bsd/local/bus_if.h b/rtemsbsd/include/rtems/bsd/local/bus_if.h index cc15dcad..1e54621f 100644 --- a/rtemsbsd/include/rtems/bsd/local/bus_if.h +++ b/rtemsbsd/include/rtems/bsd/local/bus_if.h @@ -1155,4 +1155,75 @@ static __inline int BUS_GET_CPUS(device_t _dev, device_t _child, return (rc); } +/** @brief Unique descriptor for the BUS_RESET_PREPARE() method */ +extern struct kobjop_desc bus_reset_prepare_desc; +/** @brief A function implementing the BUS_RESET_PREPARE() method */ +typedef int bus_reset_prepare_t(device_t _dev, device_t _child); +/** + * @brief Prepares the given child of the bus for reset + * + * Typically bus detaches or suspends children' drivers, and then + * calls this method to save bus-specific information, for instance, + * PCI config space, which is damaged by reset. + * + * The bus_helper_reset_prepare() helper is provided to ease + * implementing bus reset methods. + * + * @param _dev the bus device + * @param _child the child device + */ + +static __inline int BUS_RESET_PREPARE(device_t _dev, device_t _child) +{ + kobjop_t _m; + int rc; + KOBJOPLOOKUP(((kobj_t)_dev)->ops,bus_reset_prepare); + rc = ((bus_reset_prepare_t *) _m)(_dev, _child); + return (rc); +} + +/** @brief Unique descriptor for the BUS_RESET_POST() method */ +extern struct kobjop_desc bus_reset_post_desc; +/** @brief A function implementing the BUS_RESET_POST() method */ +typedef int bus_reset_post_t(device_t _dev, device_t _child); +/** + * @brief Restores the child operations after the reset + * + * The bus_helper_reset_post() helper is provided to ease + * implementing bus reset methods. + * + * @param _dev the bus device + * @param _child the child device + */ + +static __inline int BUS_RESET_POST(device_t _dev, device_t _child) +{ + kobjop_t _m; + int rc; + KOBJOPLOOKUP(((kobj_t)_dev)->ops,bus_reset_post); + rc = ((bus_reset_post_t *) _m)(_dev, _child); + return (rc); +} + +/** @brief Unique descriptor for the BUS_RESET_CHILD() method */ +extern struct kobjop_desc bus_reset_child_desc; +/** @brief A function implementing the BUS_RESET_CHILD() method */ +typedef int bus_reset_child_t(device_t _dev, device_t _child, int _flags); +/** + * @brief Performs reset of the child + * + * @param _dev the bus device + * @param _child the child device + * @param _flags DEVF_RESET_ flags + */ + +static __inline int BUS_RESET_CHILD(device_t _dev, device_t _child, int _flags) +{ + kobjop_t _m; + int rc; + KOBJOPLOOKUP(((kobj_t)_dev)->ops,bus_reset_child); + rc = ((bus_reset_child_t *) _m)(_dev, _child, _flags); + return (rc); +} + #endif /* _bus_if_h_ */ diff --git a/rtemsbsd/include/rtems/bsd/local/usbdevs.h b/rtemsbsd/include/rtems/bsd/local/usbdevs.h index 73904347..ce66071e 100644 --- a/rtemsbsd/include/rtems/bsd/local/usbdevs.h +++ b/rtemsbsd/include/rtems/bsd/local/usbdevs.h @@ -356,6 +356,7 @@ #define USB_VENDOR_AGFA 0x06bd /* AGFA-Gevaert */ #define USB_VENDOR_ASIAMD 0x06be /* Asia Microelectronic Development */ #define USB_VENDOR_BIZLINK 0x06c4 /* Bizlink International */ +#define USB_VENDOR_SYNAPTICS 0x06cb /* Synaptics, Inc. */ #define USB_VENDOR_KEYSPAN 0x06cd /* Keyspan / InnoSys Inc. */ #define USB_VENDOR_CONTEC 0x06ce /* Contec products */ #define USB_VENDOR_AASHIMA 0x06d6 /* Aashima Technology */ @@ -2587,6 +2588,7 @@ #define USB_PRODUCT_INTEL2_IRMH2 0x0024 /* Integrated Rate Matching Hub */ #define USB_PRODUCT_INTEL2_IRMH3 0x8000 /* Integrated Rate Matching Hub */ #define USB_PRODUCT_INTEL2_IRMH4 0x8008 /* Integrated Rate Matching Hub */ +#define USB_PRODUCT_INTEL2_SNP 0x0a2b /* Stone Peak (7265) Bluetooth Module */ #define USB_PRODUCT_INTEL2_SFP 0x0aa7 /* Sandy Peak (3168) Bluetooth Module */ #define USB_PRODUCT_INTEL2_JFP 0x0aaa /* Jefferson Peak (9460/9560) Bluetooth Module */ #define USB_PRODUCT_INTEL2_THP 0x0025 /* Thunder Peak (9160/9260) Bluetooth Module */ @@ -2679,6 +2681,9 @@ #define USB_PRODUCT_KENSINGTON_ORBIT 0x1003 /* Orbit USB/PS2 trackball */ #define USB_PRODUCT_KENSINGTON_TURBOBALL 0x1005 /* TurboBall */ +/* Synaptics products */ +#define USB_PRODUCT_SYNAPTICS_FPR9A 0x009a /* Fingerprint Reader */ + /* Keyspan products */ #define USB_PRODUCT_KEYSPAN_USA28_NF 0x0101 /* USA-28 serial Adapter (no firmware) */ #define USB_PRODUCT_KEYSPAN_USA28X_NF 0x0102 /* USA-28X serial Adapter (no firmware) */ diff --git a/rtemsbsd/include/rtems/bsd/local/usbdevs_data.h b/rtemsbsd/include/rtems/bsd/local/usbdevs_data.h index aa199490..78e9bb1b 100644 --- a/rtemsbsd/include/rtems/bsd/local/usbdevs_data.h +++ b/rtemsbsd/include/rtems/bsd/local/usbdevs_data.h @@ -8054,6 +8054,12 @@ const struct usb_knowndev usb_knowndevs[] = { "Integrated Rate Matching Hub", }, { + USB_VENDOR_INTEL2, USB_PRODUCT_INTEL2_SNP, + 0, + "Intel", + "Stone Peak (7265) Bluetooth Module", + }, + { USB_VENDOR_INTEL2, USB_PRODUCT_INTEL2_SFP, 0, "Intel", @@ -8372,6 +8378,12 @@ const struct usb_knowndev usb_knowndevs[] = { "TurboBall", }, { + USB_VENDOR_SYNAPTICS, USB_PRODUCT_SYNAPTICS_FPR9A, + 0, + "Synaptics, Inc.", + "Fingerprint Reader", + }, + { USB_VENDOR_KEYSPAN, USB_PRODUCT_KEYSPAN_USA28_NF, 0, "Keyspan / InnoSys Inc.", @@ -20792,6 +20804,12 @@ const struct usb_knowndev usb_knowndevs[] = { NULL, }, { + USB_VENDOR_SYNAPTICS, 0, + USB_KNOWNDEV_NOPROD, + "Synaptics, Inc.", + NULL, + }, + { USB_VENDOR_KEYSPAN, 0, USB_KNOWNDEV_NOPROD, "Keyspan / InnoSys Inc.", diff --git a/rtemsbsd/local/bus_if.c b/rtemsbsd/local/bus_if.c index 4b679f43..789aed0c 100644 --- a/rtemsbsd/local/bus_if.c +++ b/rtemsbsd/local/bus_if.c @@ -47,6 +47,16 @@ null_add_child(device_t bus, int order, const char *name, panic("bus_add_child is not implemented"); } +static int null_reset_post(device_t bus, device_t dev) +{ + return (0); +} + +static int null_reset_prepare(device_t bus, device_t dev) +{ + return (0); +} + struct kobjop_desc bus_print_child_desc = { 0, { &bus_print_child_desc, (kobjop_t)bus_generic_print_child } }; @@ -207,3 +217,15 @@ struct kobjop_desc bus_get_cpus_desc = { 0, { &bus_get_cpus_desc, (kobjop_t)bus_generic_get_cpus } }; +struct kobjop_desc bus_reset_prepare_desc = { + 0, { &bus_reset_prepare_desc, (kobjop_t)null_reset_prepare } +}; + +struct kobjop_desc bus_reset_post_desc = { + 0, { &bus_reset_post_desc, (kobjop_t)null_reset_post } +}; + +struct kobjop_desc bus_reset_child_desc = { + 0, { &bus_reset_child_desc, (kobjop_t)kobj_error_method } +}; + |