mirror of
https://git.rtems.org/rtems-libbsd/
synced 2025-06-05 19:20:24 +08:00
Update to FreeBSD stable/12 2019-06-05
Git mirror commit 78576620f2689e23144a1cf1bf55106cc6abe2b7.
This commit is contained in:
parent
8f12ed3824
commit
705e362ea5
@ -1 +1 @@
|
||||
Subproject commit 43a38f188ca2e936ec78104c30ea3e24d9c1606b
|
||||
Subproject commit 78576620f2689e23144a1cf1bf55106cc6abe2b7
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
@ -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,
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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,73 +39,99 @@ 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)
|
||||
/* 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
|
||||
|
||||
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];
|
||||
/* 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_*)
|
||||
*/
|
||||
|
||||
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];
|
||||
#define FT_RRB_NONCE_LEN 16
|
||||
|
||||
#define FT_RRB_LAST_EMPTY 0 /* placeholder or padding */
|
||||
|
||||
#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 */
|
||||
|
||||
#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;
|
||||
|
||||
#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];
|
||||
|
||||
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 ft_rrb_seq {
|
||||
le32 dom;
|
||||
le32 seq;
|
||||
le32 ts;
|
||||
} STRUCT_PACKED;
|
||||
|
||||
#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];
|
||||
|
||||
/* 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];
|
||||
} 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)
|
||||
@ -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_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);
|
||||
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_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 */
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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 */
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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 */
|
||||
|
505
freebsd/contrib/wpa/src/common/dpp.h
Normal file
505
freebsd/contrib/wpa/src/common/dpp.h
Normal file
@ -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 */
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
44
freebsd/contrib/wpa/src/common/gas_server.h
Normal file
44
freebsd/contrib/wpa/src/common/gas_server.h
Normal file
@ -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 */
|
@ -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);
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
#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 802.11-2007, 7.3.1.7, Table 7-22) */
|
||||
/* 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
|
||||
#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
|
||||
|
||||
/* Action frame categories (IEEE 802.11-2007, 7.3.1.11, Table 7-24) */
|
||||
/* 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
|
||||
#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 */
|
||||
/* 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;
|
||||
@ -677,6 +1005,16 @@ struct ieee80211_mgmt {
|
||||
* Entries (optional) */
|
||||
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[];
|
||||
@ -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 */
|
||||
|
86
freebsd/contrib/wpa/src/common/ieee802_1x_defs.h
Normal file
86
freebsd/contrib/wpa/src/common/ieee802_1x_defs.h
Normal file
@ -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 */
|
40
freebsd/contrib/wpa/src/common/ocv.h
Normal file
40
freebsd/contrib/wpa/src/common/ocv.h
Normal file
@ -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 */
|
File diff suppressed because it is too large
Load Diff
@ -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 */
|
||||
|
@ -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 */
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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 */
|
||||
/* variable length Key MIC field */
|
||||
/* big endian 2-octet Key Data Length field */
|
||||
/* 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 */
|
||||
} 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 */
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 */
|
||||
|
21
freebsd/contrib/wpa/src/crypto/aes_siv.h
Normal file
21
freebsd/contrib/wpa/src/crypto/aes_siv.h
Normal file
@ -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 */
|
@ -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,
|
||||
|
@ -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
|
||||
*
|
||||
@ -525,6 +536,14 @@ void crypto_bignum_deinit(struct crypto_bignum *n, int clear);
|
||||
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
|
||||
@ -606,6 +625,16 @@ int crypto_bignum_mulmod(const struct crypto_bignum *a,
|
||||
const struct crypto_bignum *c,
|
||||
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
|
||||
@ -636,6 +665,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
|
||||
@ -681,6 +717,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()
|
||||
@ -717,6 +760,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()
|
||||
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
||||
#ifdef CONFIG_GETRANDOM
|
||||
res = getrandom(dummy_key + dummy_key_avail,
|
||||
sizeof(dummy_key) - dummy_key_avail, GRND_NONBLOCK);
|
||||
if (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;
|
||||
}
|
||||
}
|
||||
#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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
wpa_printf(MSG_DEBUG, "random: Got %u/%u bytes from "
|
||||
"/dev/random", (unsigned) res,
|
||||
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",
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
|
27
freebsd/contrib/wpa/src/crypto/sha512.h
Normal file
27
freebsd/contrib/wpa/src/crypto/sha512.h
Normal file
@ -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 */
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
@ -247,6 +270,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()
|
||||
@ -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);
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
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);
|
||||
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__);
|
||||
if (driver_wired_init_common(&drv->common, ifname, ctx) < 0) {
|
||||
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__);
|
||||
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,
|
||||
};
|
||||
|
324
freebsd/contrib/wpa/src/drivers/driver_wired_common.c
Normal file
324
freebsd/contrib/wpa/src/drivers/driver_wired_common.c
Normal file
@ -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);
|
||||
}
|
34
freebsd/contrib/wpa/src/drivers/driver_wired_common.h
Normal file
34
freebsd/contrib/wpa/src/drivers/driver_wired_common.h
Normal file
@ -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 */
|
@ -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 */
|
||||
|
@ -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:
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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
|
||||
@ -627,6 +681,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
|
||||
*
|
||||
|
@ -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 {
|
||||
@ -205,6 +207,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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
||||
|
@ -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,
|
||||
|
@ -42,6 +42,7 @@ struct l2_ethhdr {
|
||||
enum l2_packet_filter_type {
|
||||
L2_PACKET_FILTER_DHCP,
|
||||
L2_PACKET_FILTER_NDISC,
|
||||
L2_PACKET_FILTER_PKTTYPE,
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -103,6 +103,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
|
||||
*/
|
||||
@ -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
|
||||
|
@ -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
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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 */
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
@ -103,10 +118,24 @@ static inline int pmksa_cache_list(struct rsn_pmksa_cache *pmksa, char *buf,
|
||||
return -1;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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 */
|
||||
|
@ -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 (sm->mgmt_group_cipher != WPA_CIPHER_AES_128_CMAC)
|
||||
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 &&
|
||||
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)
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 */
|
||||
|
91
freebsd/contrib/wpa/src/utils/bitfield.c
Normal file
91
freebsd/contrib/wpa/src/utils/bitfield.c
Normal file
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user