Update to FreeBSD stable/12 2019-06-05

Git mirror commit 78576620f2689e23144a1cf1bf55106cc6abe2b7.
This commit is contained in:
Sebastian Huber 2019-06-05 11:35:39 +02:00
parent 8f12ed3824
commit 705e362ea5
368 changed files with 34728 additions and 7606 deletions

@ -1 +1 @@
Subproject commit 43a38f188ca2e936ec78104c30ea3e24d9c1606b
Subproject commit 78576620f2689e23144a1cf1bf55106cc6abe2b7

View File

@ -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

View File

@ -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 */

View File

@ -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(&params, 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,
&params.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, &params);
}
@ -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);

View File

@ -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 */

View File

@ -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,

View File

@ -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));
}
}

View File

@ -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 */

View File

@ -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 */

View File

@ -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);

View File

@ -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 */

View File

@ -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 */

View File

@ -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

View File

@ -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

View File

@ -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 */

View File

@ -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;

View File

@ -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);

View File

@ -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,

View File

@ -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 */

View 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 */

View File

@ -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)
{

View File

@ -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);

View 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 */

View File

@ -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);
}

View File

@ -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 */

View File

@ -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));
}

View File

@ -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 */

View File

@ -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 */

View 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 */

View 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

View File

@ -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 */

View File

@ -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

View File

@ -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 */

View File

@ -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.
*

View File

@ -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);
}

View File

@ -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 */

View 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 */

View File

@ -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,

View File

@ -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 */

View File

@ -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 */

View File

@ -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;
}

View File

@ -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,

View File

@ -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",

View File

@ -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;
}

View File

@ -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 */

View 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 */

View File

@ -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);
/**

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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,
};

View 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);
}

View 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 */

View File

@ -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 */

View File

@ -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:

View File

@ -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 */

View File

@ -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
*

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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 */

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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) {

View File

@ -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);

View File

@ -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;
}

View File

@ -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;

View File

@ -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 */
}

View File

@ -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 */

View File

@ -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

View File

@ -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,

View File

@ -42,6 +42,7 @@ struct l2_ethhdr {
enum l2_packet_filter_type {
L2_PACKET_FILTER_DHCP,
L2_PACKET_FILTER_NDISC,
L2_PACKET_FILTER_PKTTYPE,
};
/**

View File

@ -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

View File

@ -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

View File

@ -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 */

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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 */

View File

@ -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)

View File

@ -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,

View File

@ -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;
}

View File

@ -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,

View File

@ -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,

View File

@ -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 */

View File

@ -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);
}

View File

@ -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 */

View 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;
}

View File

@ -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;
}

View File

@ -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