mirror of
https://github.com/espressif/esp-idf.git
synced 2025-09-09 16:38:10 +00:00
supplicant/esp_wifi: move supplicant to idf
Move supplicant to idf and do following refactoring: 1. Make the folder structure consitent with supplicant upstream 2. Remove duplicated header files and minimize the public header files 3. Refactor for WiFi/supplicant interfaces
This commit is contained in:
248
components/wpa_supplicant/src/ap/ap_config.c
Normal file
248
components/wpa_supplicant/src/ap/ap_config.c
Normal file
@@ -0,0 +1,248 @@
|
||||
/*
|
||||
* hostapd / Configuration helper functions
|
||||
* Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
|
||||
#include "utils/common.h"
|
||||
#include "crypto/sha1.h"
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "common/eapol_common.h"
|
||||
#include "ap/wpa_auth.h"
|
||||
#include "ap/ap_config.h"
|
||||
#include "utils/wpa_debug.h"
|
||||
#include "ap/hostapd.h"
|
||||
#include "ap/wpa_auth_i.h"
|
||||
#include "esp_supplicant/esp_wifi_driver.h"
|
||||
#include "esp_wifi_types.h"
|
||||
|
||||
void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
|
||||
{
|
||||
bss->auth_algs = WPA_AUTH_ALG_OPEN | WPA_AUTH_ALG_SHARED;
|
||||
|
||||
bss->wep_rekeying_period = 300;
|
||||
/* use key0 in individual key and key1 in broadcast key */
|
||||
bss->broadcast_key_idx_min = 1;
|
||||
bss->broadcast_key_idx_max = 2;
|
||||
|
||||
bss->wpa_group_rekey = 600;
|
||||
bss->wpa_gmk_rekey = 86400;
|
||||
bss->wpa_key_mgmt = WPA_KEY_MGMT_PSK;
|
||||
bss->wpa_pairwise = WPA_CIPHER_TKIP;
|
||||
bss->wpa_group = WPA_CIPHER_TKIP;
|
||||
bss->rsn_pairwise = 0;
|
||||
|
||||
bss->max_num_sta = MAX_STA_COUNT;
|
||||
|
||||
bss->dtim_period = 2;
|
||||
|
||||
bss->ap_max_inactivity = 5*60; //AP_MAX_INACTIVITY;
|
||||
bss->eapol_version = EAPOL_VERSION;
|
||||
|
||||
bss->max_listen_interval = 65535;
|
||||
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
bss->assoc_sa_query_max_timeout = 1000;
|
||||
bss->assoc_sa_query_retry_timeout = 201;
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
#ifdef EAP_SERVER_FAST
|
||||
/* both anonymous and authenticated provisioning */
|
||||
bss->eap_fast_prov = 3;
|
||||
bss->pac_key_lifetime = 7 * 24 * 60 * 60;
|
||||
bss->pac_key_refresh_time = 1 * 24 * 60 * 60;
|
||||
#endif /* EAP_SERVER_FAST */
|
||||
|
||||
/* Set to -1 as defaults depends on HT in setup */
|
||||
bss->wmm_enabled = -1;
|
||||
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
bss->ft_over_ds = 1;
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
|
||||
}
|
||||
|
||||
|
||||
struct hostapd_config * hostapd_config_defaults(void)
|
||||
{
|
||||
#define ecw2cw(ecw) ((1 << (ecw)) - 1)
|
||||
|
||||
struct hostapd_config *conf;
|
||||
struct hostapd_bss_config *bss;
|
||||
#undef ecw2cw
|
||||
|
||||
conf = (struct hostapd_config *)os_zalloc(sizeof(*conf));
|
||||
bss = (struct hostapd_bss_config *)os_zalloc(sizeof(*bss));
|
||||
if (conf == NULL || bss == NULL) {
|
||||
wpa_printf(MSG_DEBUG, "Failed to allocate memory for "
|
||||
"configuration data.");
|
||||
os_free(conf);
|
||||
os_free(bss);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
hostapd_config_defaults_bss(bss);
|
||||
|
||||
conf->num_bss = 1;
|
||||
conf->bss = bss;
|
||||
|
||||
conf->beacon_int = 100;
|
||||
conf->rts_threshold = -1; /* use driver default: 2347 */
|
||||
conf->fragm_threshold = -1; /* user driver default: 2346 */
|
||||
conf->send_probe_response = 1;
|
||||
|
||||
conf->ht_capab = HT_CAP_INFO_SMPS_DISABLED;
|
||||
|
||||
conf->ap_table_max_size = 255;
|
||||
conf->ap_table_expiration_time = 60;
|
||||
|
||||
return conf;
|
||||
}
|
||||
|
||||
|
||||
int hostapd_mac_comp(const void *a, const void *b)
|
||||
{
|
||||
return memcmp(a, b, sizeof(macaddr));
|
||||
}
|
||||
|
||||
|
||||
int hostapd_mac_comp_empty(const void *a)
|
||||
{
|
||||
u8 empty[ETH_ALEN];
|
||||
|
||||
os_bzero(empty, ETH_ALEN);
|
||||
|
||||
return memcmp(a, empty, ETH_ALEN);
|
||||
}
|
||||
|
||||
static int hostapd_derive_psk(struct hostapd_ssid *ssid)
|
||||
{
|
||||
ssid->wpa_psk = (struct hostapd_wpa_psk *)os_zalloc(sizeof(struct hostapd_wpa_psk));
|
||||
if (ssid->wpa_psk == NULL) {
|
||||
wpa_printf(MSG_ERROR, "Unable to alloc space for PSK");
|
||||
return -1;
|
||||
}
|
||||
wpa_hexdump_ascii(MSG_DEBUG, "SSID",
|
||||
(u8 *) ssid->ssid, ssid->ssid_len);
|
||||
wpa_hexdump_ascii_key(MSG_DEBUG, "PSK (ASCII passphrase)",
|
||||
(u8 *) ssid->wpa_passphrase,
|
||||
strlen(ssid->wpa_passphrase));
|
||||
#ifdef ESP_SUPPLICANT
|
||||
memcpy(ssid->wpa_psk->psk, esp_wifi_ap_get_prof_pmk_internal(), PMK_LEN);
|
||||
#else
|
||||
/* It's too SLOW */
|
||||
pbkdf2_sha1(ssid->wpa_passphrase,
|
||||
ssid->ssid, ssid->ssid_len,
|
||||
4096, ssid->wpa_psk->psk, PMK_LEN);
|
||||
#endif
|
||||
wpa_hexdump_key(MSG_DEBUG, "PSK (from passphrase)",
|
||||
ssid->wpa_psk->psk, PMK_LEN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int hostapd_setup_wpa_psk(struct hostapd_bss_config *conf)
|
||||
{
|
||||
struct hostapd_ssid *ssid = &conf->ssid;
|
||||
|
||||
if (ssid->wpa_passphrase != NULL) {
|
||||
if (ssid->wpa_psk != NULL) {
|
||||
wpa_printf(MSG_DEBUG, "Using pre-configured WPA PSK "
|
||||
"instead of passphrase");
|
||||
} else {
|
||||
wpa_printf(MSG_DEBUG, "Deriving WPA PSK based on "
|
||||
"passphrase\n");
|
||||
if (hostapd_derive_psk(ssid) < 0)
|
||||
return -1;
|
||||
}
|
||||
ssid->wpa_psk->group = 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int hostapd_wep_key_cmp(struct hostapd_wep_keys *a, struct hostapd_wep_keys *b)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (a->idx != b->idx || a->default_len != b->default_len)
|
||||
return 1;
|
||||
for (i = 0; i < NUM_WEP_KEYS; i++)
|
||||
if (a->len[i] != b->len[i] ||
|
||||
memcmp(a->key[i], b->key[i], a->len[i]) != 0)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* hostapd_maclist_found - Find a MAC address from a list
|
||||
* @list: MAC address list
|
||||
* @num_entries: Number of addresses in the list
|
||||
* @addr: Address to search for
|
||||
* @vlan_id: Buffer for returning VLAN ID or %NULL if not needed
|
||||
* Returns: 1 if address is in the list or 0 if not.
|
||||
*
|
||||
* Perform a binary search for given MAC address from a pre-sorted list.
|
||||
*/
|
||||
int hostapd_maclist_found(struct mac_acl_entry *list, int num_entries,
|
||||
const u8 *addr, int *vlan_id)
|
||||
{
|
||||
int start, end, middle, res;
|
||||
|
||||
start = 0;
|
||||
end = num_entries - 1;
|
||||
|
||||
while (start <= end) {
|
||||
middle = (start + end) / 2;
|
||||
res = memcmp(list[middle].addr, addr, ETH_ALEN);
|
||||
if (res == 0) {
|
||||
if (vlan_id)
|
||||
*vlan_id = list[middle].vlan_id;
|
||||
return 1;
|
||||
}
|
||||
if (res < 0)
|
||||
start = middle + 1;
|
||||
else
|
||||
end = middle - 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int hostapd_rate_found(int *list, int rate)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (list == NULL)
|
||||
return 0;
|
||||
|
||||
for (i = 0; list[i] >= 0; i++)
|
||||
if (list[i] == rate)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf,
|
||||
const u8 *addr, const u8 *prev_psk)
|
||||
{
|
||||
struct hostapd_wpa_psk *psk;
|
||||
int next_ok = prev_psk == NULL;
|
||||
|
||||
for (psk = conf->ssid.wpa_psk; psk != NULL; psk = psk->next) {
|
||||
if (next_ok &&
|
||||
(psk->group || memcmp(psk->addr, addr, ETH_ALEN) == 0))
|
||||
return psk->psk;
|
||||
|
||||
if (psk->psk == prev_psk)
|
||||
next_ok = 1;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
375
components/wpa_supplicant/src/ap/ap_config.h
Normal file
375
components/wpa_supplicant/src/ap/ap_config.h
Normal file
@@ -0,0 +1,375 @@
|
||||
/*
|
||||
* hostapd / Configuration definitions and helpers functions
|
||||
* Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef HOSTAPD_CONFIG_H
|
||||
#define HOSTAPD_CONFIG_H
|
||||
|
||||
#include "common/defs.h"
|
||||
#include "common/wpa_common.h"
|
||||
|
||||
#define MAX_STA_COUNT 4
|
||||
#define MAX_VLAN_ID 4094
|
||||
|
||||
typedef u8 macaddr[ETH_ALEN];
|
||||
|
||||
struct mac_acl_entry {
|
||||
macaddr addr;
|
||||
int vlan_id;
|
||||
};
|
||||
|
||||
struct hostapd_radius_servers;
|
||||
struct ft_remote_r0kh;
|
||||
struct ft_remote_r1kh;
|
||||
|
||||
#define HOSTAPD_MAX_SSID_LEN 32
|
||||
|
||||
#define NUM_WEP_KEYS 4
|
||||
struct hostapd_wep_keys {
|
||||
u8 idx;
|
||||
u8 *key[NUM_WEP_KEYS];
|
||||
size_t len[NUM_WEP_KEYS];
|
||||
int keys_set;
|
||||
size_t default_len; /* key length used for dynamic key generation */
|
||||
};
|
||||
|
||||
typedef enum hostap_security_policy {
|
||||
SECURITY_PLAINTEXT = 0,
|
||||
SECURITY_STATIC_WEP = 1,
|
||||
SECURITY_IEEE_802_1X = 2,
|
||||
SECURITY_WPA_PSK = 3,
|
||||
SECURITY_WPA = 4
|
||||
} secpolicy;
|
||||
|
||||
struct hostapd_ssid {
|
||||
u8 ssid[HOSTAPD_MAX_SSID_LEN];
|
||||
size_t ssid_len;
|
||||
unsigned int ssid_set:1;
|
||||
unsigned int utf8_ssid:1;
|
||||
|
||||
struct hostapd_wpa_psk *wpa_psk;
|
||||
char *wpa_passphrase;
|
||||
|
||||
struct hostapd_wep_keys wep;
|
||||
|
||||
#if 0
|
||||
#define DYNAMIC_VLAN_DISABLED 0
|
||||
#define DYNAMIC_VLAN_OPTIONAL 1
|
||||
#define DYNAMIC_VLAN_REQUIRED 2
|
||||
int dynamic_vlan;
|
||||
#define DYNAMIC_VLAN_NAMING_WITHOUT_DEVICE 0
|
||||
#define DYNAMIC_VLAN_NAMING_WITH_DEVICE 1
|
||||
#define DYNAMIC_VLAN_NAMING_END 2
|
||||
int vlan_naming;
|
||||
#ifdef CONFIG_FULL_DYNAMIC_VLAN
|
||||
char *vlan_tagged_interface;
|
||||
#endif /* CONFIG_FULL_DYNAMIC_VLAN */
|
||||
struct hostapd_wep_keys **dyn_vlan_keys;
|
||||
size_t max_dyn_vlan_keys;
|
||||
#endif
|
||||
};
|
||||
|
||||
#if 0
|
||||
#define VLAN_ID_WILDCARD -1
|
||||
|
||||
struct hostapd_vlan {
|
||||
struct hostapd_vlan *next;
|
||||
int vlan_id; /* VLAN ID or -1 (VLAN_ID_WILDCARD) for wildcard entry */
|
||||
char ifname[IFNAMSIZ + 1];
|
||||
int dynamic_vlan;
|
||||
#ifdef CONFIG_FULL_DYNAMIC_VLAN
|
||||
|
||||
#define DVLAN_CLEAN_BR 0x1
|
||||
#define DVLAN_CLEAN_VLAN 0x2
|
||||
#define DVLAN_CLEAN_VLAN_PORT 0x4
|
||||
#define DVLAN_CLEAN_WLAN_PORT 0x8
|
||||
int clean;
|
||||
#endif /* CONFIG_FULL_DYNAMIC_VLAN */
|
||||
};
|
||||
#endif
|
||||
|
||||
#define PMK_LEN 32
|
||||
struct hostapd_sta_wpa_psk_short {
|
||||
struct hostapd_sta_wpa_psk_short *next;
|
||||
u8 psk[PMK_LEN];
|
||||
};
|
||||
|
||||
struct hostapd_wpa_psk {
|
||||
struct hostapd_wpa_psk *next;
|
||||
int group;
|
||||
u8 psk[PMK_LEN];
|
||||
u8 addr[ETH_ALEN];
|
||||
};
|
||||
|
||||
#if 0
|
||||
struct hostapd_eap_user {
|
||||
struct hostapd_eap_user *next;
|
||||
u8 *identity;
|
||||
size_t identity_len;
|
||||
struct {
|
||||
int vendor;
|
||||
u32 method;
|
||||
} methods[EAP_MAX_METHODS];
|
||||
u8 *password;
|
||||
size_t password_len;
|
||||
int phase2;
|
||||
int force_version;
|
||||
unsigned int wildcard_prefix:1;
|
||||
unsigned int password_hash:1; /* whether password is hashed with
|
||||
* nt_password_hash() */
|
||||
int ttls_auth; /* EAP_TTLS_AUTH_* bitfield */
|
||||
};
|
||||
|
||||
struct hostapd_radius_attr {
|
||||
u8 type;
|
||||
struct wpabuf *val;
|
||||
struct hostapd_radius_attr *next;
|
||||
};
|
||||
|
||||
|
||||
#define NUM_TX_QUEUES 4
|
||||
|
||||
struct hostapd_tx_queue_params {
|
||||
int aifs;
|
||||
int cwmin;
|
||||
int cwmax;
|
||||
int burst; /* maximum burst time in 0.1 ms, i.e., 10 = 1 ms */
|
||||
};
|
||||
|
||||
|
||||
#define MAX_ROAMING_CONSORTIUM_LEN 15
|
||||
|
||||
struct hostapd_roaming_consortium {
|
||||
u8 len;
|
||||
u8 oi[MAX_ROAMING_CONSORTIUM_LEN];
|
||||
};
|
||||
|
||||
struct hostapd_lang_string {
|
||||
u8 lang[3];
|
||||
u8 name_len;
|
||||
u8 name[252];
|
||||
};
|
||||
|
||||
#define MAX_NAI_REALMS 10
|
||||
#define MAX_NAI_REALMLEN 255
|
||||
#define MAX_NAI_EAP_METHODS 5
|
||||
#define MAX_NAI_AUTH_TYPES 4
|
||||
struct hostapd_nai_realm_data {
|
||||
u8 encoding;
|
||||
char realm_buf[MAX_NAI_REALMLEN + 1];
|
||||
char *realm[MAX_NAI_REALMS];
|
||||
u8 eap_method_count;
|
||||
struct hostapd_nai_realm_eap {
|
||||
u8 eap_method;
|
||||
u8 num_auths;
|
||||
u8 auth_id[MAX_NAI_AUTH_TYPES];
|
||||
u8 auth_val[MAX_NAI_AUTH_TYPES];
|
||||
} eap_method[MAX_NAI_EAP_METHODS];
|
||||
};
|
||||
#endif
|
||||
|
||||
/**
|
||||
* struct hostapd_bss_config - Per-BSS configuration
|
||||
*/
|
||||
struct hostapd_bss_config {
|
||||
int max_num_sta; /* maximum number of STAs in station table */
|
||||
|
||||
int dtim_period;
|
||||
|
||||
int ieee802_1x; /* use IEEE 802.1X */
|
||||
int eapol_version;
|
||||
struct hostapd_ssid ssid;
|
||||
|
||||
int wep_rekeying_period;
|
||||
int broadcast_key_idx_min, broadcast_key_idx_max;
|
||||
|
||||
enum {
|
||||
ACCEPT_UNLESS_DENIED = 0,
|
||||
DENY_UNLESS_ACCEPTED = 1,
|
||||
USE_EXTERNAL_RADIUS_AUTH = 2
|
||||
} macaddr_acl;
|
||||
|
||||
int auth_algs; /* bitfield of allowed IEEE 802.11 authentication
|
||||
* algorithms, WPA_AUTH_ALG_{OPEN,SHARED,LEAP} */
|
||||
|
||||
int wpa; /* bitfield of WPA_PROTO_WPA, WPA_PROTO_RSN */
|
||||
int wpa_key_mgmt;
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
enum mfp_options ieee80211w;
|
||||
/* dot11AssociationSAQueryMaximumTimeout (in TUs) */
|
||||
unsigned int assoc_sa_query_max_timeout;
|
||||
/* dot11AssociationSAQueryRetryTimeout (in TUs) */
|
||||
int assoc_sa_query_retry_timeout;
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
enum {
|
||||
PSK_RADIUS_IGNORED = 0,
|
||||
PSK_RADIUS_ACCEPTED = 1,
|
||||
PSK_RADIUS_REQUIRED = 2
|
||||
} wpa_psk_radius;
|
||||
int wpa_pairwise;
|
||||
int wpa_group;
|
||||
int wpa_group_rekey;
|
||||
int wpa_strict_rekey;
|
||||
int wpa_gmk_rekey;
|
||||
int wpa_ptk_rekey;
|
||||
int rsn_pairwise;
|
||||
int rsn_preauth;
|
||||
char *rsn_preauth_interfaces;
|
||||
int peerkey;
|
||||
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
/* 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 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 ap_max_inactivity;
|
||||
int ignore_broadcast_ssid;
|
||||
|
||||
int wmm_enabled;
|
||||
int wmm_uapsd;
|
||||
|
||||
macaddr bssid;
|
||||
|
||||
/*
|
||||
* Maximum listen interval that STAs can use when associating with this
|
||||
* BSS. If a STA tries to use larger value, the association will be
|
||||
* denied with status code 51.
|
||||
*/
|
||||
u16 max_listen_interval;
|
||||
|
||||
#ifdef CONFIG_WPS
|
||||
int ap_setup_locked;
|
||||
u8 uuid[16];
|
||||
char *wps_pin_requests;
|
||||
char *device_name;
|
||||
char *manufacturer;
|
||||
char *model_name;
|
||||
char *model_number;
|
||||
char *serial_number;
|
||||
u8 device_type[WPS_DEV_TYPE_LEN];
|
||||
char *config_methods;
|
||||
u8 os_version[4];
|
||||
char *ap_pin;
|
||||
int skip_cred_build;
|
||||
u8 *extra_cred;
|
||||
size_t extra_cred_len;
|
||||
int wps_cred_processing;
|
||||
u8 *ap_settings;
|
||||
size_t ap_settings_len;
|
||||
char *upnp_iface;
|
||||
char *friendly_name;
|
||||
char *manufacturer_url;
|
||||
char *model_description;
|
||||
char *model_url;
|
||||
char *upc;
|
||||
struct wpabuf *wps_vendor_ext[MAX_WPS_VENDOR_EXTENSIONS];
|
||||
int wps_nfc_dev_pw_id;
|
||||
struct wpabuf *wps_nfc_dh_pubkey;
|
||||
struct wpabuf *wps_nfc_dh_privkey;
|
||||
struct wpabuf *wps_nfc_dev_pw;
|
||||
#endif /* CONFIG_WPS */
|
||||
|
||||
#ifdef CONFIG_HS20
|
||||
int hs20;
|
||||
int disable_dgaf;
|
||||
unsigned int hs20_oper_friendly_name_count;
|
||||
struct hostapd_lang_string *hs20_oper_friendly_name;
|
||||
u8 *hs20_wan_metrics;
|
||||
u8 *hs20_connection_capability;
|
||||
size_t hs20_connection_capability_len;
|
||||
u8 *hs20_operating_class;
|
||||
u8 hs20_operating_class_len;
|
||||
#endif /* CONFIG_HS20 */
|
||||
|
||||
#ifdef CONFIG_RADIUS_TEST
|
||||
char *dump_msk_file;
|
||||
#endif /* CONFIG_RADIUS_TEST */
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* struct hostapd_config - Per-radio interface configuration
|
||||
*/
|
||||
struct hostapd_config {
|
||||
struct hostapd_bss_config *bss, *last_bss;
|
||||
size_t num_bss;
|
||||
|
||||
u16 beacon_int;
|
||||
int rts_threshold;
|
||||
int fragm_threshold;
|
||||
u8 send_probe_response;
|
||||
u8 channel;
|
||||
enum hostapd_hw_mode hw_mode; /* HOSTAPD_MODE_IEEE80211A, .. */
|
||||
enum {
|
||||
LONG_PREAMBLE = 0,
|
||||
SHORT_PREAMBLE = 1
|
||||
} preamble;
|
||||
|
||||
int *supported_rates;
|
||||
int *basic_rates;
|
||||
|
||||
const struct wpa_driver_ops *driver;
|
||||
|
||||
int ap_table_max_size;
|
||||
int ap_table_expiration_time;
|
||||
|
||||
char country[3]; /* first two octets: country code as described in
|
||||
* ISO/IEC 3166-1. Third octet:
|
||||
* ' ' (ascii 32): all environments
|
||||
* 'O': Outdoor environemnt only
|
||||
* 'I': Indoor environment only
|
||||
*/
|
||||
|
||||
int ieee80211d;
|
||||
|
||||
/*
|
||||
* WMM AC parameters, in same order as 802.1D, i.e.
|
||||
* 0 = BE (best effort)
|
||||
* 1 = BK (background)
|
||||
* 2 = VI (video)
|
||||
* 3 = VO (voice)
|
||||
*/
|
||||
|
||||
int ht_op_mode_fixed;
|
||||
u16 ht_capab;
|
||||
int ieee80211n;
|
||||
int secondary_channel;
|
||||
int require_ht;
|
||||
u32 vht_capab;
|
||||
int ieee80211ac;
|
||||
int require_vht;
|
||||
u8 vht_oper_chwidth;
|
||||
u8 vht_oper_centr_freq_seg0_idx;
|
||||
u8 vht_oper_centr_freq_seg1_idx;
|
||||
};
|
||||
|
||||
|
||||
int hostapd_mac_comp(const void *a, const void *b);
|
||||
int hostapd_mac_comp_empty(const void *a);
|
||||
struct hostapd_config * hostapd_config_defaults(void);
|
||||
void hostapd_config_defaults_bss(struct hostapd_bss_config *bss);
|
||||
void hostapd_config_free(struct hostapd_config *conf);
|
||||
int hostapd_maclist_found(struct mac_acl_entry *list, int num_entries,
|
||||
const u8 *addr, int *vlan_id);
|
||||
int hostapd_rate_found(int *list, int rate);
|
||||
int hostapd_wep_key_cmp(struct hostapd_wep_keys *a,
|
||||
struct hostapd_wep_keys *b);
|
||||
const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf,
|
||||
const u8 *addr, const u8 *prev_psk);
|
||||
int hostapd_setup_wpa_psk(struct hostapd_bss_config *conf);
|
||||
bool wpa_ap_join(void** sm, uint8_t *bssid, uint8_t *wpa_ie, uint8_t wpa_ie_len);
|
||||
bool wpa_ap_remove(void* sm);
|
||||
|
||||
#endif /* HOSTAPD_CONFIG_H */
|
115
components/wpa_supplicant/src/ap/hostapd.h
Normal file
115
components/wpa_supplicant/src/ap/hostapd.h
Normal file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* hostapd / Initialization and configuration
|
||||
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef HOSTAPD_H
|
||||
#define HOSTAPD_H
|
||||
|
||||
#include "common/defs.h"
|
||||
#include "ap/ap_config.h"
|
||||
|
||||
struct wpa_driver_ops;
|
||||
struct wpa_ctrl_dst;
|
||||
struct radius_server_data;
|
||||
struct upnp_wps_device_sm;
|
||||
struct hostapd_data;
|
||||
struct sta_info;
|
||||
struct hostap_sta_driver_data;
|
||||
struct ieee80211_ht_capabilities;
|
||||
struct full_dynamic_vlan;
|
||||
enum wps_event;
|
||||
union wps_event_data;
|
||||
|
||||
struct hostapd_iface;
|
||||
|
||||
struct hapd_interfaces {
|
||||
int (*reload_config)(struct hostapd_iface *iface);
|
||||
struct hostapd_config * (*config_read_cb)(const char *config_fname);
|
||||
int (*ctrl_iface_init)(struct hostapd_data *hapd);
|
||||
void (*ctrl_iface_deinit)(struct hostapd_data *hapd);
|
||||
int (*for_each_interface)(struct hapd_interfaces *interfaces,
|
||||
int (*cb)(struct hostapd_iface *iface,
|
||||
void *ctx), void *ctx);
|
||||
int (*driver_init)(struct hostapd_iface *iface);
|
||||
|
||||
size_t count;
|
||||
int global_ctrl_sock;
|
||||
char *global_iface_path;
|
||||
char *global_iface_name;
|
||||
struct hostapd_iface **iface;
|
||||
};
|
||||
|
||||
|
||||
struct hostapd_probereq_cb {
|
||||
int (*cb)(void *ctx, const u8 *sa, const u8 *da, const u8 *bssid,
|
||||
const u8 *ie, size_t ie_len, int ssi_signal);
|
||||
void *ctx;
|
||||
};
|
||||
|
||||
#define HOSTAPD_RATE_BASIC 0x00000001
|
||||
|
||||
struct hostapd_rate_data {
|
||||
int rate; /* rate in 100 kbps */
|
||||
int flags; /* HOSTAPD_RATE_ flags */
|
||||
};
|
||||
|
||||
struct hostapd_frame_info {
|
||||
u32 channel;
|
||||
u32 datarate;
|
||||
int ssi_signal; /* dBm */
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* struct hostapd_data - hostapd per-BSS data structure
|
||||
*/
|
||||
struct hostapd_data {
|
||||
struct hostapd_config *iconf;
|
||||
struct hostapd_bss_config *conf;
|
||||
int interface_added; /* virtual interface added for this BSS */
|
||||
|
||||
u8 own_addr[ETH_ALEN];
|
||||
|
||||
int num_sta; /* number of entries in sta_list */
|
||||
|
||||
struct wpa_authenticator *wpa_auth;
|
||||
|
||||
#ifdef CONFIG_FULL_DYNAMIC_VLAN
|
||||
struct full_dynamic_vlan *full_dynamic_vlan;
|
||||
#endif /* CONFIG_FULL_DYNAMIC_VLAN */
|
||||
|
||||
#ifdef CONFIG_WPS
|
||||
unsigned int ap_pin_failures;
|
||||
unsigned int ap_pin_failures_consecutive;
|
||||
struct upnp_wps_device_sm *wps_upnp;
|
||||
unsigned int ap_pin_lockout_time;
|
||||
#endif /* CONFIG_WPS */
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
struct p2p_data *p2p;
|
||||
struct p2p_group *p2p_group;
|
||||
struct wpabuf *p2p_beacon_ie;
|
||||
struct wpabuf *p2p_probe_resp_ie;
|
||||
|
||||
/* Number of non-P2P association stations */
|
||||
int num_sta_no_p2p;
|
||||
|
||||
/* Periodic NoA (used only when no non-P2P clients in the group) */
|
||||
int noa_enabled;
|
||||
int noa_start;
|
||||
int noa_duration;
|
||||
#endif /* CONFIG_P2P */
|
||||
#ifdef CONFIG_INTERWORKING
|
||||
size_t gas_frag_limit;
|
||||
#endif /* CONFIG_INTERWORKING */
|
||||
|
||||
#ifdef CONFIG_SQLITE
|
||||
struct hostapd_eap_user tmp_eap_user;
|
||||
#endif /* CONFIG_SQLITE */
|
||||
};
|
||||
|
||||
#endif /* HOSTAPD_H */
|
78
components/wpa_supplicant/src/ap/ieee802_1x.c
Normal file
78
components/wpa_supplicant/src/ap/ieee802_1x.c
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* hostapd / IEEE 802.1X-2004 Authenticator
|
||||
* Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
|
||||
#include "utils/common.h"
|
||||
#include "crypto/crypto.h"
|
||||
#include "crypto/random.h"
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "hostapd.h"
|
||||
#include "ap/sta_info.h"
|
||||
#include "ap/wpa_auth.h"
|
||||
#include "ap/ap_config.h"
|
||||
#include "ap/ieee802_1x.h"
|
||||
#include "utils/wpa_debug.h"
|
||||
|
||||
/**
|
||||
* ieee802_1x_receive - Process the EAPOL frames from the Supplicant
|
||||
* @hapd: hostapd BSS data
|
||||
* @sa: Source address (sender of the EAPOL frame)
|
||||
* @buf: EAPOL frame
|
||||
* @len: Length of buf in octets
|
||||
*
|
||||
* This function is called for each incoming EAPOL frame from the interface
|
||||
*/
|
||||
void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
|
||||
size_t len)
|
||||
{
|
||||
struct sta_info *sta;
|
||||
struct ieee802_1x_hdr *hdr;
|
||||
struct ieee802_1x_eapol_key *key;
|
||||
u16 datalen;
|
||||
|
||||
wpa_printf( MSG_DEBUG, "IEEE 802.1X: %lu bytes from " MACSTR,
|
||||
(unsigned long) len, MAC2STR(sa));
|
||||
sta = ap_get_sta(hapd, sa);
|
||||
if (!sta || !(sta->flags & (WLAN_STA_ASSOC | WLAN_STA_PREAUTH))) {
|
||||
wpa_printf( MSG_DEBUG, "IEEE 802.1X data frame from not "
|
||||
"associated/Pre-authenticating STA");
|
||||
return;
|
||||
}
|
||||
|
||||
if (len < sizeof(*hdr)) {
|
||||
wpa_printf( MSG_DEBUG, " too short IEEE 802.1X packet\n");
|
||||
return;
|
||||
}
|
||||
|
||||
hdr = (struct ieee802_1x_hdr *) buf;
|
||||
datalen = be_to_host16(hdr->length);
|
||||
wpa_printf( MSG_DEBUG, " IEEE 802.1X: version=%d type=%d length=%d",
|
||||
hdr->version, hdr->type, datalen);
|
||||
|
||||
if (len - sizeof(*hdr) < datalen) {
|
||||
wpa_printf( MSG_DEBUG, " frame too short for this IEEE 802.1X packet\n");
|
||||
return;
|
||||
}
|
||||
if (len - sizeof(*hdr) > datalen) {
|
||||
wpa_printf( MSG_DEBUG, " ignoring %lu extra octets after "
|
||||
"IEEE 802.1X packet",
|
||||
(unsigned long) len - sizeof(*hdr) - datalen);
|
||||
}
|
||||
|
||||
key = (struct ieee802_1x_eapol_key *) (hdr + 1);
|
||||
if (datalen >= sizeof(struct ieee802_1x_eapol_key) &&
|
||||
hdr->type == IEEE802_1X_TYPE_EAPOL_KEY &&
|
||||
(key->type == EAPOL_KEY_TYPE_WPA ||
|
||||
key->type == EAPOL_KEY_TYPE_RSN)) {
|
||||
wpa_receive(hapd->wpa_auth, sta->wpa_sm, (u8 *) hdr,
|
||||
sizeof(*hdr) + datalen);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
24
components/wpa_supplicant/src/ap/ieee802_1x.h
Normal file
24
components/wpa_supplicant/src/ap/ieee802_1x.h
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* hostapd / IEEE 802.1X-2004 Authenticator
|
||||
* Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef IEEE802_1X_H
|
||||
#define IEEE802_1X_H
|
||||
|
||||
struct hostapd_data;
|
||||
struct sta_info;
|
||||
struct eapol_state_machine;
|
||||
struct hostapd_config;
|
||||
struct hostapd_bss_config;
|
||||
struct hostapd_radius_attr;
|
||||
struct radius_msg;
|
||||
|
||||
|
||||
void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
|
||||
size_t len);
|
||||
|
||||
#endif /* IEEE802_1X_H */
|
141
components/wpa_supplicant/src/ap/sta_info.h
Normal file
141
components/wpa_supplicant/src/ap/sta_info.h
Normal file
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* hostapd / Station table
|
||||
* Copyright (c) 2002-2011, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef STA_INFO_H
|
||||
#define STA_INFO_H
|
||||
|
||||
/* STA flags */
|
||||
#define WLAN_STA_AUTH BIT(0)
|
||||
#define WLAN_STA_ASSOC BIT(1)
|
||||
#define WLAN_STA_PS BIT(2)
|
||||
#define WLAN_STA_TIM BIT(3)
|
||||
#define WLAN_STA_PERM BIT(4)
|
||||
#define WLAN_STA_AUTHORIZED BIT(5)
|
||||
#define WLAN_STA_PENDING_POLL BIT(6) /* pending activity poll not ACKed */
|
||||
#define WLAN_STA_SHORT_PREAMBLE BIT(7)
|
||||
#define WLAN_STA_PREAUTH BIT(8)
|
||||
#define WLAN_STA_WMM BIT(9)
|
||||
#define WLAN_STA_MFP BIT(10)
|
||||
#define WLAN_STA_HT BIT(11)
|
||||
#define WLAN_STA_WPS BIT(12)
|
||||
#define WLAN_STA_MAYBE_WPS BIT(13)
|
||||
#define WLAN_STA_WDS BIT(14)
|
||||
#define WLAN_STA_ASSOC_REQ_OK BIT(15)
|
||||
#define WLAN_STA_WPS2 BIT(16)
|
||||
#define WLAN_STA_GAS BIT(17)
|
||||
#define WLAN_STA_VHT BIT(18)
|
||||
#define WLAN_STA_PENDING_DISASSOC_CB BIT(29)
|
||||
#define WLAN_STA_PENDING_DEAUTH_CB BIT(30)
|
||||
#define WLAN_STA_NONERP BIT(31)
|
||||
|
||||
/* Maximum number of supported rates (from both Supported Rates and Extended
|
||||
* Supported Rates IEs). */
|
||||
#define WLAN_SUPP_RATES_MAX 32
|
||||
|
||||
|
||||
struct sta_info {
|
||||
struct sta_info *next; /* next entry in sta list */
|
||||
struct sta_info *hnext; /* next entry in hash table list */
|
||||
u8 addr[6];
|
||||
u16 aid; /* STA's unique AID (1 .. 2007) or 0 if not yet assigned */
|
||||
u32 flags; /* Bitfield of WLAN_STA_* */
|
||||
u16 capability;
|
||||
u16 listen_interval; /* or beacon_int for APs */
|
||||
u8 supported_rates[WLAN_SUPP_RATES_MAX];
|
||||
int supported_rates_len;
|
||||
|
||||
u16 auth_alg;
|
||||
|
||||
enum {
|
||||
STA_NULLFUNC = 0, STA_DISASSOC, STA_DEAUTH, STA_REMOVE
|
||||
} timeout_next;
|
||||
|
||||
struct wpa_state_machine *wpa_sm;
|
||||
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
int sa_query_count; /* number of pending SA Query requests;
|
||||
* 0 = no SA Query in progress */
|
||||
int sa_query_timed_out;
|
||||
u8 *sa_query_trans_id; /* buffer of WLAN_SA_QUERY_TR_ID_LEN *
|
||||
* sa_query_count octets of pending SA Query
|
||||
* transaction identifiers */
|
||||
struct os_time sa_query_start;
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
|
||||
#ifdef CONFIG_INTERWORKING
|
||||
#define GAS_DIALOG_MAX 8 /* Max concurrent dialog number */
|
||||
struct gas_dialog_info *gas_dialog;
|
||||
u8 gas_dialog_next;
|
||||
#endif /* CONFIG_INTERWORKING */
|
||||
|
||||
#ifdef CONFIG_SAE
|
||||
enum { SAE_INIT, SAE_COMMIT, SAE_CONFIRM } sae_state;
|
||||
u16 sae_send_confirm;
|
||||
#endif /* CONFIG_SAE */
|
||||
};
|
||||
|
||||
|
||||
/* Default value for maximum station inactivity. After AP_MAX_INACTIVITY has
|
||||
* passed since last received frame from the station, a nullfunc data frame is
|
||||
* sent to the station. If this frame is not acknowledged and no other frames
|
||||
* have been received, the station will be disassociated after
|
||||
* AP_DISASSOC_DELAY seconds. Similarly, the station will be deauthenticated
|
||||
* after AP_DEAUTH_DELAY seconds has passed after disassociation. */
|
||||
#define AP_MAX_INACTIVITY (5 * 60)
|
||||
#define AP_DISASSOC_DELAY (1)
|
||||
#define AP_DEAUTH_DELAY (1)
|
||||
/* Number of seconds to keep STA entry with Authenticated flag after it has
|
||||
* been disassociated. */
|
||||
#define AP_MAX_INACTIVITY_AFTER_DISASSOC (1 * 30)
|
||||
/* Number of seconds to keep STA entry after it has been deauthenticated. */
|
||||
#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),
|
||||
void *ctx);
|
||||
struct sta_info * ap_get_sta(struct hostapd_data *hapd, const u8 *sta);
|
||||
void ap_sta_hash_add(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
void hostapd_free_stas(struct hostapd_data *hapd);
|
||||
void ap_handle_timer(void *eloop_ctx, void *timeout_ctx);
|
||||
void ap_sta_session_timeout(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
u32 session_timeout);
|
||||
void ap_sta_no_session_timeout(struct hostapd_data *hapd,
|
||||
struct sta_info *sta);
|
||||
struct sta_info * ap_sta_add(struct hostapd_data *hapd, const u8 *addr);
|
||||
void ap_sta_disassociate(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
u16 reason);
|
||||
void ap_sta_deauthenticate(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
u16 reason);
|
||||
#ifdef CONFIG_WPS
|
||||
int ap_sta_wps_cancel(struct hostapd_data *hapd,
|
||||
struct sta_info *sta, void *ctx);
|
||||
#endif /* CONFIG_WPS */
|
||||
int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
int old_vlanid);
|
||||
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);
|
||||
void ap_sta_disconnect(struct hostapd_data *hapd, struct sta_info *sta,
|
||||
const u8 *addr, u16 reason);
|
||||
|
||||
void ap_sta_set_authorized(struct hostapd_data *hapd,
|
||||
struct sta_info *sta, int authorized);
|
||||
static inline int ap_sta_is_authorized(struct sta_info *sta)
|
||||
{
|
||||
return sta->flags & WLAN_STA_AUTHORIZED;
|
||||
}
|
||||
|
||||
void ap_sta_deauth_cb(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
void ap_sta_disassoc_cb(struct hostapd_data *hapd, struct sta_info *sta);
|
||||
|
||||
#endif /* STA_INFO_H */
|
2439
components/wpa_supplicant/src/ap/wpa_auth.c
Normal file
2439
components/wpa_supplicant/src/ap/wpa_auth.c
Normal file
File diff suppressed because it is too large
Load Diff
294
components/wpa_supplicant/src/ap/wpa_auth.h
Normal file
294
components/wpa_supplicant/src/ap/wpa_auth.h
Normal file
@@ -0,0 +1,294 @@
|
||||
/*
|
||||
* hostapd - IEEE 802.11i-2004 / WPA Authenticator
|
||||
* Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef WPA_AUTH_H
|
||||
#define WPA_AUTH_H
|
||||
|
||||
#include "common/defs.h"
|
||||
#include "common/eapol_common.h"
|
||||
#include "common/wpa_common.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack(push, 1)
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
#define WPA_IS_MULTICAST(_a) (*(_a) & 0x01)
|
||||
|
||||
/* IEEE Std 802.11r-2008, 11A.10.3 - Remote request/response frame definition
|
||||
*/
|
||||
struct ft_rrb_frame {
|
||||
u8 frame_type; /* RSN_REMOTE_FRAME_TYPE_FT_RRB */
|
||||
u8 packet_type; /* FT_PACKET_REQUEST/FT_PACKET_RESPONSE */
|
||||
le16 action_length; /* little endian length of action_frame */
|
||||
u8 ap_address[ETH_ALEN];
|
||||
/*
|
||||
* Followed by action_length bytes of FT Action frame (from Category
|
||||
* field to the end of Action Frame body.
|
||||
*/
|
||||
} STRUCT_PACKED;
|
||||
|
||||
#define RSN_REMOTE_FRAME_TYPE_FT_RRB 1
|
||||
|
||||
#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_DATA_LEN 44
|
||||
#define FT_R0KH_R1KH_RESP_DATA_LEN 76
|
||||
#define FT_R0KH_R1KH_PUSH_DATA_LEN 88
|
||||
|
||||
struct ft_r0kh_r1kh_pull_frame {
|
||||
u8 frame_type; /* RSN_REMOTE_FRAME_TYPE_FT_RRB */
|
||||
u8 packet_type; /* FT_PACKET_R0KH_R1KH_PULL */
|
||||
le16 data_length; /* little endian length of data (44) */
|
||||
u8 ap_address[ETH_ALEN];
|
||||
|
||||
u8 nonce[16];
|
||||
u8 pmk_r0_name[WPA_PMK_NAME_LEN];
|
||||
u8 r1kh_id[FT_R1KH_ID_LEN];
|
||||
u8 s1kh_id[ETH_ALEN];
|
||||
u8 pad[4]; /* 8-octet boundary for AES key wrap */
|
||||
u8 key_wrap_extra[8];
|
||||
} STRUCT_PACKED;
|
||||
|
||||
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 (76) */
|
||||
u8 ap_address[ETH_ALEN];
|
||||
|
||||
u8 nonce[16]; /* 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[2]; /* 8-octet boundary for AES key wrap */
|
||||
u8 key_wrap_extra[8];
|
||||
} STRUCT_PACKED;
|
||||
|
||||
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 (88) */
|
||||
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[6]; /* 8-octet boundary for AES key wrap */
|
||||
u8 key_wrap_extra[8];
|
||||
} STRUCT_PACKED;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack(pop)
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
|
||||
/* per STA state machine data */
|
||||
|
||||
struct wpa_authenticator;
|
||||
struct wpa_state_machine;
|
||||
struct rsn_pmksa_cache_entry;
|
||||
struct eapol_state_machine;
|
||||
|
||||
|
||||
struct ft_remote_r0kh {
|
||||
struct ft_remote_r0kh *next;
|
||||
u8 addr[ETH_ALEN];
|
||||
u8 id[FT_R0KH_ID_MAX_LEN];
|
||||
size_t id_len;
|
||||
u8 key[16];
|
||||
};
|
||||
|
||||
|
||||
struct ft_remote_r1kh {
|
||||
struct ft_remote_r1kh *next;
|
||||
u8 addr[ETH_ALEN];
|
||||
u8 id[FT_R1KH_ID_LEN];
|
||||
u8 key[16];
|
||||
};
|
||||
|
||||
|
||||
struct wpa_auth_config {
|
||||
int wpa;
|
||||
int wpa_key_mgmt;
|
||||
int wpa_pairwise;
|
||||
int wpa_group;
|
||||
int wpa_group_rekey;
|
||||
int wpa_strict_rekey;
|
||||
int wpa_gmk_rekey;
|
||||
int wpa_ptk_rekey;
|
||||
int rsn_pairwise;
|
||||
int rsn_preauth;
|
||||
int eapol_version;
|
||||
int peerkey;
|
||||
int wmm_enabled;
|
||||
int wmm_uapsd;
|
||||
int disable_pmksa_caching;
|
||||
int okc;
|
||||
int tx_status;
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
enum mfp_options ieee80211w;
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
#define SSID_LEN 32
|
||||
u8 ssid[SSID_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 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 disable_gtk;
|
||||
int ap_mlme;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
LOGGER_DEBUG, LOGGER_INFO, LOGGER_WARNING
|
||||
} logger_level;
|
||||
|
||||
typedef enum {
|
||||
WPA_EAPOL_portEnabled, WPA_EAPOL_portValid, WPA_EAPOL_authorized,
|
||||
WPA_EAPOL_portControl_Auto, WPA_EAPOL_keyRun, WPA_EAPOL_keyAvailable,
|
||||
WPA_EAPOL_keyDone, WPA_EAPOL_inc_EapolFramesTx
|
||||
} 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);
|
||||
int (*mic_failure_report)(void *ctx, const u8 *addr);
|
||||
void (*set_eapol)(void *ctx, const u8 *addr, wpa_eapol_variable var,
|
||||
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 *prev_psk);
|
||||
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);
|
||||
int (*get_seqnum)(void *ctx, const u8 *addr, int idx, u8 *seq);
|
||||
int (*send_eapol)(void *ctx, const u8 *addr, const u8 *data,
|
||||
size_t data_len, int encrypt);
|
||||
int (*for_each_sta)(void *ctx, int (*cb)(struct wpa_state_machine *sm,
|
||||
void *ctx), void *cb_ctx);
|
||||
int (*for_each_auth)(void *ctx, int (*cb)(struct wpa_authenticator *a,
|
||||
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
|
||||
struct wpa_state_machine * (*add_sta)(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 */
|
||||
};
|
||||
|
||||
struct wpa_authenticator * wpa_init(const u8 *addr,
|
||||
struct wpa_auth_config *conf,
|
||||
struct wpa_auth_callbacks *cb);
|
||||
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,
|
||||
struct wpa_auth_config *conf);
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
|
||||
struct wpa_state_machine *sm,
|
||||
const u8 *wpa_ie, size_t wpa_ie_len/*,
|
||||
const u8 *mdie, size_t mdie_len*/);
|
||||
int wpa_auth_uses_mfp(struct wpa_state_machine *sm);
|
||||
struct wpa_state_machine *
|
||||
wpa_auth_sta_init(struct wpa_authenticator *wpa_auth, const u8 *addr);
|
||||
int wpa_auth_sta_associated(struct wpa_authenticator *wpa_auth,
|
||||
struct wpa_state_machine *sm);
|
||||
void wpa_auth_sta_no_wpa(struct wpa_state_machine *sm);
|
||||
void wpa_auth_sta_deinit(struct wpa_state_machine *sm);
|
||||
void wpa_receive(struct wpa_authenticator *wpa_auth,
|
||||
struct wpa_state_machine *sm,
|
||||
u8 *data, size_t data_len);
|
||||
typedef enum {
|
||||
WPA_AUTH, WPA_ASSOC, WPA_DISASSOC, WPA_DEAUTH, WPA_REAUTH,
|
||||
WPA_REAUTH_EAPOL, WPA_ASSOC_FT
|
||||
} wpa_event;
|
||||
void wpa_remove_ptk(struct wpa_state_machine *sm);
|
||||
int wpa_auth_sm_event(struct wpa_state_machine *sm, wpa_event event);
|
||||
void wpa_auth_sm_notify(struct wpa_state_machine *sm);
|
||||
void wpa_gtk_rekey(struct wpa_authenticator *wpa_auth);
|
||||
int wpa_get_mib(struct wpa_authenticator *wpa_auth, char *buf, size_t buflen);
|
||||
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);
|
||||
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_clear_pmksa(struct wpa_state_machine *sm,
|
||||
struct rsn_pmksa_cache_entry *entry);
|
||||
struct rsn_pmksa_cache_entry *
|
||||
wpa_auth_sta_get_pmksa(struct wpa_state_machine *sm);
|
||||
void wpa_auth_sta_local_mic_failure_report(struct wpa_state_machine *sm);
|
||||
const u8 * wpa_auth_get_wpa_ie(struct wpa_authenticator *wpa_auth,
|
||||
size_t *len);
|
||||
int wpa_auth_pmksa_add(struct wpa_state_machine *sm, const u8 *pmk,
|
||||
int session_timeout, struct eapol_state_machine *eapol);
|
||||
int wpa_auth_pmksa_add_preauth(struct wpa_authenticator *wpa_auth,
|
||||
const u8 *pmk, size_t len, const u8 *sta_addr,
|
||||
int session_timeout,
|
||||
struct eapol_state_machine *eapol);
|
||||
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
|
||||
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);
|
||||
void wpa_ft_process_auth(struct wpa_state_machine *sm, const u8 *bssid,
|
||||
u16 auth_transaction, const u8 *ies, size_t ies_len,
|
||||
void (*cb)(void *ctx, const u8 *dst, const u8 *bssid,
|
||||
u16 auth_transaction, u16 resp,
|
||||
const u8 *ies, size_t ies_len),
|
||||
void *ctx);
|
||||
u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies,
|
||||
size_t ies_len);
|
||||
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_push_pmk_r1(struct wpa_authenticator *wpa_auth, const u8 *addr);
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
|
||||
void wpa_wnmsleep_rekey_gtk(struct wpa_state_machine *sm);
|
||||
void wpa_set_wnmsleep(struct wpa_state_machine *sm, int flag);
|
||||
int wpa_wnmsleep_gtk_subelem(struct wpa_state_machine *sm, u8 *pos);
|
||||
int wpa_wnmsleep_igtk_subelem(struct wpa_state_machine *sm, u8 *pos);
|
||||
|
||||
int wpa_auth_uses_sae(struct wpa_state_machine *sm);
|
||||
|
||||
#endif /* WPA_AUTH_H */
|
210
components/wpa_supplicant/src/ap/wpa_auth_i.h
Normal file
210
components/wpa_supplicant/src/ap/wpa_auth_i.h
Normal file
@@ -0,0 +1,210 @@
|
||||
/*
|
||||
* hostapd - IEEE 802.11i-2004 / WPA Authenticator: Internal definitions
|
||||
* Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef WPA_AUTH_I_H
|
||||
#define WPA_AUTH_I_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];
|
||||
|
||||
enum {
|
||||
WPA_PTK_INITIALIZE, WPA_PTK_DISCONNECT, WPA_PTK_DISCONNECTED,
|
||||
WPA_PTK_AUTHENTICATION, WPA_PTK_AUTHENTICATION2,
|
||||
WPA_PTK_INITPMK, WPA_PTK_INITPSK, WPA_PTK_PTKSTART,
|
||||
WPA_PTK_PTKCALCNEGOTIATING, WPA_PTK_PTKCALCNEGOTIATING2,
|
||||
WPA_PTK_PTKINITNEGOTIATING, WPA_PTK_PTKINITDONE
|
||||
} wpa_ptk_state;
|
||||
|
||||
enum {
|
||||
WPA_PTK_GROUP_IDLE = 0,
|
||||
WPA_PTK_GROUP_REKEYNEGOTIATING,
|
||||
WPA_PTK_GROUP_REKEYESTABLISHED,
|
||||
WPA_PTK_GROUP_KEYERROR
|
||||
} wpa_ptk_group_state;
|
||||
|
||||
Boolean Init;
|
||||
Boolean DeauthenticationRequest;
|
||||
Boolean AuthenticationRequest;
|
||||
Boolean ReAuthenticationRequest;
|
||||
Boolean Disconnect;
|
||||
int TimeoutCtr;
|
||||
int GTimeoutCtr;
|
||||
Boolean TimeoutEvt;
|
||||
Boolean EAPOLKeyReceived;
|
||||
Boolean EAPOLKeyPairwise;
|
||||
Boolean EAPOLKeyRequest;
|
||||
Boolean MICVerified;
|
||||
Boolean GUpdateStationKeys;
|
||||
u8 ANonce[WPA_NONCE_LEN];
|
||||
u8 SNonce[WPA_NONCE_LEN];
|
||||
u8 PMK[PMK_LEN];
|
||||
struct wpa_ptk PTK;
|
||||
Boolean PTK_valid;
|
||||
Boolean pairwise_set;
|
||||
int keycount;
|
||||
Boolean Pair;
|
||||
struct wpa_key_replay_counter {
|
||||
u8 counter[WPA_REPLAY_COUNTER_LEN];
|
||||
Boolean valid;
|
||||
} key_replay[RSNA_MAX_EAPOL_RETRIES],
|
||||
prev_key_replay[RSNA_MAX_EAPOL_RETRIES];
|
||||
Boolean PInitAKeys; /* WPA only, not in IEEE 802.11i */
|
||||
Boolean PTKRequest; /* not in IEEE 802.11i state machine */
|
||||
Boolean has_GTK;
|
||||
Boolean PtkGroupInit; /* init request for PTK Group state machine */
|
||||
|
||||
u8 *last_rx_eapol_key; /* starting from IEEE 802.1X header */
|
||||
size_t last_rx_eapol_key_len;
|
||||
|
||||
unsigned int changed:1;
|
||||
unsigned int in_step_loop:1;
|
||||
unsigned int pending_deinit:1;
|
||||
unsigned int started:1;
|
||||
unsigned int mgmt_frame_prot:1;
|
||||
unsigned int rx_eapol_key_secure:1;
|
||||
unsigned int update_snonce:1;
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
unsigned int ft_completed:1;
|
||||
unsigned int pmk_r1_name_valid:1;
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
unsigned int is_wnmsleep:1;
|
||||
|
||||
u8 req_replay_counter[WPA_REPLAY_COUNTER_LEN];
|
||||
int req_replay_counter_used;
|
||||
|
||||
u8 *wpa_ie;
|
||||
size_t wpa_ie_len;
|
||||
|
||||
enum {
|
||||
WPA_VERSION_NO_WPA = 0 /* WPA not used */,
|
||||
WPA_VERSION_WPA = 1 /* WPA / IEEE 802.11i/D3.0 */,
|
||||
WPA_VERSION_WPA2 = 2 /* WPA2 / IEEE 802.11i */
|
||||
} wpa;
|
||||
int pairwise; /* Pairwise cipher suite, WPA_CIPHER_* */
|
||||
int wpa_key_mgmt; /* the selected WPA_KEY_MGMT_* */
|
||||
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
u8 xxkey[PMK_LEN]; /* PSK or the second 256 bits of MSK */
|
||||
size_t xxkey_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 */
|
||||
size_t r0kh_id_len;
|
||||
u8 sup_pmk_r1_name[WPA_PMK_NAME_LEN]; /* PMKR1Name from EAPOL-Key
|
||||
* message 2/4 */
|
||||
u8 *assoc_resp_ftie;
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
|
||||
int pending_1_of_4_timeout;
|
||||
u32 index;
|
||||
ETSTimer resend_eapol;
|
||||
};
|
||||
|
||||
|
||||
/* per group key state machine data */
|
||||
struct wpa_group {
|
||||
struct wpa_group *next;
|
||||
int vlan_id;
|
||||
|
||||
Boolean GInit;
|
||||
int GKeyDoneStations;
|
||||
Boolean GTKReKey;
|
||||
int GTK_len;
|
||||
int GN, GM;
|
||||
Boolean GTKAuthenticator;
|
||||
u8 Counter[WPA_NONCE_LEN];
|
||||
|
||||
enum {
|
||||
WPA_GROUP_GTK_INIT = 0,
|
||||
WPA_GROUP_SETKEYS, WPA_GROUP_SETKEYSDONE
|
||||
} wpa_group_state;
|
||||
|
||||
u8 GMK[WPA_GMK_LEN];
|
||||
u8 GTK[2][WPA_GTK_MAX_LEN];
|
||||
u8 GNonce[WPA_NONCE_LEN];
|
||||
Boolean changed;
|
||||
Boolean first_sta_seen;
|
||||
Boolean reject_4way_hs_for_entropy;
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
u8 IGTK[2][WPA_IGTK_LEN];
|
||||
int GN_igtk, GM_igtk;
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
};
|
||||
|
||||
|
||||
struct wpa_ft_pmk_cache;
|
||||
|
||||
/* per authenticator data */
|
||||
struct wpa_authenticator {
|
||||
struct wpa_group *group;
|
||||
|
||||
struct wpa_auth_config conf;
|
||||
|
||||
u8 *wpa_ie;
|
||||
size_t wpa_ie_len;
|
||||
|
||||
u8 addr[ETH_ALEN];
|
||||
|
||||
};
|
||||
|
||||
|
||||
int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
|
||||
const u8 *pmkid);
|
||||
void __wpa_send_eapol(struct wpa_authenticator *wpa_auth,
|
||||
struct wpa_state_machine *sm, int key_info,
|
||||
const u8 *key_rsc, const u8 *nonce,
|
||||
const u8 *kde, size_t kde_len,
|
||||
int keyidx, int encr, int force_version);
|
||||
int wpa_auth_for_each_sta(struct wpa_authenticator *wpa_auth,
|
||||
int (*cb)(struct wpa_state_machine *sm, void *ctx),
|
||||
void *cb_ctx);
|
||||
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, struct wpa_eapol_key *key);
|
||||
void wpa_smk_m1(struct wpa_authenticator *wpa_auth,
|
||||
struct wpa_state_machine *sm, struct wpa_eapol_key *key);
|
||||
void wpa_smk_m3(struct wpa_authenticator *wpa_auth,
|
||||
struct wpa_state_machine *sm, struct wpa_eapol_key *key);
|
||||
#endif /* CONFIG_PEERKEY */
|
||||
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
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,
|
||||
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, size_t ptk_len);
|
||||
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 */
|
||||
|
||||
#endif /* WPA_AUTH_I_H */
|
705
components/wpa_supplicant/src/ap/wpa_auth_ie.c
Normal file
705
components/wpa_supplicant/src/ap/wpa_auth_ie.c
Normal file
@@ -0,0 +1,705 @@
|
||||
/*
|
||||
* hostapd - WPA/RSN IE and KDE definitions
|
||||
* Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#include "utils/includes.h"
|
||||
#include "utils/common.h"
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "ap/wpa_auth.h"
|
||||
#include "ap/wpa_auth_ie.h"
|
||||
#include "ap/wpa_auth_i.h"
|
||||
#include "common/wpa_common.h"
|
||||
#include "utils/wpa_debug.h"
|
||||
|
||||
#ifdef CONFIG_RSN_TESTING
|
||||
int rsn_testing = 0;
|
||||
#endif /* CONFIG_RSN_TESTING */
|
||||
|
||||
|
||||
static int wpa_write_wpa_ie(struct wpa_auth_config *conf, u8 *buf, size_t len)
|
||||
{
|
||||
struct wpa_ie_hdr *hdr;
|
||||
int num_suites;
|
||||
u8 *pos, *count;
|
||||
u32 suite;
|
||||
|
||||
hdr = (struct wpa_ie_hdr *) buf;
|
||||
hdr->elem_id = WLAN_EID_VENDOR_SPECIFIC;
|
||||
RSN_SELECTOR_PUT(hdr->oui, WPA_OUI_TYPE);
|
||||
WPA_PUT_LE16(hdr->version, WPA_VERSION);
|
||||
pos = (u8 *) (hdr + 1);
|
||||
|
||||
suite = wpa_cipher_to_suite(WPA_PROTO_WPA, conf->wpa_group);
|
||||
if (suite == 0) {
|
||||
wpa_printf( MSG_DEBUG, "Invalid group cipher (%d).",
|
||||
conf->wpa_group);
|
||||
return -1;
|
||||
}
|
||||
RSN_SELECTOR_PUT(pos, suite);
|
||||
pos += WPA_SELECTOR_LEN;
|
||||
|
||||
count = pos;
|
||||
pos += 2;
|
||||
|
||||
num_suites = wpa_cipher_put_suites(pos, conf->wpa_pairwise);
|
||||
if (num_suites == 0) {
|
||||
wpa_printf( MSG_DEBUG, "Invalid pairwise cipher (%d).",
|
||||
conf->wpa_pairwise);
|
||||
return -1;
|
||||
}
|
||||
pos += num_suites * WPA_SELECTOR_LEN;
|
||||
WPA_PUT_LE16(count, num_suites);
|
||||
|
||||
num_suites = 0;
|
||||
count = pos;
|
||||
pos += 2;
|
||||
|
||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
|
||||
RSN_SELECTOR_PUT(pos, WPA_AUTH_KEY_MGMT_UNSPEC_802_1X);
|
||||
pos += WPA_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) {
|
||||
RSN_SELECTOR_PUT(pos, WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X);
|
||||
pos += WPA_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
|
||||
if (num_suites == 0) {
|
||||
wpa_printf( MSG_DEBUG, "Invalid key management type (%d).",
|
||||
conf->wpa_key_mgmt);
|
||||
return -1;
|
||||
}
|
||||
WPA_PUT_LE16(count, num_suites);
|
||||
|
||||
/* WPA Capabilities; use defaults, so no need to include it */
|
||||
|
||||
hdr->len = (pos - buf) - 2;
|
||||
|
||||
return pos - buf;
|
||||
}
|
||||
|
||||
|
||||
int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
|
||||
const u8 *pmkid)
|
||||
{
|
||||
struct rsn_ie_hdr *hdr;
|
||||
int num_suites, res;
|
||||
u8 *pos, *count;
|
||||
u16 capab;
|
||||
u32 suite;
|
||||
|
||||
hdr = (struct rsn_ie_hdr *) buf;
|
||||
hdr->elem_id = WLAN_EID_RSN;
|
||||
WPA_PUT_LE16(hdr->version, RSN_VERSION);
|
||||
pos = (u8 *) (hdr + 1);
|
||||
|
||||
suite = wpa_cipher_to_suite(WPA_PROTO_RSN, conf->wpa_group);
|
||||
if (suite == 0) {
|
||||
wpa_printf( MSG_DEBUG, "Invalid group cipher (%d).",
|
||||
conf->wpa_group);
|
||||
return -1;
|
||||
}
|
||||
RSN_SELECTOR_PUT(pos, suite);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
|
||||
num_suites = 0;
|
||||
count = pos;
|
||||
pos += 2;
|
||||
|
||||
#ifdef CONFIG_RSN_TESTING
|
||||
if (rsn_testing) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_SELECTOR(0x12, 0x34, 0x56, 1));
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
#endif /* CONFIG_RSN_TESTING */
|
||||
|
||||
res = rsn_cipher_put_suites(pos, conf->rsn_pairwise);
|
||||
num_suites += res;
|
||||
pos += res * RSN_SELECTOR_LEN;
|
||||
|
||||
#ifdef CONFIG_RSN_TESTING
|
||||
if (rsn_testing) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_SELECTOR(0x12, 0x34, 0x56, 2));
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
#endif /* CONFIG_RSN_TESTING */
|
||||
|
||||
if (num_suites == 0) {
|
||||
wpa_printf( MSG_DEBUG, "Invalid pairwise cipher (%d).",
|
||||
conf->rsn_pairwise);
|
||||
return -1;
|
||||
}
|
||||
WPA_PUT_LE16(count, num_suites);
|
||||
|
||||
num_suites = 0;
|
||||
count = pos;
|
||||
pos += 2;
|
||||
|
||||
#ifdef CONFIG_RSN_TESTING
|
||||
if (rsn_testing) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_SELECTOR(0x12, 0x34, 0x56, 1));
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
#endif /* CONFIG_RSN_TESTING */
|
||||
|
||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_UNSPEC_802_1X);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_802_1X);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_PSK) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_PSK);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SHA256);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_SHA256);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
#ifdef CONFIG_SAE
|
||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_SAE) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_SAE);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_SAE) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_SAE);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
#endif /* CONFIG_SAE */
|
||||
|
||||
#ifdef CONFIG_RSN_TESTING
|
||||
if (rsn_testing) {
|
||||
RSN_SELECTOR_PUT(pos, RSN_SELECTOR(0x12, 0x34, 0x56, 2));
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
num_suites++;
|
||||
}
|
||||
#endif /* CONFIG_RSN_TESTING */
|
||||
|
||||
if (num_suites == 0) {
|
||||
wpa_printf( MSG_DEBUG, "Invalid key management type (%d).",
|
||||
conf->wpa_key_mgmt);
|
||||
return -1;
|
||||
}
|
||||
WPA_PUT_LE16(count, num_suites);
|
||||
|
||||
/* RSN Capabilities */
|
||||
capab = 0;
|
||||
if (conf->rsn_preauth)
|
||||
capab |= WPA_CAPABILITY_PREAUTH;
|
||||
if (conf->peerkey)
|
||||
capab |= WPA_CAPABILITY_PEERKEY_ENABLED;
|
||||
if (conf->wmm_enabled) {
|
||||
/* 4 PTKSA replay counters when using WMM */
|
||||
capab |= (RSN_NUM_REPLAY_COUNTERS_16 << 2);
|
||||
}
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
|
||||
capab |= WPA_CAPABILITY_MFPC;
|
||||
if (conf->ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED)
|
||||
capab |= WPA_CAPABILITY_MFPR;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
#ifdef CONFIG_RSN_TESTING
|
||||
if (rsn_testing)
|
||||
capab |= BIT(8) | BIT(14) | BIT(15);
|
||||
#endif /* CONFIG_RSN_TESTING */
|
||||
WPA_PUT_LE16(pos, capab);
|
||||
pos += 2;
|
||||
|
||||
if (pmkid) {
|
||||
if (pos + 2 + PMKID_LEN > buf + len)
|
||||
return -1;
|
||||
/* PMKID Count */
|
||||
WPA_PUT_LE16(pos, 1);
|
||||
pos += 2;
|
||||
memcpy(pos, pmkid, PMKID_LEN);
|
||||
pos += PMKID_LEN;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
|
||||
if (pos + 2 + 4 > buf + len)
|
||||
return -1;
|
||||
if (pmkid == NULL) {
|
||||
/* PMKID Count */
|
||||
WPA_PUT_LE16(pos, 0);
|
||||
pos += 2;
|
||||
}
|
||||
|
||||
/* Management Group Cipher Suite */
|
||||
RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
|
||||
#ifdef CONFIG_RSN_TESTING
|
||||
if (rsn_testing) {
|
||||
/*
|
||||
* Fill in any defined fields and add extra data to the end of
|
||||
* the element.
|
||||
*/
|
||||
int pmkid_count_set = pmkid != NULL;
|
||||
if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION)
|
||||
pmkid_count_set = 1;
|
||||
/* PMKID Count */
|
||||
WPA_PUT_LE16(pos, 0);
|
||||
pos += 2;
|
||||
if (conf->ieee80211w == NO_MGMT_FRAME_PROTECTION) {
|
||||
/* Management Group Cipher Suite */
|
||||
RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
}
|
||||
|
||||
memset(pos, 0x12, 17);
|
||||
pos += 17;
|
||||
}
|
||||
#endif /* CONFIG_RSN_TESTING */
|
||||
|
||||
hdr->len = (pos - buf) - 2;
|
||||
|
||||
return pos - buf;
|
||||
}
|
||||
|
||||
|
||||
int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth)
|
||||
{
|
||||
u8 *pos, buf[128];
|
||||
int res;
|
||||
|
||||
pos = buf;
|
||||
|
||||
if (wpa_auth->conf.wpa & WPA_PROTO_RSN) {
|
||||
res = wpa_write_rsn_ie(&wpa_auth->conf,
|
||||
pos, buf + sizeof(buf) - pos, NULL);
|
||||
if (res < 0)
|
||||
return res;
|
||||
pos += res;
|
||||
}
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
if (wpa_key_mgmt_ft(wpa_auth->conf.wpa_key_mgmt)) {
|
||||
res = wpa_write_mdie(&wpa_auth->conf, pos,
|
||||
buf + sizeof(buf) - pos);
|
||||
if (res < 0)
|
||||
return res;
|
||||
pos += res;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
if (wpa_auth->conf.wpa & WPA_PROTO_WPA) {
|
||||
res = wpa_write_wpa_ie(&wpa_auth->conf,
|
||||
pos, buf + sizeof(buf) - pos);
|
||||
if (res < 0)
|
||||
return res;
|
||||
pos += res;
|
||||
}
|
||||
|
||||
os_free(wpa_auth->wpa_ie);
|
||||
wpa_auth->wpa_ie = os_malloc(pos - buf);
|
||||
if (wpa_auth->wpa_ie == NULL)
|
||||
return -1;
|
||||
memcpy(wpa_auth->wpa_ie, buf, pos - buf);
|
||||
wpa_auth->wpa_ie_len = pos - buf;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u8 * wpa_add_kde(u8 *pos, u32 kde, const u8 *data, size_t data_len,
|
||||
const u8 *data2, size_t data2_len)
|
||||
{
|
||||
*pos++ = WLAN_EID_VENDOR_SPECIFIC;
|
||||
*pos++ = RSN_SELECTOR_LEN + data_len + data2_len;
|
||||
RSN_SELECTOR_PUT(pos, kde);
|
||||
pos += RSN_SELECTOR_LEN;
|
||||
memcpy(pos, data, data_len);
|
||||
pos += data_len;
|
||||
if (data2) {
|
||||
memcpy(pos, data2, data2_len);
|
||||
pos += data2_len;
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
|
||||
struct wpa_state_machine *sm,
|
||||
const u8 *wpa_ie, size_t wpa_ie_len/*,
|
||||
const u8 *mdie, size_t mdie_len*/)
|
||||
{
|
||||
struct wpa_ie_data data;
|
||||
int ciphers, key_mgmt, res, version;
|
||||
u32 selector;
|
||||
|
||||
if (wpa_auth == NULL || sm == NULL)
|
||||
return WPA_NOT_ENABLED;
|
||||
|
||||
if (wpa_ie == NULL || wpa_ie_len < 1)
|
||||
return WPA_INVALID_IE;
|
||||
|
||||
if (wpa_ie[0] == WLAN_EID_RSN)
|
||||
version = WPA_PROTO_RSN;
|
||||
else
|
||||
version = WPA_PROTO_WPA;
|
||||
|
||||
if (!(wpa_auth->conf.wpa & version)) {
|
||||
wpa_printf( MSG_DEBUG, "Invalid WPA proto (%d) from " MACSTR,
|
||||
version, MAC2STR(sm->addr));
|
||||
return WPA_INVALID_PROTO;
|
||||
}
|
||||
|
||||
if (version == WPA_PROTO_RSN) {
|
||||
res = wpa_parse_wpa_ie_rsn(wpa_ie, wpa_ie_len, &data);
|
||||
|
||||
selector = RSN_AUTH_KEY_MGMT_UNSPEC_802_1X;
|
||||
if (0) {
|
||||
}
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
else if (data.key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X)
|
||||
selector = RSN_AUTH_KEY_MGMT_FT_802_1X;
|
||||
else if (data.key_mgmt & WPA_KEY_MGMT_FT_PSK)
|
||||
selector = RSN_AUTH_KEY_MGMT_FT_PSK;
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
else if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256)
|
||||
selector = RSN_AUTH_KEY_MGMT_802_1X_SHA256;
|
||||
else if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
|
||||
selector = RSN_AUTH_KEY_MGMT_PSK_SHA256;
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
#ifdef CONFIG_SAE
|
||||
else if (data.key_mgmt & WPA_KEY_MGMT_SAE)
|
||||
selector = RSN_AUTH_KEY_MGMT_SAE;
|
||||
else if (data.key_mgmt & WPA_KEY_MGMT_FT_SAE)
|
||||
selector = RSN_AUTH_KEY_MGMT_FT_SAE;
|
||||
#endif /* CONFIG_SAE */
|
||||
else if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X)
|
||||
selector = RSN_AUTH_KEY_MGMT_UNSPEC_802_1X;
|
||||
else if (data.key_mgmt & WPA_KEY_MGMT_PSK)
|
||||
selector = RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X;
|
||||
|
||||
selector = wpa_cipher_to_suite(WPA_PROTO_RSN,
|
||||
data.pairwise_cipher);
|
||||
if (!selector)
|
||||
selector = RSN_CIPHER_SUITE_CCMP;
|
||||
|
||||
selector = wpa_cipher_to_suite(WPA_PROTO_RSN,
|
||||
data.group_cipher);
|
||||
if (!selector)
|
||||
selector = RSN_CIPHER_SUITE_CCMP;
|
||||
} else {
|
||||
res = wpa_parse_wpa_ie_wpa(wpa_ie, wpa_ie_len, &data);
|
||||
|
||||
selector = WPA_AUTH_KEY_MGMT_UNSPEC_802_1X;
|
||||
if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X)
|
||||
selector = WPA_AUTH_KEY_MGMT_UNSPEC_802_1X;
|
||||
else if (data.key_mgmt & WPA_KEY_MGMT_PSK)
|
||||
selector = WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X;
|
||||
|
||||
selector = wpa_cipher_to_suite(WPA_PROTO_WPA,
|
||||
data.pairwise_cipher);
|
||||
if (!selector)
|
||||
selector = RSN_CIPHER_SUITE_TKIP;
|
||||
|
||||
selector = wpa_cipher_to_suite(WPA_PROTO_WPA,
|
||||
data.group_cipher);
|
||||
if (!selector)
|
||||
selector = WPA_CIPHER_SUITE_TKIP;
|
||||
}
|
||||
if (res) {
|
||||
wpa_printf( MSG_DEBUG, "Failed to parse WPA/RSN IE from "
|
||||
MACSTR " (res=%d)", MAC2STR(sm->addr), res);
|
||||
wpa_hexdump(MSG_DEBUG, "WPA/RSN IE", wpa_ie, wpa_ie_len);
|
||||
return WPA_INVALID_IE;
|
||||
}
|
||||
|
||||
if (data.group_cipher != wpa_auth->conf.wpa_group) {
|
||||
wpa_printf( MSG_DEBUG, "Invalid WPA group cipher (0x%x) from "
|
||||
MACSTR, data.group_cipher, MAC2STR(sm->addr));
|
||||
return WPA_INVALID_GROUP;
|
||||
}
|
||||
|
||||
key_mgmt = data.key_mgmt & wpa_auth->conf.wpa_key_mgmt;
|
||||
if (!key_mgmt) {
|
||||
wpa_printf( MSG_DEBUG, "Invalid WPA key mgmt (0x%x) from "
|
||||
MACSTR, data.key_mgmt, MAC2STR(sm->addr));
|
||||
return WPA_INVALID_AKMP;
|
||||
}
|
||||
if (0) {
|
||||
}
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
else if (key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X)
|
||||
sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
|
||||
else if (key_mgmt & WPA_KEY_MGMT_FT_PSK)
|
||||
sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_PSK;
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
else if (key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256)
|
||||
sm->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
|
||||
else if (key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
|
||||
sm->wpa_key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
#ifdef CONFIG_SAE
|
||||
else if (key_mgmt & WPA_KEY_MGMT_SAE)
|
||||
sm->wpa_key_mgmt = WPA_KEY_MGMT_SAE;
|
||||
else if (key_mgmt & WPA_KEY_MGMT_FT_SAE)
|
||||
sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_SAE;
|
||||
#endif /* CONFIG_SAE */
|
||||
else if (key_mgmt & WPA_KEY_MGMT_IEEE8021X)
|
||||
sm->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X;
|
||||
else
|
||||
sm->wpa_key_mgmt = WPA_KEY_MGMT_PSK;
|
||||
|
||||
if (version == WPA_PROTO_RSN)
|
||||
ciphers = data.pairwise_cipher & wpa_auth->conf.rsn_pairwise;
|
||||
else
|
||||
ciphers = data.pairwise_cipher & wpa_auth->conf.wpa_pairwise;
|
||||
if (!ciphers) {
|
||||
wpa_printf( MSG_DEBUG, "Invalid %s pairwise cipher (0x%x) "
|
||||
"from " MACSTR,
|
||||
version == WPA_PROTO_RSN ? "RSN" : "WPA",
|
||||
data.pairwise_cipher, MAC2STR(sm->addr));
|
||||
return WPA_INVALID_PAIRWISE;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
if (wpa_auth->conf.ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED) {
|
||||
if (!(data.capabilities & WPA_CAPABILITY_MFPC)) {
|
||||
wpa_printf( MSG_DEBUG, "Management frame protection "
|
||||
"required, but client did not enable it");
|
||||
return WPA_MGMT_FRAME_PROTECTION_VIOLATION;
|
||||
}
|
||||
|
||||
if (ciphers & WPA_CIPHER_TKIP) {
|
||||
wpa_printf( MSG_DEBUG, "Management frame protection "
|
||||
"cannot use TKIP");
|
||||
return WPA_MGMT_FRAME_PROTECTION_VIOLATION;
|
||||
}
|
||||
|
||||
if (data.mgmt_group_cipher != WPA_CIPHER_AES_128_CMAC) {
|
||||
wpa_printf( MSG_DEBUG, "Unsupported management group "
|
||||
"cipher %d", data.mgmt_group_cipher);
|
||||
return WPA_INVALID_MGMT_GROUP_CIPHER;
|
||||
}
|
||||
}
|
||||
|
||||
if (wpa_auth->conf.ieee80211w == NO_MGMT_FRAME_PROTECTION ||
|
||||
!(data.capabilities & WPA_CAPABILITY_MFPC))
|
||||
sm->mgmt_frame_prot = 0;
|
||||
else
|
||||
sm->mgmt_frame_prot = 1;
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
|
||||
if (mdie == NULL || mdie_len < MOBILITY_DOMAIN_ID_LEN + 1) {
|
||||
wpa_printf( MSG_DEBUG, "RSN: Trying to use FT, but "
|
||||
"MDIE not included");
|
||||
return WPA_INVALID_MDIE;
|
||||
}
|
||||
if (memcmp(mdie, wpa_auth->conf.mobility_domain,
|
||||
MOBILITY_DOMAIN_ID_LEN) != 0) {
|
||||
wpa_hexdump(MSG_DEBUG, "RSN: Attempted to use unknown "
|
||||
"MDIE", mdie, MOBILITY_DOMAIN_ID_LEN);
|
||||
return WPA_INVALID_MDIE;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
|
||||
if (ciphers & WPA_CIPHER_CCMP)
|
||||
sm->pairwise = WPA_CIPHER_CCMP;
|
||||
else if (ciphers & WPA_CIPHER_GCMP)
|
||||
sm->pairwise = WPA_CIPHER_GCMP;
|
||||
else
|
||||
sm->pairwise = WPA_CIPHER_TKIP;
|
||||
|
||||
/* TODO: clear WPA/WPA2 state if STA changes from one to another */
|
||||
if (wpa_ie[0] == WLAN_EID_RSN)
|
||||
sm->wpa = WPA_VERSION_WPA2;
|
||||
else
|
||||
sm->wpa = WPA_VERSION_WPA;
|
||||
|
||||
if (sm->wpa_ie == NULL || sm->wpa_ie_len < wpa_ie_len) {
|
||||
os_free(sm->wpa_ie);
|
||||
sm->wpa_ie = os_malloc(wpa_ie_len);
|
||||
if (sm->wpa_ie == NULL)
|
||||
return WPA_ALLOC_FAIL;
|
||||
}
|
||||
memcpy(sm->wpa_ie, wpa_ie, wpa_ie_len);
|
||||
sm->wpa_ie_len = wpa_ie_len;
|
||||
|
||||
return WPA_IE_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* wpa_parse_generic - Parse EAPOL-Key Key Data Generic IEs
|
||||
* @pos: Pointer to the IE header
|
||||
* @end: Pointer to the end of the Key Data buffer
|
||||
* @ie: Pointer to parsed IE data
|
||||
* Returns: 0 on success, 1 if end mark is found, -1 on failure
|
||||
*/
|
||||
static int wpa_parse_generic(const u8 *pos, const u8 *end,
|
||||
struct wpa_eapol_ie_parse *ie)
|
||||
{
|
||||
if (pos[1] == 0)
|
||||
return 1;
|
||||
|
||||
if (pos[1] >= 6 &&
|
||||
RSN_SELECTOR_GET(pos + 2) == WPA_OUI_TYPE &&
|
||||
pos[2 + WPA_SELECTOR_LEN] == 1 &&
|
||||
pos[2 + WPA_SELECTOR_LEN + 1] == 0) {
|
||||
ie->wpa_ie = pos;
|
||||
ie->wpa_ie_len = pos[1] + 2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (pos + 1 + RSN_SELECTOR_LEN < end &&
|
||||
pos[1] >= RSN_SELECTOR_LEN + PMKID_LEN &&
|
||||
RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_PMKID) {
|
||||
ie->pmkid = pos + 2 + RSN_SELECTOR_LEN;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (pos[1] > RSN_SELECTOR_LEN + 2 &&
|
||||
RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_GROUPKEY) {
|
||||
ie->gtk = pos + 2 + RSN_SELECTOR_LEN;
|
||||
ie->gtk_len = pos[1] - RSN_SELECTOR_LEN;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (pos[1] > RSN_SELECTOR_LEN + 2 &&
|
||||
RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_MAC_ADDR) {
|
||||
ie->mac_addr = pos + 2 + RSN_SELECTOR_LEN;
|
||||
ie->mac_addr_len = pos[1] - RSN_SELECTOR_LEN;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_PEERKEY */
|
||||
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
if (pos[1] > RSN_SELECTOR_LEN + 2 &&
|
||||
RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_IGTK) {
|
||||
ie->igtk = pos + 2 + RSN_SELECTOR_LEN;
|
||||
ie->igtk_len = pos[1] - RSN_SELECTOR_LEN;
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* wpa_parse_kde_ies - Parse EAPOL-Key Key Data IEs
|
||||
* @buf: Pointer to the Key Data buffer
|
||||
* @len: Key Data Length
|
||||
* @ie: Pointer to parsed IE data
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int wpa_parse_kde_ies(const u8 *buf, size_t len, struct wpa_eapol_ie_parse *ie)
|
||||
{
|
||||
const u8 *pos, *end;
|
||||
int ret = 0;
|
||||
|
||||
memset(ie, 0, sizeof(*ie));
|
||||
for (pos = buf, end = pos + len; pos + 1 < end; pos += 2 + pos[1]) {
|
||||
if (pos[0] == 0xdd &&
|
||||
((pos == buf + len - 1) || pos[1] == 0)) {
|
||||
/* Ignore padding */
|
||||
break;
|
||||
}
|
||||
if (pos + 2 + pos[1] > end) {
|
||||
wpa_printf( MSG_DEBUG, "WPA: EAPOL-Key Key Data "
|
||||
"underflow (ie=%d len=%d pos=%d)",
|
||||
pos[0], pos[1], (int) (pos - buf));
|
||||
wpa_hexdump_key(MSG_DEBUG, "WPA: Key Data",
|
||||
buf, len);
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
if (*pos == WLAN_EID_RSN) {
|
||||
ie->rsn_ie = pos;
|
||||
ie->rsn_ie_len = pos[1] + 2;
|
||||
#ifdef CONFIG_IEEE80211R
|
||||
} else if (*pos == WLAN_EID_MOBILITY_DOMAIN) {
|
||||
ie->mdie = pos;
|
||||
ie->mdie_len = pos[1] + 2;
|
||||
} else if (*pos == WLAN_EID_FAST_BSS_TRANSITION) {
|
||||
ie->ftie = pos;
|
||||
ie->ftie_len = pos[1] + 2;
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
} else if (*pos == WLAN_EID_VENDOR_SPECIFIC) {
|
||||
ret = wpa_parse_generic(pos, end, ie);
|
||||
if (ret < 0)
|
||||
break;
|
||||
if (ret > 0) {
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
wpa_hexdump(MSG_DEBUG, "WPA: Unrecognized EAPOL-Key "
|
||||
"Key Data IE", pos, 2 + pos[1]);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int wpa_auth_uses_mfp(struct wpa_state_machine *sm)
|
||||
{
|
||||
return sm ? sm->mgmt_frame_prot : 0;
|
||||
}
|
50
components/wpa_supplicant/src/ap/wpa_auth_ie.h
Normal file
50
components/wpa_supplicant/src/ap/wpa_auth_ie.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* hostapd - WPA/RSN IE and KDE definitions
|
||||
* Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifndef WPA_AUTH_IE_H
|
||||
#define WPA_AUTH_IE_H
|
||||
|
||||
struct wpa_eapol_ie_parse {
|
||||
const u8 *wpa_ie;
|
||||
size_t wpa_ie_len;
|
||||
const u8 *rsn_ie;
|
||||
size_t rsn_ie_len;
|
||||
const u8 *pmkid;
|
||||
const u8 *gtk;
|
||||
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
|
||||
const u8 *mdie;
|
||||
size_t mdie_len;
|
||||
const u8 *ftie;
|
||||
size_t ftie_len;
|
||||
#endif /* CONFIG_IEEE80211R */
|
||||
};
|
||||
|
||||
int wpa_parse_kde_ies(const u8 *buf, size_t len,
|
||||
struct wpa_eapol_ie_parse *ie);
|
||||
u8 * wpa_add_kde(u8 *pos, u32 kde, const u8 *data, size_t data_len,
|
||||
const u8 *data2, size_t data2_len);
|
||||
int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth);
|
||||
|
||||
#endif /* WPA_AUTH_IE_H */
|
Reference in New Issue
Block a user