wpa_supplicant: Initial Revision 0.8.X
Based on:
commit 0725cc7b7efc434910e89865c42eda7ce61bbf08
Author: Jouni Malinen <j@w1.fi>
Date: Thu Apr 21 20:41:01 2011 +0300
Enable CONFIG_DRIVER_NL80211=y in the default configuration
nl80211 should be preferred over WEXT with any recent Linux
kernel version.
Change-Id: I26aec5afbbd4f4a1f5fd900912545b6f5050de64
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/src/common/Makefile b/src/common/Makefile
new file mode 100644
index 0000000..9c41962
--- /dev/null
+++ b/src/common/Makefile
@@ -0,0 +1,8 @@
+all:
+ @echo Nothing to be made.
+
+clean:
+ rm -f *~ *.o *.d
+
+install:
+ @echo Nothing to be made.
diff --git a/src/common/defs.h b/src/common/defs.h
new file mode 100644
index 0000000..8abec07
--- /dev/null
+++ b/src/common/defs.h
@@ -0,0 +1,270 @@
+/*
+ * WPA Supplicant - Common definitions
+ * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#ifndef DEFS_H
+#define DEFS_H
+
+#ifdef FALSE
+#undef FALSE
+#endif
+#ifdef TRUE
+#undef TRUE
+#endif
+typedef enum { FALSE = 0, TRUE = 1 } Boolean;
+
+
+#define WPA_CIPHER_NONE BIT(0)
+#define WPA_CIPHER_WEP40 BIT(1)
+#define WPA_CIPHER_WEP104 BIT(2)
+#define WPA_CIPHER_TKIP BIT(3)
+#define WPA_CIPHER_CCMP BIT(4)
+#ifdef CONFIG_IEEE80211W
+#define WPA_CIPHER_AES_128_CMAC BIT(5)
+#endif /* CONFIG_IEEE80211W */
+
+#define WPA_KEY_MGMT_IEEE8021X BIT(0)
+#define WPA_KEY_MGMT_PSK BIT(1)
+#define WPA_KEY_MGMT_NONE BIT(2)
+#define WPA_KEY_MGMT_IEEE8021X_NO_WPA BIT(3)
+#define WPA_KEY_MGMT_WPA_NONE BIT(4)
+#define WPA_KEY_MGMT_FT_IEEE8021X BIT(5)
+#define WPA_KEY_MGMT_FT_PSK BIT(6)
+#define WPA_KEY_MGMT_IEEE8021X_SHA256 BIT(7)
+#define WPA_KEY_MGMT_PSK_SHA256 BIT(8)
+#define WPA_KEY_MGMT_WPS BIT(9)
+
+static inline int wpa_key_mgmt_wpa_ieee8021x(int akm)
+{
+ return !!(akm & (WPA_KEY_MGMT_IEEE8021X |
+ WPA_KEY_MGMT_FT_IEEE8021X |
+ WPA_KEY_MGMT_IEEE8021X_SHA256));
+}
+
+static inline int wpa_key_mgmt_wpa_psk(int akm)
+{
+ return !!(akm & (WPA_KEY_MGMT_PSK |
+ WPA_KEY_MGMT_FT_PSK |
+ WPA_KEY_MGMT_PSK_SHA256));
+}
+
+static inline int wpa_key_mgmt_ft(int akm)
+{
+ return !!(akm & (WPA_KEY_MGMT_FT_PSK |
+ WPA_KEY_MGMT_FT_IEEE8021X));
+}
+
+static inline int wpa_key_mgmt_sha256(int akm)
+{
+ return !!(akm & (WPA_KEY_MGMT_PSK_SHA256 |
+ WPA_KEY_MGMT_IEEE8021X_SHA256));
+}
+
+static inline int wpa_key_mgmt_wpa(int akm)
+{
+ return wpa_key_mgmt_wpa_ieee8021x(akm) ||
+ wpa_key_mgmt_wpa_psk(akm);
+}
+
+
+#define WPA_PROTO_WPA BIT(0)
+#define WPA_PROTO_RSN BIT(1)
+
+#define WPA_AUTH_ALG_OPEN BIT(0)
+#define WPA_AUTH_ALG_SHARED BIT(1)
+#define WPA_AUTH_ALG_LEAP BIT(2)
+#define WPA_AUTH_ALG_FT BIT(3)
+
+
+enum wpa_alg {
+ WPA_ALG_NONE,
+ WPA_ALG_WEP,
+ WPA_ALG_TKIP,
+ WPA_ALG_CCMP,
+ WPA_ALG_IGTK,
+ WPA_ALG_PMK
+};
+
+/**
+ * enum wpa_cipher - Cipher suites
+ */
+enum wpa_cipher {
+ CIPHER_NONE,
+ CIPHER_WEP40,
+ CIPHER_TKIP,
+ CIPHER_CCMP,
+ CIPHER_WEP104
+};
+
+/**
+ * enum wpa_key_mgmt - Key management suites
+ */
+enum wpa_key_mgmt {
+ KEY_MGMT_802_1X,
+ KEY_MGMT_PSK,
+ KEY_MGMT_NONE,
+ KEY_MGMT_802_1X_NO_WPA,
+ KEY_MGMT_WPA_NONE,
+ KEY_MGMT_FT_802_1X,
+ KEY_MGMT_FT_PSK,
+ KEY_MGMT_802_1X_SHA256,
+ KEY_MGMT_PSK_SHA256,
+ KEY_MGMT_WPS
+};
+
+/**
+ * enum wpa_states - wpa_supplicant state
+ *
+ * These enumeration values are used to indicate the current wpa_supplicant
+ * state (wpa_s->wpa_state). The current state can be retrieved with
+ * wpa_supplicant_get_state() function and the state can be changed by calling
+ * wpa_supplicant_set_state(). In WPA state machine (wpa.c and preauth.c), the
+ * wrapper functions wpa_sm_get_state() and wpa_sm_set_state() should be used
+ * to access the state variable.
+ */
+enum wpa_states {
+ /**
+ * WPA_DISCONNECTED - Disconnected state
+ *
+ * This state indicates that client is not associated, but is likely to
+ * start looking for an access point. This state is entered when a
+ * connection is lost.
+ */
+ WPA_DISCONNECTED,
+
+ /**
+ * WPA_INTERFACE_DISABLED - Interface disabled
+ *
+ * This stat eis entered if the network interface is disabled, e.g.,
+ * due to rfkill. wpa_supplicant refuses any new operations that would
+ * use the radio until the interface has been enabled.
+ */
+ WPA_INTERFACE_DISABLED,
+
+ /**
+ * WPA_INACTIVE - Inactive state (wpa_supplicant disabled)
+ *
+ * This state is entered if there are no enabled networks in the
+ * configuration. wpa_supplicant is not trying to associate with a new
+ * network and external interaction (e.g., ctrl_iface call to add or
+ * enable a network) is needed to start association.
+ */
+ WPA_INACTIVE,
+
+ /**
+ * WPA_SCANNING - Scanning for a network
+ *
+ * This state is entered when wpa_supplicant starts scanning for a
+ * network.
+ */
+ WPA_SCANNING,
+
+ /**
+ * WPA_AUTHENTICATING - Trying to authenticate with a BSS/SSID
+ *
+ * This state is entered when wpa_supplicant has found a suitable BSS
+ * to authenticate with and the driver is configured to try to
+ * authenticate with this BSS. This state is used only with drivers
+ * that use wpa_supplicant as the SME.
+ */
+ WPA_AUTHENTICATING,
+
+ /**
+ * WPA_ASSOCIATING - Trying to associate with a BSS/SSID
+ *
+ * This state is entered when wpa_supplicant has found a suitable BSS
+ * to associate with and the driver is configured to try to associate
+ * with this BSS in ap_scan=1 mode. When using ap_scan=2 mode, this
+ * state is entered when the driver is configured to try to associate
+ * with a network using the configured SSID and security policy.
+ */
+ WPA_ASSOCIATING,
+
+ /**
+ * WPA_ASSOCIATED - Association completed
+ *
+ * This state is entered when the driver reports that association has
+ * been successfully completed with an AP. If IEEE 802.1X is used
+ * (with or without WPA/WPA2), wpa_supplicant remains in this state
+ * until the IEEE 802.1X/EAPOL authentication has been completed.
+ */
+ WPA_ASSOCIATED,
+
+ /**
+ * WPA_4WAY_HANDSHAKE - WPA 4-Way Key Handshake in progress
+ *
+ * This state is entered when WPA/WPA2 4-Way Handshake is started. In
+ * case of WPA-PSK, this happens when receiving the first EAPOL-Key
+ * frame after association. In case of WPA-EAP, this state is entered
+ * when the IEEE 802.1X/EAPOL authentication has been completed.
+ */
+ WPA_4WAY_HANDSHAKE,
+
+ /**
+ * WPA_GROUP_HANDSHAKE - WPA Group Key Handshake in progress
+ *
+ * This state is entered when 4-Way Key Handshake has been completed
+ * (i.e., when the supplicant sends out message 4/4) and when Group
+ * Key rekeying is started by the AP (i.e., when supplicant receives
+ * message 1/2).
+ */
+ WPA_GROUP_HANDSHAKE,
+
+ /**
+ * WPA_COMPLETED - All authentication completed
+ *
+ * This state is entered when the full authentication process is
+ * completed. In case of WPA2, this happens when the 4-Way Handshake is
+ * successfully completed. With WPA, this state is entered after the
+ * Group Key Handshake; with IEEE 802.1X (non-WPA) connection is
+ * completed after dynamic keys are received (or if not used, after
+ * the EAP authentication has been completed). With static WEP keys and
+ * plaintext connections, this state is entered when an association
+ * has been completed.
+ *
+ * This state indicates that the supplicant has completed its
+ * processing for the association phase and that data connection is
+ * fully configured.
+ */
+ WPA_COMPLETED
+};
+
+#define MLME_SETPROTECTION_PROTECT_TYPE_NONE 0
+#define MLME_SETPROTECTION_PROTECT_TYPE_RX 1
+#define MLME_SETPROTECTION_PROTECT_TYPE_TX 2
+#define MLME_SETPROTECTION_PROTECT_TYPE_RX_TX 3
+
+#define MLME_SETPROTECTION_KEY_TYPE_GROUP 0
+#define MLME_SETPROTECTION_KEY_TYPE_PAIRWISE 1
+
+
+/**
+ * enum mfp_options - Management frame protection (IEEE 802.11w) options
+ */
+enum mfp_options {
+ NO_MGMT_FRAME_PROTECTION = 0,
+ MGMT_FRAME_PROTECTION_OPTIONAL = 1,
+ MGMT_FRAME_PROTECTION_REQUIRED = 2
+};
+
+/**
+ * enum hostapd_hw_mode - Hardware mode
+ */
+enum hostapd_hw_mode {
+ HOSTAPD_MODE_IEEE80211B,
+ HOSTAPD_MODE_IEEE80211G,
+ HOSTAPD_MODE_IEEE80211A,
+ NUM_HOSTAPD_MODES
+};
+
+#endif /* DEFS_H */
diff --git a/src/common/eapol_common.h b/src/common/eapol_common.h
new file mode 100644
index 0000000..d70e62d
--- /dev/null
+++ b/src/common/eapol_common.h
@@ -0,0 +1,47 @@
+/*
+ * EAPOL definitions shared between hostapd and wpa_supplicant
+ * Copyright (c) 2002-2007, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#ifndef EAPOL_COMMON_H
+#define EAPOL_COMMON_H
+
+/* IEEE Std 802.1X-2004 */
+
+#ifdef _MSC_VER
+#pragma pack(push, 1)
+#endif /* _MSC_VER */
+
+struct ieee802_1x_hdr {
+ u8 version;
+ u8 type;
+ be16 length;
+ /* followed by length octets of data */
+} STRUCT_PACKED;
+
+#ifdef _MSC_VER
+#pragma pack(pop)
+#endif /* _MSC_VER */
+
+#define EAPOL_VERSION 2
+
+enum { IEEE802_1X_TYPE_EAP_PACKET = 0,
+ IEEE802_1X_TYPE_EAPOL_START = 1,
+ IEEE802_1X_TYPE_EAPOL_LOGOFF = 2,
+ IEEE802_1X_TYPE_EAPOL_KEY = 3,
+ IEEE802_1X_TYPE_EAPOL_ENCAPSULATED_ASF_ALERT = 4
+};
+
+enum { EAPOL_KEY_TYPE_RC4 = 1, EAPOL_KEY_TYPE_RSN = 2,
+ EAPOL_KEY_TYPE_WPA = 254 };
+
+#endif /* EAPOL_COMMON_H */
diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c
new file mode 100644
index 0000000..ee41b3a
--- /dev/null
+++ b/src/common/ieee802_11_common.c
@@ -0,0 +1,347 @@
+/*
+ * IEEE 802.11 Common routines
+ * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#include "includes.h"
+
+#include "common.h"
+#include "ieee802_11_defs.h"
+#include "ieee802_11_common.h"
+
+
+static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen,
+ struct ieee802_11_elems *elems,
+ int show_errors)
+{
+ unsigned int oui;
+
+ /* first 3 bytes in vendor specific information element are the IEEE
+ * OUI of the vendor. The following byte is used a vendor specific
+ * sub-type. */
+ if (elen < 4) {
+ if (show_errors) {
+ wpa_printf(MSG_MSGDUMP, "short vendor specific "
+ "information element ignored (len=%lu)",
+ (unsigned long) elen);
+ }
+ return -1;
+ }
+
+ oui = WPA_GET_BE24(pos);
+ switch (oui) {
+ case OUI_MICROSOFT:
+ /* Microsoft/Wi-Fi information elements are further typed and
+ * subtyped */
+ switch (pos[3]) {
+ case 1:
+ /* Microsoft OUI (00:50:F2) with OUI Type 1:
+ * real WPA information element */
+ elems->wpa_ie = pos;
+ elems->wpa_ie_len = elen;
+ break;
+ case WMM_OUI_TYPE:
+ /* WMM information element */
+ if (elen < 5) {
+ wpa_printf(MSG_MSGDUMP, "short WMM "
+ "information element ignored "
+ "(len=%lu)",
+ (unsigned long) elen);
+ return -1;
+ }
+ switch (pos[4]) {
+ case WMM_OUI_SUBTYPE_INFORMATION_ELEMENT:
+ case WMM_OUI_SUBTYPE_PARAMETER_ELEMENT:
+ /*
+ * Share same pointer since only one of these
+ * is used and they start with same data.
+ * Length field can be used to distinguish the
+ * IEs.
+ */
+ elems->wmm = pos;
+ elems->wmm_len = elen;
+ break;
+ case WMM_OUI_SUBTYPE_TSPEC_ELEMENT:
+ elems->wmm_tspec = pos;
+ elems->wmm_tspec_len = elen;
+ break;
+ default:
+ wpa_printf(MSG_EXCESSIVE, "unknown WMM "
+ "information element ignored "
+ "(subtype=%d len=%lu)",
+ pos[4], (unsigned long) elen);
+ return -1;
+ }
+ break;
+ case 4:
+ /* Wi-Fi Protected Setup (WPS) IE */
+ elems->wps_ie = pos;
+ elems->wps_ie_len = elen;
+ break;
+ default:
+ wpa_printf(MSG_EXCESSIVE, "Unknown Microsoft "
+ "information element ignored "
+ "(type=%d len=%lu)",
+ pos[3], (unsigned long) elen);
+ return -1;
+ }
+ break;
+
+ case OUI_WFA:
+ switch (pos[3]) {
+ case P2P_OUI_TYPE:
+ /* Wi-Fi Alliance - P2P IE */
+ elems->p2p = pos;
+ elems->p2p_len = elen;
+ break;
+ default:
+ wpa_printf(MSG_MSGDUMP, "Unknown WFA "
+ "information element ignored "
+ "(type=%d len=%lu)\n",
+ pos[3], (unsigned long) elen);
+ return -1;
+ }
+ break;
+
+ case OUI_BROADCOM:
+ switch (pos[3]) {
+ case VENDOR_HT_CAPAB_OUI_TYPE:
+ elems->vendor_ht_cap = pos;
+ elems->vendor_ht_cap_len = elen;
+ break;
+ default:
+ wpa_printf(MSG_EXCESSIVE, "Unknown Broadcom "
+ "information element ignored "
+ "(type=%d len=%lu)",
+ pos[3], (unsigned long) elen);
+ return -1;
+ }
+ break;
+
+ default:
+ wpa_printf(MSG_EXCESSIVE, "unknown vendor specific "
+ "information element ignored (vendor OUI "
+ "%02x:%02x:%02x len=%lu)",
+ pos[0], pos[1], pos[2], (unsigned long) elen);
+ return -1;
+ }
+
+ return 0;
+}
+
+
+/**
+ * ieee802_11_parse_elems - Parse information elements in management frames
+ * @start: Pointer to the start of IEs
+ * @len: Length of IE buffer in octets
+ * @elems: Data structure for parsed elements
+ * @show_errors: Whether to show parsing errors in debug log
+ * Returns: Parsing result
+ */
+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;
+ int unknown = 0;
+
+ os_memset(elems, 0, sizeof(*elems));
+
+ while (left >= 2) {
+ u8 id, elen;
+
+ 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;
+ }
+
+ switch (id) {
+ case WLAN_EID_SSID:
+ elems->ssid = pos;
+ elems->ssid_len = elen;
+ break;
+ case WLAN_EID_SUPP_RATES:
+ elems->supp_rates = pos;
+ elems->supp_rates_len = elen;
+ break;
+ case WLAN_EID_FH_PARAMS:
+ elems->fh_params = pos;
+ elems->fh_params_len = elen;
+ break;
+ case WLAN_EID_DS_PARAMS:
+ elems->ds_params = pos;
+ elems->ds_params_len = elen;
+ break;
+ case WLAN_EID_CF_PARAMS:
+ elems->cf_params = pos;
+ elems->cf_params_len = elen;
+ break;
+ case WLAN_EID_TIM:
+ elems->tim = pos;
+ elems->tim_len = elen;
+ break;
+ case WLAN_EID_IBSS_PARAMS:
+ elems->ibss_params = pos;
+ elems->ibss_params_len = elen;
+ break;
+ case WLAN_EID_CHALLENGE:
+ elems->challenge = pos;
+ elems->challenge_len = elen;
+ break;
+ case WLAN_EID_ERP_INFO:
+ elems->erp_info = pos;
+ elems->erp_info_len = elen;
+ break;
+ case WLAN_EID_EXT_SUPP_RATES:
+ elems->ext_supp_rates = pos;
+ elems->ext_supp_rates_len = elen;
+ break;
+ case WLAN_EID_VENDOR_SPECIFIC:
+ if (ieee802_11_parse_vendor_specific(pos, elen,
+ elems,
+ show_errors))
+ unknown++;
+ break;
+ case WLAN_EID_RSN:
+ elems->rsn_ie = pos;
+ elems->rsn_ie_len = elen;
+ break;
+ case WLAN_EID_PWR_CAPABILITY:
+ elems->power_cap = pos;
+ elems->power_cap_len = elen;
+ break;
+ case WLAN_EID_SUPPORTED_CHANNELS:
+ elems->supp_channels = pos;
+ elems->supp_channels_len = elen;
+ break;
+ case WLAN_EID_MOBILITY_DOMAIN:
+ elems->mdie = pos;
+ elems->mdie_len = elen;
+ break;
+ case WLAN_EID_FAST_BSS_TRANSITION:
+ elems->ftie = pos;
+ elems->ftie_len = elen;
+ break;
+ case WLAN_EID_TIMEOUT_INTERVAL:
+ elems->timeout_int = pos;
+ elems->timeout_int_len = elen;
+ break;
+ case WLAN_EID_HT_CAP:
+ elems->ht_capabilities = pos;
+ elems->ht_capabilities_len = elen;
+ break;
+ case WLAN_EID_HT_OPERATION:
+ elems->ht_operation = pos;
+ elems->ht_operation_len = elen;
+ break;
+ case WLAN_EID_LINK_ID:
+ if (elen < 18)
+ break;
+ elems->link_id = pos;
+ break;
+ default:
+ unknown++;
+ if (!show_errors)
+ break;
+ wpa_printf(MSG_MSGDUMP, "IEEE 802.11 element parse "
+ "ignored unknown element (id=%d elen=%d)",
+ id, elen);
+ break;
+ }
+
+ left -= elen;
+ pos += elen;
+ }
+
+ if (left)
+ return ParseFailed;
+
+ return unknown ? ParseUnknown : ParseOK;
+}
+
+
+int ieee802_11_ie_count(const u8 *ies, size_t ies_len)
+{
+ int count = 0;
+ const u8 *pos, *end;
+
+ if (ies == NULL)
+ return 0;
+
+ pos = ies;
+ end = ies + ies_len;
+
+ while (pos + 2 <= end) {
+ if (pos + 2 + pos[1] > end)
+ break;
+ count++;
+ pos += 2 + pos[1];
+ }
+
+ return count;
+}
+
+
+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;
+
+ pos = ies;
+ end = ies + ies_len;
+ ie = NULL;
+
+ while (pos + 1 < end) {
+ if (pos + 2 + pos[1] > end)
+ return NULL;
+ if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
+ WPA_GET_BE32(&pos[2]) == oui_type) {
+ ie = pos;
+ break;
+ }
+ pos += 2 + pos[1];
+ }
+
+ if (ie == NULL)
+ return NULL; /* No specified vendor IE found */
+
+ buf = wpabuf_alloc(ies_len);
+ if (buf == NULL)
+ return NULL;
+
+ /*
+ * There may be multiple vendor IEs in the message, so need to
+ * concatenate their data fields.
+ */
+ while (pos + 1 < end) {
+ if (pos + 2 + pos[1] > end)
+ 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];
+ }
+
+ return buf;
+}
diff --git a/src/common/ieee802_11_common.h b/src/common/ieee802_11_common.h
new file mode 100644
index 0000000..0c90fa4
--- /dev/null
+++ b/src/common/ieee802_11_common.h
@@ -0,0 +1,81 @@
+/*
+ * IEEE 802.11 Common routines
+ * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#ifndef IEEE802_11_COMMON_H
+#define IEEE802_11_COMMON_H
+
+/* Parsed Information Elements */
+struct ieee802_11_elems {
+ const u8 *ssid;
+ const u8 *supp_rates;
+ const u8 *fh_params;
+ const u8 *ds_params;
+ const u8 *cf_params;
+ const u8 *tim;
+ const u8 *ibss_params;
+ const u8 *challenge;
+ const u8 *erp_info;
+ const u8 *ext_supp_rates;
+ const u8 *wpa_ie;
+ const u8 *rsn_ie;
+ const u8 *wmm; /* WMM Information or Parameter Element */
+ const u8 *wmm_tspec;
+ const u8 *wps_ie;
+ const u8 *power_cap;
+ const u8 *supp_channels;
+ const u8 *mdie;
+ const u8 *ftie;
+ const u8 *timeout_int;
+ const u8 *ht_capabilities;
+ const u8 *ht_operation;
+ const u8 *vendor_ht_cap;
+ const u8 *p2p;
+ const u8 *link_id;
+
+ u8 ssid_len;
+ u8 supp_rates_len;
+ u8 fh_params_len;
+ u8 ds_params_len;
+ u8 cf_params_len;
+ u8 tim_len;
+ u8 ibss_params_len;
+ u8 challenge_len;
+ u8 erp_info_len;
+ u8 ext_supp_rates_len;
+ u8 wpa_ie_len;
+ u8 rsn_ie_len;
+ u8 wmm_len; /* 7 = WMM Information; 24 = WMM Parameter */
+ u8 wmm_tspec_len;
+ u8 wps_ie_len;
+ u8 power_cap_len;
+ u8 supp_channels_len;
+ u8 mdie_len;
+ u8 ftie_len;
+ u8 timeout_int_len;
+ u8 ht_capabilities_len;
+ u8 ht_operation_len;
+ u8 vendor_ht_cap_len;
+ u8 p2p_len;
+};
+
+typedef enum { ParseOK = 0, ParseUnknown = 1, ParseFailed = -1 } ParseRes;
+
+ParseRes ieee802_11_parse_elems(const u8 *start, size_t len,
+ struct ieee802_11_elems *elems,
+ int show_errors);
+int ieee802_11_ie_count(const u8 *ies, size_t ies_len);
+struct wpabuf * ieee802_11_vendor_ie_concat(const u8 *ies, size_t ies_len,
+ u32 oui_type);
+
+#endif /* IEEE802_11_COMMON_H */
diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
new file mode 100644
index 0000000..86868c0
--- /dev/null
+++ b/src/common/ieee802_11_defs.h
@@ -0,0 +1,800 @@
+/*
+ * IEEE 802.11 Frame type definitions
+ * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2007-2008 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#ifndef IEEE802_11_DEFS_H
+#define IEEE802_11_DEFS_H
+
+/* IEEE 802.11 defines */
+
+#define WLAN_FC_PVER 0x0003
+#define WLAN_FC_TODS 0x0100
+#define WLAN_FC_FROMDS 0x0200
+#define WLAN_FC_MOREFRAG 0x0400
+#define WLAN_FC_RETRY 0x0800
+#define WLAN_FC_PWRMGT 0x1000
+#define WLAN_FC_MOREDATA 0x2000
+#define WLAN_FC_ISWEP 0x4000
+#define WLAN_FC_ORDER 0x8000
+
+#define WLAN_FC_GET_TYPE(fc) (((fc) & 0x000c) >> 2)
+#define WLAN_FC_GET_STYPE(fc) (((fc) & 0x00f0) >> 4)
+
+#define WLAN_GET_SEQ_FRAG(seq) ((seq) & (BIT(3) | BIT(2) | BIT(1) | BIT(0)))
+#define WLAN_GET_SEQ_SEQ(seq) \
+ (((seq) & (~(BIT(3) | BIT(2) | BIT(1) | BIT(0)))) >> 4)
+
+#define WLAN_FC_TYPE_MGMT 0
+#define WLAN_FC_TYPE_CTRL 1
+#define WLAN_FC_TYPE_DATA 2
+
+/* management */
+#define WLAN_FC_STYPE_ASSOC_REQ 0
+#define WLAN_FC_STYPE_ASSOC_RESP 1
+#define WLAN_FC_STYPE_REASSOC_REQ 2
+#define WLAN_FC_STYPE_REASSOC_RESP 3
+#define WLAN_FC_STYPE_PROBE_REQ 4
+#define WLAN_FC_STYPE_PROBE_RESP 5
+#define WLAN_FC_STYPE_BEACON 8
+#define WLAN_FC_STYPE_ATIM 9
+#define WLAN_FC_STYPE_DISASSOC 10
+#define WLAN_FC_STYPE_AUTH 11
+#define WLAN_FC_STYPE_DEAUTH 12
+#define WLAN_FC_STYPE_ACTION 13
+
+/* control */
+#define WLAN_FC_STYPE_PSPOLL 10
+#define WLAN_FC_STYPE_RTS 11
+#define WLAN_FC_STYPE_CTS 12
+#define WLAN_FC_STYPE_ACK 13
+#define WLAN_FC_STYPE_CFEND 14
+#define WLAN_FC_STYPE_CFENDACK 15
+
+/* data */
+#define WLAN_FC_STYPE_DATA 0
+#define WLAN_FC_STYPE_DATA_CFACK 1
+#define WLAN_FC_STYPE_DATA_CFPOLL 2
+#define WLAN_FC_STYPE_DATA_CFACKPOLL 3
+#define WLAN_FC_STYPE_NULLFUNC 4
+#define WLAN_FC_STYPE_CFACK 5
+#define WLAN_FC_STYPE_CFPOLL 6
+#define WLAN_FC_STYPE_CFACKPOLL 7
+#define WLAN_FC_STYPE_QOS_DATA 8
+#define WLAN_FC_STYPE_QOS_DATA_CFACK 9
+#define WLAN_FC_STYPE_QOS_DATA_CFPOLL 10
+#define WLAN_FC_STYPE_QOS_DATA_CFACKPOLL 11
+#define WLAN_FC_STYPE_QOS_NULL 12
+#define WLAN_FC_STYPE_QOS_CFPOLL 14
+#define WLAN_FC_STYPE_QOS_CFACKPOLL 15
+
+/* Authentication algorithms */
+#define WLAN_AUTH_OPEN 0
+#define WLAN_AUTH_SHARED_KEY 1
+#define WLAN_AUTH_FT 2
+#define WLAN_AUTH_LEAP 128
+
+#define WLAN_AUTH_CHALLENGE_LEN 128
+
+#define WLAN_CAPABILITY_ESS BIT(0)
+#define WLAN_CAPABILITY_IBSS BIT(1)
+#define WLAN_CAPABILITY_CF_POLLABLE BIT(2)
+#define WLAN_CAPABILITY_CF_POLL_REQUEST BIT(3)
+#define WLAN_CAPABILITY_PRIVACY BIT(4)
+#define WLAN_CAPABILITY_SHORT_PREAMBLE BIT(5)
+#define WLAN_CAPABILITY_PBCC BIT(6)
+#define WLAN_CAPABILITY_CHANNEL_AGILITY BIT(7)
+#define WLAN_CAPABILITY_SPECTRUM_MGMT BIT(8)
+#define WLAN_CAPABILITY_SHORT_SLOT_TIME BIT(10)
+#define WLAN_CAPABILITY_DSSS_OFDM BIT(13)
+
+/* Status codes (IEEE 802.11-2007, 7.3.1.9, Table 7-23) */
+#define WLAN_STATUS_SUCCESS 0
+#define WLAN_STATUS_UNSPECIFIED_FAILURE 1
+#define WLAN_STATUS_TDLS_WAKEUP_ALTERNATE 2
+#define WLAN_STATUS_TDLS_WAKEUP_REJECT 3
+#define WLAN_STATUS_SECURITY_DISABLED 5
+#define WLAN_STATUS_UNACCEPTABLE_LIFETIME 6
+#define WLAN_STATUS_NOT_IN_SAME_BSS 7
+#define WLAN_STATUS_CAPS_UNSUPPORTED 10
+#define WLAN_STATUS_REASSOC_NO_ASSOC 11
+#define WLAN_STATUS_ASSOC_DENIED_UNSPEC 12
+#define WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG 13
+#define WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION 14
+#define WLAN_STATUS_CHALLENGE_FAIL 15
+#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_REQUEST_DECLINED 37
+#define WLAN_STATUS_INVALID_PARAMETERS 38
+/* IEEE 802.11i */
+#define WLAN_STATUS_INVALID_IE 40
+#define WLAN_STATUS_GROUP_CIPHER_NOT_VALID 41
+#define WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID 42
+#define WLAN_STATUS_AKMP_NOT_VALID 43
+#define WLAN_STATUS_UNSUPPORTED_RSN_IE_VERSION 44
+#define WLAN_STATUS_INVALID_RSN_IE_CAPAB 45
+#define WLAN_STATUS_CIPHER_REJECTED_PER_POLICY 46
+#define WLAN_STATUS_TS_NOT_CREATED 47
+#define WLAN_STATUS_DIRECT_LINK_NOT_ALLOWED 48
+#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_INVALID_RSNIE 72
+
+/* Reason codes (IEEE 802.11-2007, 7.3.1.7, Table 7-22) */
+#define WLAN_REASON_UNSPECIFIED 1
+#define WLAN_REASON_PREV_AUTH_NOT_VALID 2
+#define WLAN_REASON_DEAUTH_LEAVING 3
+#define WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY 4
+#define WLAN_REASON_DISASSOC_AP_BUSY 5
+#define WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA 6
+#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_INVALID_IE 13
+#define WLAN_REASON_MICHAEL_MIC_FAILURE 14
+#define WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT 15
+#define WLAN_REASON_GROUP_KEY_UPDATE_TIMEOUT 16
+#define WLAN_REASON_IE_IN_4WAY_DIFFERS 17
+#define WLAN_REASON_GROUP_CIPHER_NOT_VALID 18
+#define WLAN_REASON_PAIRWISE_CIPHER_NOT_VALID 19
+#define WLAN_REASON_AKMP_NOT_VALID 20
+#define WLAN_REASON_UNSUPPORTED_RSN_IE_VERSION 21
+#define WLAN_REASON_INVALID_RSN_IE_CAPAB 22
+#define WLAN_REASON_IEEE_802_1X_AUTH_FAILED 23
+#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_DISASSOC_LOW_ACK 34
+
+
+/* Information Element IDs */
+#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_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
+#define WLAN_EID_TPC_REPORT 35
+#define WLAN_EID_SUPPORTED_CHANNELS 36
+#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_IBSS_DFS 41
+/* EIDs defined by IEEE 802.11h - END */
+#define WLAN_EID_ERP_INFO 42
+#define WLAN_EID_HT_CAP 45
+#define WLAN_EID_RSN 48
+#define WLAN_EID_EXT_SUPP_RATES 50
+#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_HT_OPERATION 61
+#define WLAN_EID_SECONDARY_CHANNEL_OFFSET 62
+#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_MMIE 76
+#define WLAN_EID_LINK_ID 101
+#define WLAN_EID_ADV_PROTO 108
+#define WLAN_EID_EXT_CAPAB 127
+#define WLAN_EID_VENDOR_SPECIFIC 221
+
+
+/* Action frame categories (IEEE 802.11-2007, 7.3.1.11, Table 7-24) */
+#define WLAN_ACTION_SPECTRUM_MGMT 0
+#define WLAN_ACTION_QOS 1
+#define WLAN_ACTION_DLS 2
+#define WLAN_ACTION_BLOCK_ACK 3
+#define WLAN_ACTION_PUBLIC 4
+#define WLAN_ACTION_RADIO_MEASUREMENT 5
+#define WLAN_ACTION_FT 6
+#define WLAN_ACTION_HT 7
+#define WLAN_ACTION_SA_QUERY 8
+#define WLAN_ACTION_TDLS 12
+#define WLAN_ACTION_WMM 17 /* WMM Specification 1.1 */
+#define WLAN_ACTION_VENDOR_SPECIFIC 127
+
+/* Public action codes */
+#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
+
+/* SA Query Action frame (IEEE 802.11w/D8.0, 7.4.9) */
+#define WLAN_SA_QUERY_REQUEST 0
+#define WLAN_SA_QUERY_RESPONSE 1
+
+#define WLAN_SA_QUERY_TR_ID_LEN 2
+
+/* TDLS action codes */
+#define WLAN_TDLS_SETUP_REQUEST 0
+#define WLAN_TDLS_SETUP_RESPONSE 1
+#define WLAN_TDLS_SETUP_CONFIRM 2
+#define WLAN_TDLS_TEARDOWN 3
+#define WLAN_TDLS_PEER_TRAFFIC_INDICATION 4
+#define WLAN_TDLS_CHANNEL_SWITCH_REQUEST 5
+#define WLAN_TDLS_CHANNEL_SWITCH_RESPONSE 6
+#define WLAN_TDLS_PEER_PSM_REQUEST 7
+#define WLAN_TDLS_PEER_PSM_RESPONSE 8
+#define WLAN_TDLS_PEER_TRAFFIC_RESPONSE 9
+#define WLAN_TDLS_DISCOVERY_REQUEST 10
+
+/* Timeout Interval Type */
+#define WLAN_TIMEOUT_REASSOC_DEADLINE 1
+#define WLAN_TIMEOUT_KEY_LIFETIME 2
+#define WLAN_TIMEOUT_ASSOC_COMEBACK 3
+
+/* Advertisement Protocol ID definitions (IEEE 802.11u) */
+enum adv_proto_id {
+ NATIVE_QUERY_PROTOCOL = 0,
+ MIH_INFO_SERVICE = 1,
+ MIH_CMD_AND_EVENT_DISCOVERY = 2,
+ EMERGENCY_ALERT_SYSTEM = 3,
+ LOCATION_TO_SERVICE = 4,
+ ADV_PROTO_VENDOR_SPECIFIC = 221
+};
+
+/* Native Query Protocol info ID definitions (IEEE 802.11u) */
+enum nqp_info_id {
+ NQP_CAPABILITY_LIST = 256,
+ NQP_VENUE_NAME = 257,
+ NQP_EMERGENCY_CALL_NUMBER = 258,
+ NQP_NETWORK_AUTH_TYPE = 259,
+ NQP_ROAMING_CONSORTIUM = 260,
+ NQP_IP_ADDR_TYPE_AVAILABILITY = 261,
+ NQP_NAI_REALM = 262,
+ NQP_3GPP_CELLULAR_NETWORK = 263,
+ NQP_AP_GEOSPATIAL_LOCATION = 264,
+ NQP_AP_CIVIC_LOCATION = 265,
+ NQP_DOMAIN_NAME = 266,
+ NQP_EMERGENCY_ALERT_URI = 267,
+ NQP_VENDOR_SPECIFIC = 56797
+};
+
+
+#ifdef _MSC_VER
+#pragma pack(push, 1)
+#endif /* _MSC_VER */
+
+struct ieee80211_hdr {
+ le16 frame_control;
+ le16 duration_id;
+ u8 addr1[6];
+ u8 addr2[6];
+ u8 addr3[6];
+ le16 seq_ctrl;
+ /* followed by 'u8 addr4[6];' if ToDS and FromDS is set in data frame
+ */
+} STRUCT_PACKED;
+
+#define IEEE80211_DA_FROMDS addr1
+#define IEEE80211_BSSID_FROMDS addr2
+#define IEEE80211_SA_FROMDS addr3
+
+#define IEEE80211_HDRLEN (sizeof(struct ieee80211_hdr))
+
+#define IEEE80211_FC(type, stype) host_to_le16((type << 2) | (stype << 4))
+
+struct ieee80211_mgmt {
+ le16 frame_control;
+ le16 duration;
+ u8 da[6];
+ u8 sa[6];
+ u8 bssid[6];
+ le16 seq_ctrl;
+ union {
+ struct {
+ le16 auth_alg;
+ le16 auth_transaction;
+ le16 status_code;
+ /* possibly followed by Challenge text */
+ u8 variable[0];
+ } STRUCT_PACKED auth;
+ struct {
+ le16 reason_code;
+ u8 variable[0];
+ } STRUCT_PACKED deauth;
+ struct {
+ le16 capab_info;
+ le16 listen_interval;
+ /* followed by SSID and Supported rates */
+ u8 variable[0];
+ } STRUCT_PACKED assoc_req;
+ struct {
+ le16 capab_info;
+ le16 status_code;
+ le16 aid;
+ /* followed by Supported rates */
+ u8 variable[0];
+ } STRUCT_PACKED assoc_resp, reassoc_resp;
+ struct {
+ le16 capab_info;
+ le16 listen_interval;
+ u8 current_ap[6];
+ /* followed by SSID and Supported rates */
+ u8 variable[0];
+ } STRUCT_PACKED reassoc_req;
+ struct {
+ le16 reason_code;
+ u8 variable[0];
+ } STRUCT_PACKED disassoc;
+ struct {
+ u8 timestamp[8];
+ le16 beacon_int;
+ le16 capab_info;
+ /* followed by some of SSID, Supported rates,
+ * FH Params, DS Params, CF Params, IBSS Params, TIM */
+ u8 variable[0];
+ } STRUCT_PACKED beacon;
+ struct {
+ /* only variable items: SSID, Supported rates */
+ u8 variable[0];
+ } STRUCT_PACKED probe_req;
+ struct {
+ u8 timestamp[8];
+ le16 beacon_int;
+ le16 capab_info;
+ /* followed by some of SSID, Supported rates,
+ * FH Params, DS Params, CF Params, IBSS Params */
+ u8 variable[0];
+ } STRUCT_PACKED probe_resp;
+ struct {
+ u8 category;
+ union {
+ struct {
+ u8 action_code;
+ u8 dialog_token;
+ u8 status_code;
+ u8 variable[0];
+ } STRUCT_PACKED wmm_action;
+ struct{
+ u8 action_code;
+ u8 element_id;
+ u8 length;
+ u8 switch_mode;
+ u8 new_chan;
+ u8 switch_count;
+ } STRUCT_PACKED chan_switch;
+ struct {
+ u8 action;
+ u8 sta_addr[ETH_ALEN];
+ u8 target_ap_addr[ETH_ALEN];
+ u8 variable[0]; /* FT Request */
+ } STRUCT_PACKED ft_action_req;
+ struct {
+ u8 action;
+ u8 sta_addr[ETH_ALEN];
+ u8 target_ap_addr[ETH_ALEN];
+ le16 status_code;
+ u8 variable[0]; /* FT Request */
+ } STRUCT_PACKED ft_action_resp;
+ struct {
+ u8 action;
+ u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN];
+ } STRUCT_PACKED sa_query_req;
+ struct {
+ u8 action; /* */
+ u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN];
+ } STRUCT_PACKED sa_query_resp;
+ struct {
+ u8 action;
+ u8 variable[0];
+ } STRUCT_PACKED public_action;
+ struct {
+ u8 action; /* 9 */
+ u8 oui[3];
+ /* Vendor-specific content */
+ u8 variable[0];
+ } STRUCT_PACKED vs_public_action;
+ } u;
+ } STRUCT_PACKED action;
+ } u;
+} STRUCT_PACKED;
+
+
+struct ieee80211_ht_capabilities {
+ le16 ht_capabilities_info;
+ u8 a_mpdu_params;
+ u8 supported_mcs_set[16];
+ le16 ht_extended_capabilities;
+ le32 tx_bf_capability_info;
+ u8 asel_capabilities;
+} STRUCT_PACKED;
+
+
+struct ieee80211_ht_operation {
+ u8 control_chan;
+ u8 ht_param;
+ le16 operation_mode;
+ le16 stbc_param;
+ u8 basic_set[16];
+} STRUCT_PACKED;
+
+#ifdef _MSC_VER
+#pragma pack(pop)
+#endif /* _MSC_VER */
+
+#define ERP_INFO_NON_ERP_PRESENT BIT(0)
+#define ERP_INFO_USE_PROTECTION BIT(1)
+#define ERP_INFO_BARKER_PREAMBLE_MODE BIT(2)
+
+
+#define HT_CAP_INFO_LDPC_CODING_CAP ((u16) BIT(0))
+#define HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET ((u16) BIT(1))
+#define HT_CAP_INFO_SMPS_MASK ((u16) (BIT(2) | BIT(3)))
+#define HT_CAP_INFO_SMPS_STATIC ((u16) 0)
+#define HT_CAP_INFO_SMPS_DYNAMIC ((u16) BIT(2))
+#define HT_CAP_INFO_SMPS_DISABLED ((u16) (BIT(2) | BIT(3)))
+#define HT_CAP_INFO_GREEN_FIELD ((u16) BIT(4))
+#define HT_CAP_INFO_SHORT_GI20MHZ ((u16) BIT(5))
+#define HT_CAP_INFO_SHORT_GI40MHZ ((u16) BIT(6))
+#define HT_CAP_INFO_TX_STBC ((u16) BIT(7))
+#define HT_CAP_INFO_RX_STBC_MASK ((u16) (BIT(8) | BIT(9)))
+#define HT_CAP_INFO_RX_STBC_1 ((u16) BIT(8))
+#define HT_CAP_INFO_RX_STBC_12 ((u16) BIT(9))
+#define HT_CAP_INFO_RX_STBC_123 ((u16) (BIT(8) | BIT(9)))
+#define HT_CAP_INFO_DELAYED_BA ((u16) BIT(10))
+#define HT_CAP_INFO_MAX_AMSDU_SIZE ((u16) BIT(11))
+#define HT_CAP_INFO_DSSS_CCK40MHZ ((u16) BIT(12))
+#define HT_CAP_INFO_PSMP_SUPP ((u16) BIT(13))
+#define HT_CAP_INFO_40MHZ_INTOLERANT ((u16) BIT(14))
+#define HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT ((u16) BIT(15))
+
+
+#define EXT_HT_CAP_INFO_PCO ((u16) BIT(0))
+#define EXT_HT_CAP_INFO_TRANS_TIME_OFFSET 1
+#define EXT_HT_CAP_INFO_MCS_FEEDBACK_OFFSET 8
+#define EXT_HT_CAP_INFO_HTC_SUPPORTED ((u16) BIT(10))
+#define EXT_HT_CAP_INFO_RD_RESPONDER ((u16) BIT(11))
+
+
+#define TX_BEAMFORM_CAP_TXBF_CAP ((u32) BIT(0))
+#define TX_BEAMFORM_CAP_RX_STAGGERED_SOUNDING_CAP ((u32) BIT(1))
+#define TX_BEAMFORM_CAP_TX_STAGGERED_SOUNDING_CAP ((u32) BIT(2))
+#define TX_BEAMFORM_CAP_RX_ZLF_CAP ((u32) BIT(3))
+#define TX_BEAMFORM_CAP_TX_ZLF_CAP ((u32) BIT(4))
+#define TX_BEAMFORM_CAP_IMPLICIT_ZLF_CAP ((u32) BIT(5))
+#define TX_BEAMFORM_CAP_CALIB_OFFSET 6
+#define TX_BEAMFORM_CAP_EXPLICIT_CSI_TXBF_CAP ((u32) BIT(8))
+#define TX_BEAMFORM_CAP_EXPLICIT_UNCOMPR_STEERING_MATRIX_CAP ((u32) BIT(9))
+#define TX_BEAMFORM_CAP_EXPLICIT_BF_CSI_FEEDBACK_CAP ((u32) BIT(10))
+#define TX_BEAMFORM_CAP_EXPLICIT_BF_CSI_FEEDBACK_OFFSET 11
+#define TX_BEAMFORM_CAP_EXPLICIT_UNCOMPR_STEERING_MATRIX_FEEDBACK_OFFSET 13
+#define TX_BEAMFORM_CAP_EXPLICIT_COMPRESSED_STEERING_MATRIX_FEEDBACK_OFFSET 15
+#define TX_BEAMFORM_CAP_MINIMAL_GROUPING_OFFSET 17
+#define TX_BEAMFORM_CAP_CSI_NUM_BEAMFORMER_ANT_OFFSET 19
+#define TX_BEAMFORM_CAP_UNCOMPRESSED_STEERING_MATRIX_BEAMFORMER_ANT_OFFSET 21
+#define TX_BEAMFORM_CAP_COMPRESSED_STEERING_MATRIX_BEAMFORMER_ANT_OFFSET 23
+#define TX_BEAMFORM_CAP_SCI_MAX_OF_ROWS_BEANFORMER_SUPPORTED_OFFSET 25
+
+
+#define ASEL_CAPABILITY_ASEL_CAPABLE ((u8) BIT(0))
+#define ASEL_CAPABILITY_EXPLICIT_CSI_FEEDBACK_BASED_TX_AS_CAP ((u8) BIT(1))
+#define ASEL_CAPABILITY_ANT_INDICES_FEEDBACK_BASED_TX_AS_CAP ((u8) BIT(2))
+#define ASEL_CAPABILITY_EXPLICIT_CSI_FEEDBACK_CAP ((u8) BIT(3))
+#define ASEL_CAPABILITY_ANT_INDICES_FEEDBACK_CAP ((u8) BIT(4))
+#define ASEL_CAPABILITY_RX_AS_CAP ((u8) BIT(5))
+#define ASEL_CAPABILITY_TX_SOUND_PPDUS_CAP ((u8) BIT(6))
+
+#define HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK ((u8) BIT(0) | BIT(1))
+#define HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE ((u8) BIT(0))
+#define HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW ((u8) BIT(0) | BIT(1))
+#define HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH ((u8) BIT(2))
+#define HT_INFO_HT_PARAM_RIFS_MODE ((u8) BIT(3))
+#define HT_INFO_HT_PARAM_CTRL_ACCESS_ONLY ((u8) BIT(4))
+#define HT_INFO_HT_PARAM_SRV_INTERVAL_GRANULARITY ((u8) BIT(5))
+
+
+#define OP_MODE_PURE 0
+#define OP_MODE_MAY_BE_LEGACY_STAS 1
+#define OP_MODE_20MHZ_HT_STA_ASSOCED 2
+#define OP_MODE_MIXED 3
+
+#define HT_INFO_OPERATION_MODE_OP_MODE_MASK \
+ ((le16) (0x0001 | 0x0002))
+#define HT_INFO_OPERATION_MODE_OP_MODE_OFFSET 0
+#define HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT ((u8) BIT(2))
+#define HT_INFO_OPERATION_MODE_TRANSMIT_BURST_LIMIT ((u8) BIT(3))
+#define HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT ((u8) BIT(4))
+
+#define HT_INFO_STBC_PARAM_DUAL_BEACON ((u16) BIT(6))
+#define HT_INFO_STBC_PARAM_DUAL_STBC_PROTECT ((u16) BIT(7))
+#define HT_INFO_STBC_PARAM_SECONDARY_BCN ((u16) BIT(8))
+#define HT_INFO_STBC_PARAM_LSIG_TXOP_PROTECT_ALLOWED ((u16) BIT(9))
+#define HT_INFO_STBC_PARAM_PCO_ACTIVE ((u16) BIT(10))
+#define HT_INFO_STBC_PARAM_PCO_PHASE ((u16) BIT(11))
+
+#define BSS_MEMBERSHIP_SELECTOR_HT_PHY 127
+
+#define OUI_MICROSOFT 0x0050f2 /* Microsoft (also used in Wi-Fi specs)
+ * 00:50:F2 */
+#define WPA_IE_VENDOR_TYPE 0x0050f201
+#define WPS_IE_VENDOR_TYPE 0x0050f204
+#define OUI_WFA 0x506f9a
+#define P2P_IE_VENDOR_TYPE 0x506f9a09
+
+#define WMM_OUI_TYPE 2
+#define WMM_OUI_SUBTYPE_INFORMATION_ELEMENT 0
+#define WMM_OUI_SUBTYPE_PARAMETER_ELEMENT 1
+#define WMM_OUI_SUBTYPE_TSPEC_ELEMENT 2
+#define WMM_VERSION 1
+
+#define WMM_ACTION_CODE_ADDTS_REQ 0
+#define WMM_ACTION_CODE_ADDTS_RESP 1
+#define WMM_ACTION_CODE_DELTS 2
+
+#define WMM_ADDTS_STATUS_ADMISSION_ACCEPTED 0
+#define WMM_ADDTS_STATUS_INVALID_PARAMETERS 1
+/* 2 - Reserved */
+#define WMM_ADDTS_STATUS_REFUSED 3
+/* 4-255 - Reserved */
+
+/* WMM TSPEC Direction Field Values */
+#define WMM_TSPEC_DIRECTION_UPLINK 0
+#define WMM_TSPEC_DIRECTION_DOWNLINK 1
+/* 2 - Reserved */
+#define WMM_TSPEC_DIRECTION_BI_DIRECTIONAL 3
+
+/*
+ * WMM Information Element (used in (Re)Association Request frames; may also be
+ * used in Beacon frames)
+ */
+struct wmm_information_element {
+ /* Element ID: 221 (0xdd); Length: 7 */
+ /* required fields for WMM version 1 */
+ u8 oui[3]; /* 00:50:f2 */
+ u8 oui_type; /* 2 */
+ u8 oui_subtype; /* 0 */
+ u8 version; /* 1 for WMM version 1.0 */
+ u8 qos_info; /* AP/STA specific QoS info */
+
+} STRUCT_PACKED;
+
+#define WMM_AC_AIFSN_MASK 0x0f
+#define WMM_AC_AIFNS_SHIFT 0
+#define WMM_AC_ACM 0x10
+#define WMM_AC_ACI_MASK 0x60
+#define WMM_AC_ACI_SHIFT 5
+
+#define WMM_AC_ECWMIN_MASK 0x0f
+#define WMM_AC_ECWMIN_SHIFT 0
+#define WMM_AC_ECWMAX_MASK 0xf0
+#define WMM_AC_ECWMAX_SHIFT 4
+
+struct wmm_ac_parameter {
+ u8 aci_aifsn; /* AIFSN, ACM, ACI */
+ u8 cw; /* ECWmin, ECWmax (CW = 2^ECW - 1) */
+ le16 txop_limit;
+} STRUCT_PACKED;
+
+/*
+ * WMM Parameter Element (used in Beacon, Probe Response, and (Re)Association
+ * Response frmaes)
+ */
+struct wmm_parameter_element {
+ /* Element ID: 221 (0xdd); Length: 24 */
+ /* required fields for WMM version 1 */
+ u8 oui[3]; /* 00:50:f2 */
+ u8 oui_type; /* 2 */
+ u8 oui_subtype; /* 1 */
+ u8 version; /* 1 for WMM version 1.0 */
+ u8 qos_info; /* AP/STA specif QoS info */
+ u8 reserved; /* 0 */
+ struct wmm_ac_parameter ac[4]; /* AC_BE, AC_BK, AC_VI, AC_VO */
+
+} STRUCT_PACKED;
+
+/* WMM TSPEC Element */
+struct wmm_tspec_element {
+ u8 eid; /* 221 = 0xdd */
+ u8 length; /* 6 + 55 = 61 */
+ u8 oui[3]; /* 00:50:f2 */
+ u8 oui_type; /* 2 */
+ u8 oui_subtype; /* 2 */
+ u8 version; /* 1 */
+ /* WMM TSPEC body (55 octets): */
+ u8 ts_info[3];
+ le16 nominal_msdu_size;
+ le16 maximum_msdu_size;
+ le32 minimum_service_interval;
+ le32 maximum_service_interval;
+ le32 inactivity_interval;
+ le32 suspension_interval;
+ le32 service_start_time;
+ le32 minimum_data_rate;
+ le32 mean_data_rate;
+ le32 peak_data_rate;
+ le32 maximum_burst_size;
+ le32 delay_bound;
+ le32 minimum_phy_rate;
+ le16 surplus_bandwidth_allowance;
+ le16 medium_time;
+} STRUCT_PACKED;
+
+
+/* Access Categories / ACI to AC coding */
+enum {
+ WMM_AC_BE = 0 /* Best Effort */,
+ WMM_AC_BK = 1 /* Background */,
+ WMM_AC_VI = 2 /* Video */,
+ WMM_AC_VO = 3 /* Voice */
+};
+
+
+/* Wi-Fi Direct (P2P) */
+
+#define P2P_OUI_TYPE 9
+
+enum p2p_attr_id {
+ P2P_ATTR_STATUS = 0,
+ P2P_ATTR_MINOR_REASON_CODE = 1,
+ P2P_ATTR_CAPABILITY = 2,
+ P2P_ATTR_DEVICE_ID = 3,
+ P2P_ATTR_GROUP_OWNER_INTENT = 4,
+ P2P_ATTR_CONFIGURATION_TIMEOUT = 5,
+ P2P_ATTR_LISTEN_CHANNEL = 6,
+ P2P_ATTR_GROUP_BSSID = 7,
+ P2P_ATTR_EXT_LISTEN_TIMING = 8,
+ P2P_ATTR_INTENDED_INTERFACE_ADDR = 9,
+ P2P_ATTR_MANAGEABILITY = 10,
+ P2P_ATTR_CHANNEL_LIST = 11,
+ P2P_ATTR_NOTICE_OF_ABSENCE = 12,
+ P2P_ATTR_DEVICE_INFO = 13,
+ P2P_ATTR_GROUP_INFO = 14,
+ P2P_ATTR_GROUP_ID = 15,
+ P2P_ATTR_INTERFACE = 16,
+ P2P_ATTR_OPERATING_CHANNEL = 17,
+ P2P_ATTR_INVITATION_FLAGS = 18,
+ P2P_ATTR_VENDOR_SPECIFIC = 221
+};
+
+#define P2P_MAX_GO_INTENT 15
+
+/* P2P Capability - Device Capability bitmap */
+#define P2P_DEV_CAPAB_SERVICE_DISCOVERY BIT(0)
+#define P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY BIT(1)
+#define P2P_DEV_CAPAB_CONCURRENT_OPER BIT(2)
+#define P2P_DEV_CAPAB_INFRA_MANAGED BIT(3)
+#define P2P_DEV_CAPAB_DEVICE_LIMIT BIT(4)
+#define P2P_DEV_CAPAB_INVITATION_PROCEDURE BIT(5)
+
+/* P2P Capability - Group Capability bitmap */
+#define P2P_GROUP_CAPAB_GROUP_OWNER BIT(0)
+#define P2P_GROUP_CAPAB_PERSISTENT_GROUP BIT(1)
+#define P2P_GROUP_CAPAB_GROUP_LIMIT BIT(2)
+#define P2P_GROUP_CAPAB_INTRA_BSS_DIST BIT(3)
+#define P2P_GROUP_CAPAB_CROSS_CONN BIT(4)
+#define P2P_GROUP_CAPAB_PERSISTENT_RECONN BIT(5)
+#define P2P_GROUP_CAPAB_GROUP_FORMATION BIT(6)
+
+/* Invitation Flags */
+#define P2P_INVITATION_FLAGS_TYPE BIT(0)
+
+/* P2P Manageability */
+#define P2P_MAN_DEVICE_MANAGEMENT BIT(0)
+#define P2P_MAN_CROSS_CONNECTION_PERMITTED BIT(1)
+#define P2P_MAN_COEXISTENCE_OPTIONAL BIT(2)
+
+enum p2p_status_code {
+ P2P_SC_SUCCESS = 0,
+ P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE = 1,
+ P2P_SC_FAIL_INCOMPATIBLE_PARAMS = 2,
+ P2P_SC_FAIL_LIMIT_REACHED = 3,
+ P2P_SC_FAIL_INVALID_PARAMS = 4,
+ P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE = 5,
+ P2P_SC_FAIL_PREV_PROTOCOL_ERROR = 6,
+ P2P_SC_FAIL_NO_COMMON_CHANNELS = 7,
+ P2P_SC_FAIL_UNKNOWN_GROUP = 8,
+ P2P_SC_FAIL_BOTH_GO_INTENT_15 = 9,
+ P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD = 10,
+ P2P_SC_FAIL_REJECTED_BY_USER = 11,
+};
+
+#define P2P_WILDCARD_SSID "DIRECT-"
+#define P2P_WILDCARD_SSID_LEN 7
+
+/* P2P action frames */
+enum p2p_act_frame_type {
+ P2P_NOA = 0,
+ P2P_PRESENCE_REQ = 1,
+ P2P_PRESENCE_RESP = 2,
+ P2P_GO_DISC_REQ = 3
+};
+
+/* P2P public action frames */
+enum p2p_action_frame_type {
+ P2P_GO_NEG_REQ = 0,
+ P2P_GO_NEG_RESP = 1,
+ P2P_GO_NEG_CONF = 2,
+ P2P_INVITATION_REQ = 3,
+ P2P_INVITATION_RESP = 4,
+ P2P_DEV_DISC_REQ = 5,
+ P2P_DEV_DISC_RESP = 6,
+ P2P_PROV_DISC_REQ = 7,
+ P2P_PROV_DISC_RESP = 8
+};
+
+enum p2p_service_protocol_type {
+ P2P_SERV_ALL_SERVICES = 0,
+ P2P_SERV_BONJOUR = 1,
+ P2P_SERV_UPNP = 2,
+ P2P_SERV_WS_DISCOVERY = 3,
+ P2P_SERV_VENDOR_SPECIFIC = 255
+};
+
+enum p2p_sd_status {
+ P2P_SD_SUCCESS = 0,
+ P2P_SD_PROTO_NOT_AVAILABLE = 1,
+ P2P_SD_REQUESTED_INFO_NOT_AVAILABLE = 2,
+ P2P_SD_BAD_REQUEST = 3
+};
+
+
+#define OUI_BROADCOM 0x00904c /* Broadcom (Epigram) */
+
+#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
+
+/* AKM suite selectors */
+#define WLAN_AKM_SUITE_8021X 0x000FAC01
+#define WLAN_AKM_SUITE_PSK 0x000FAC02
+
+#endif /* IEEE802_11_DEFS_H */
diff --git a/src/common/privsep_commands.h b/src/common/privsep_commands.h
new file mode 100644
index 0000000..cc900be
--- /dev/null
+++ b/src/common/privsep_commands.h
@@ -0,0 +1,75 @@
+/*
+ * WPA Supplicant - privilege separation commands
+ * Copyright (c) 2007-2009, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#ifndef PRIVSEP_COMMANDS_H
+#define PRIVSEP_COMMANDS_H
+
+enum privsep_cmd {
+ PRIVSEP_CMD_REGISTER,
+ PRIVSEP_CMD_UNREGISTER,
+ PRIVSEP_CMD_SCAN,
+ PRIVSEP_CMD_GET_SCAN_RESULTS,
+ PRIVSEP_CMD_ASSOCIATE,
+ PRIVSEP_CMD_GET_BSSID,
+ PRIVSEP_CMD_GET_SSID,
+ PRIVSEP_CMD_SET_KEY,
+ PRIVSEP_CMD_GET_CAPA,
+ PRIVSEP_CMD_L2_REGISTER,
+ PRIVSEP_CMD_L2_UNREGISTER,
+ PRIVSEP_CMD_L2_NOTIFY_AUTH_START,
+ PRIVSEP_CMD_L2_SEND,
+ PRIVSEP_CMD_SET_COUNTRY,
+};
+
+struct privsep_cmd_associate
+{
+ u8 bssid[ETH_ALEN];
+ u8 ssid[32];
+ size_t ssid_len;
+ int freq;
+ int pairwise_suite;
+ int group_suite;
+ int key_mgmt_suite;
+ int auth_alg;
+ int mode;
+ size_t wpa_ie_len;
+ /* followed by wpa_ie_len bytes of wpa_ie */
+};
+
+struct privsep_cmd_set_key
+{
+ int alg;
+ u8 addr[ETH_ALEN];
+ int key_idx;
+ int set_tx;
+ u8 seq[8];
+ size_t seq_len;
+ u8 key[32];
+ size_t key_len;
+};
+
+enum privsep_event {
+ PRIVSEP_EVENT_SCAN_RESULTS,
+ PRIVSEP_EVENT_ASSOC,
+ PRIVSEP_EVENT_DISASSOC,
+ PRIVSEP_EVENT_ASSOCINFO,
+ PRIVSEP_EVENT_MICHAEL_MIC_FAILURE,
+ PRIVSEP_EVENT_INTERFACE_STATUS,
+ PRIVSEP_EVENT_PMKID_CANDIDATE,
+ PRIVSEP_EVENT_STKSTART,
+ PRIVSEP_EVENT_FT_RESPONSE,
+ PRIVSEP_EVENT_RX_EAPOL,
+};
+
+#endif /* PRIVSEP_COMMANDS_H */
diff --git a/src/common/version.h b/src/common/version.h
new file mode 100644
index 0000000..ba2d2c0
--- /dev/null
+++ b/src/common/version.h
@@ -0,0 +1,10 @@
+#ifndef VERSION_H
+#define VERSION_H
+
+#ifndef VERSION_STR_POSTFIX
+#define VERSION_STR_POSTFIX ""
+#endif /* VERSION_STR_POSTFIX */
+
+#define VERSION_STR "0.8.x" VERSION_STR_POSTFIX
+
+#endif /* VERSION_H */
diff --git a/src/common/wpa_common.c b/src/common/wpa_common.c
new file mode 100644
index 0000000..eb2745e
--- /dev/null
+++ b/src/common/wpa_common.c
@@ -0,0 +1,927 @@
+/*
+ * WPA/RSN - Shared functions for supplicant and authenticator
+ * Copyright (c) 2002-2008, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#include "includes.h"
+
+#include "common.h"
+#include "crypto/md5.h"
+#include "crypto/sha1.h"
+#include "crypto/sha256.h"
+#include "crypto/aes_wrap.h"
+#include "crypto/crypto.h"
+#include "ieee802_11_defs.h"
+#include "defs.h"
+#include "wpa_common.h"
+
+
+/**
+ * wpa_eapol_key_mic - Calculate EAPOL-Key MIC
+ * @key: EAPOL-Key Key Confirmation Key (KCK)
+ * @ver: Key descriptor version (WPA_KEY_INFO_TYPE_*)
+ * @buf: Pointer to the beginning of the EAPOL header (version field)
+ * @len: Length of the EAPOL frame (from EAPOL header to the end of the frame)
+ * @mic: Pointer to the buffer to which the EAPOL-Key MIC is written
+ * Returns: 0 on success, -1 on failure
+ *
+ * Calculate EAPOL-Key MIC for an EAPOL-Key packet. The EAPOL-Key MIC field has
+ * to be cleared (all zeroes) when calling this function.
+ *
+ * Note: 'IEEE Std 802.11i-2004 - 8.5.2 EAPOL-Key frames' has an error in the
+ * description of the Key MIC calculation. It includes packet data from the
+ * beginning of the EAPOL-Key header, not EAPOL header. This incorrect change
+ * happened during final editing of the standard and the correct behavior is
+ * defined in the last draft (IEEE 802.11i/D10).
+ */
+int wpa_eapol_key_mic(const u8 *key, int ver, const u8 *buf, size_t len,
+ u8 *mic)
+{
+ u8 hash[SHA1_MAC_LEN];
+
+ switch (ver) {
+ case WPA_KEY_INFO_TYPE_HMAC_MD5_RC4:
+ return hmac_md5(key, 16, buf, len, mic);
+ case WPA_KEY_INFO_TYPE_HMAC_SHA1_AES:
+ if (hmac_sha1(key, 16, buf, len, hash))
+ return -1;
+ os_memcpy(mic, hash, MD5_MAC_LEN);
+ break;
+#if defined(CONFIG_IEEE80211R) || defined(CONFIG_IEEE80211W)
+ case WPA_KEY_INFO_TYPE_AES_128_CMAC:
+ return omac1_aes_128(key, buf, len, mic);
+#endif /* CONFIG_IEEE80211R || CONFIG_IEEE80211W */
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+
+/**
+ * wpa_pmk_to_ptk - Calculate PTK from PMK, addresses, and nonces
+ * @pmk: Pairwise master key
+ * @pmk_len: Length of PMK
+ * @label: Label to use in derivation
+ * @addr1: AA or SA
+ * @addr2: SA or AA
+ * @nonce1: ANonce or SNonce
+ * @nonce2: SNonce or ANonce
+ * @ptk: Buffer for pairwise transient key
+ * @ptk_len: Length of PTK
+ * @use_sha256: Whether to use SHA256-based KDF
+ *
+ * IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy
+ * PTK = PRF-X(PMK, "Pairwise key expansion",
+ * Min(AA, SA) || Max(AA, SA) ||
+ * Min(ANonce, SNonce) || Max(ANonce, SNonce))
+ *
+ * STK = PRF-X(SMK, "Peer key expansion",
+ * Min(MAC_I, MAC_P) || Max(MAC_I, MAC_P) ||
+ * Min(INonce, PNonce) || Max(INonce, PNonce))
+ */
+void 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,
+ u8 *ptk, size_t ptk_len, int use_sha256)
+{
+ u8 data[2 * ETH_ALEN + 2 * WPA_NONCE_LEN];
+
+ if (os_memcmp(addr1, addr2, ETH_ALEN) < 0) {
+ os_memcpy(data, addr1, ETH_ALEN);
+ os_memcpy(data + ETH_ALEN, addr2, ETH_ALEN);
+ } else {
+ os_memcpy(data, addr2, ETH_ALEN);
+ os_memcpy(data + ETH_ALEN, addr1, ETH_ALEN);
+ }
+
+ if (os_memcmp(nonce1, nonce2, WPA_NONCE_LEN) < 0) {
+ os_memcpy(data + 2 * ETH_ALEN, nonce1, WPA_NONCE_LEN);
+ os_memcpy(data + 2 * ETH_ALEN + WPA_NONCE_LEN, nonce2,
+ WPA_NONCE_LEN);
+ } else {
+ os_memcpy(data + 2 * ETH_ALEN, nonce2, WPA_NONCE_LEN);
+ os_memcpy(data + 2 * ETH_ALEN + WPA_NONCE_LEN, nonce1,
+ WPA_NONCE_LEN);
+ }
+
+#ifdef CONFIG_IEEE80211W
+ if (use_sha256)
+ sha256_prf(pmk, pmk_len, label, data, sizeof(data),
+ ptk, ptk_len);
+ else
+#endif /* CONFIG_IEEE80211W */
+ sha1_prf(pmk, pmk_len, label, data, sizeof(data), ptk,
+ ptk_len);
+
+ wpa_printf(MSG_DEBUG, "WPA: PTK derivation - A1=" MACSTR " A2=" MACSTR,
+ MAC2STR(addr1), MAC2STR(addr2));
+ wpa_hexdump(MSG_DEBUG, "WPA: Nonce1", nonce1, WPA_NONCE_LEN);
+ wpa_hexdump(MSG_DEBUG, "WPA: Nonce2", nonce2, WPA_NONCE_LEN);
+ wpa_hexdump_key(MSG_DEBUG, "WPA: PMK", pmk, pmk_len);
+ wpa_hexdump_key(MSG_DEBUG, "WPA: PTK", ptk, ptk_len);
+}
+
+
+#ifdef CONFIG_IEEE80211R
+int wpa_ft_mic(const u8 *kck, const u8 *sta_addr, const u8 *ap_addr,
+ u8 transaction_seqnum, const u8 *mdie, size_t mdie_len,
+ const u8 *ftie, size_t ftie_len,
+ const u8 *rsnie, size_t rsnie_len,
+ const u8 *ric, size_t ric_len, u8 *mic)
+{
+ u8 *buf, *pos;
+ size_t buf_len;
+
+ buf_len = 2 * ETH_ALEN + 1 + mdie_len + ftie_len + rsnie_len + ric_len;
+ buf = os_malloc(buf_len);
+ if (buf == NULL)
+ return -1;
+
+ pos = buf;
+ os_memcpy(pos, sta_addr, ETH_ALEN);
+ pos += ETH_ALEN;
+ os_memcpy(pos, ap_addr, ETH_ALEN);
+ pos += ETH_ALEN;
+ *pos++ = transaction_seqnum;
+ if (rsnie) {
+ os_memcpy(pos, rsnie, rsnie_len);
+ pos += rsnie_len;
+ }
+ if (mdie) {
+ os_memcpy(pos, mdie, mdie_len);
+ pos += mdie_len;
+ }
+ if (ftie) {
+ struct rsn_ftie *_ftie;
+ os_memcpy(pos, ftie, ftie_len);
+ if (ftie_len < 2 + sizeof(*_ftie)) {
+ os_free(buf);
+ return -1;
+ }
+ _ftie = (struct rsn_ftie *) (pos + 2);
+ os_memset(_ftie->mic, 0, sizeof(_ftie->mic));
+ pos += ftie_len;
+ }
+ if (ric) {
+ os_memcpy(pos, ric, ric_len);
+ pos += ric_len;
+ }
+
+ wpa_hexdump(MSG_MSGDUMP, "FT: MIC data", buf, pos - buf);
+ if (omac1_aes_128(kck, buf, pos - buf, mic)) {
+ os_free(buf);
+ return -1;
+ }
+
+ os_free(buf);
+
+ return 0;
+}
+#endif /* CONFIG_IEEE80211R */
+
+
+#ifndef CONFIG_NO_WPA2
+static int rsn_selector_to_bitfield(const u8 *s)
+{
+ if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_NONE)
+ return WPA_CIPHER_NONE;
+ if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_WEP40)
+ return WPA_CIPHER_WEP40;
+ if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_TKIP)
+ return WPA_CIPHER_TKIP;
+ if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_CCMP)
+ return WPA_CIPHER_CCMP;
+ if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_WEP104)
+ return WPA_CIPHER_WEP104;
+#ifdef CONFIG_IEEE80211W
+ if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_AES_128_CMAC)
+ return WPA_CIPHER_AES_128_CMAC;
+#endif /* CONFIG_IEEE80211W */
+ return 0;
+}
+
+
+static int rsn_key_mgmt_to_bitfield(const u8 *s)
+{
+ if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_UNSPEC_802_1X)
+ return WPA_KEY_MGMT_IEEE8021X;
+ if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X)
+ return WPA_KEY_MGMT_PSK;
+#ifdef CONFIG_IEEE80211R
+ if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_802_1X)
+ return WPA_KEY_MGMT_FT_IEEE8021X;
+ if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_PSK)
+ return WPA_KEY_MGMT_FT_PSK;
+#endif /* CONFIG_IEEE80211R */
+#ifdef CONFIG_IEEE80211W
+ if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_802_1X_SHA256)
+ return WPA_KEY_MGMT_IEEE8021X_SHA256;
+ if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_PSK_SHA256)
+ return WPA_KEY_MGMT_PSK_SHA256;
+#endif /* CONFIG_IEEE80211W */
+ return 0;
+}
+#endif /* CONFIG_NO_WPA2 */
+
+
+/**
+ * wpa_parse_wpa_ie_rsn - Parse RSN IE
+ * @rsn_ie: Buffer containing RSN IE
+ * @rsn_ie_len: RSN IE buffer length (including IE number and length octets)
+ * @data: Pointer to structure that will be filled in with parsed data
+ * Returns: 0 on success, <0 on failure
+ */
+int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
+ struct wpa_ie_data *data)
+{
+#ifndef CONFIG_NO_WPA2
+ const struct rsn_ie_hdr *hdr;
+ const u8 *pos;
+ int left;
+ int i, count;
+
+ os_memset(data, 0, sizeof(*data));
+ data->proto = WPA_PROTO_RSN;
+ data->pairwise_cipher = WPA_CIPHER_CCMP;
+ data->group_cipher = WPA_CIPHER_CCMP;
+ data->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
+ data->capabilities = 0;
+ data->pmkid = NULL;
+ data->num_pmkid = 0;
+#ifdef CONFIG_IEEE80211W
+ data->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
+#else /* CONFIG_IEEE80211W */
+ data->mgmt_group_cipher = 0;
+#endif /* CONFIG_IEEE80211W */
+
+ if (rsn_ie_len == 0) {
+ /* No RSN IE - fail silently */
+ return -1;
+ }
+
+ if (rsn_ie_len < sizeof(struct rsn_ie_hdr)) {
+ wpa_printf(MSG_DEBUG, "%s: ie len too short %lu",
+ __func__, (unsigned long) rsn_ie_len);
+ return -1;
+ }
+
+ hdr = (const struct rsn_ie_hdr *) rsn_ie;
+
+ if (hdr->elem_id != WLAN_EID_RSN ||
+ hdr->len != rsn_ie_len - 2 ||
+ WPA_GET_LE16(hdr->version) != RSN_VERSION) {
+ wpa_printf(MSG_DEBUG, "%s: malformed ie or unknown version",
+ __func__);
+ return -2;
+ }
+
+ pos = (const u8 *) (hdr + 1);
+ left = rsn_ie_len - sizeof(*hdr);
+
+ if (left >= RSN_SELECTOR_LEN) {
+ data->group_cipher = rsn_selector_to_bitfield(pos);
+#ifdef CONFIG_IEEE80211W
+ if (data->group_cipher == WPA_CIPHER_AES_128_CMAC) {
+ wpa_printf(MSG_DEBUG, "%s: AES-128-CMAC used as group "
+ "cipher", __func__);
+ return -1;
+ }
+#endif /* CONFIG_IEEE80211W */
+ pos += RSN_SELECTOR_LEN;
+ left -= RSN_SELECTOR_LEN;
+ } else if (left > 0) {
+ wpa_printf(MSG_DEBUG, "%s: ie length mismatch, %u too much",
+ __func__, left);
+ return -3;
+ }
+
+ if (left >= 2) {
+ data->pairwise_cipher = 0;
+ count = WPA_GET_LE16(pos);
+ pos += 2;
+ left -= 2;
+ if (count == 0 || left < count * RSN_SELECTOR_LEN) {
+ wpa_printf(MSG_DEBUG, "%s: ie count botch (pairwise), "
+ "count %u left %u", __func__, count, left);
+ return -4;
+ }
+ for (i = 0; i < count; i++) {
+ data->pairwise_cipher |= rsn_selector_to_bitfield(pos);
+ pos += RSN_SELECTOR_LEN;
+ left -= RSN_SELECTOR_LEN;
+ }
+#ifdef CONFIG_IEEE80211W
+ if (data->pairwise_cipher & WPA_CIPHER_AES_128_CMAC) {
+ wpa_printf(MSG_DEBUG, "%s: AES-128-CMAC used as "
+ "pairwise cipher", __func__);
+ return -1;
+ }
+#endif /* CONFIG_IEEE80211W */
+ } else if (left == 1) {
+ wpa_printf(MSG_DEBUG, "%s: ie too short (for key mgmt)",
+ __func__);
+ return -5;
+ }
+
+ if (left >= 2) {
+ data->key_mgmt = 0;
+ count = WPA_GET_LE16(pos);
+ pos += 2;
+ left -= 2;
+ if (count == 0 || left < count * RSN_SELECTOR_LEN) {
+ wpa_printf(MSG_DEBUG, "%s: ie count botch (key mgmt), "
+ "count %u left %u", __func__, count, left);
+ return -6;
+ }
+ for (i = 0; i < count; i++) {
+ data->key_mgmt |= rsn_key_mgmt_to_bitfield(pos);
+ pos += RSN_SELECTOR_LEN;
+ left -= RSN_SELECTOR_LEN;
+ }
+ } else if (left == 1) {
+ wpa_printf(MSG_DEBUG, "%s: ie too short (for capabilities)",
+ __func__);
+ return -7;
+ }
+
+ if (left >= 2) {
+ data->capabilities = WPA_GET_LE16(pos);
+ pos += 2;
+ left -= 2;
+ }
+
+ if (left >= 2) {
+ data->num_pmkid = WPA_GET_LE16(pos);
+ pos += 2;
+ left -= 2;
+ if (left < (int) data->num_pmkid * PMKID_LEN) {
+ wpa_printf(MSG_DEBUG, "%s: PMKID underflow "
+ "(num_pmkid=%lu left=%d)",
+ __func__, (unsigned long) data->num_pmkid,
+ left);
+ data->num_pmkid = 0;
+ return -9;
+ } else {
+ data->pmkid = pos;
+ pos += data->num_pmkid * PMKID_LEN;
+ left -= data->num_pmkid * PMKID_LEN;
+ }
+ }
+
+#ifdef CONFIG_IEEE80211W
+ if (left >= 4) {
+ data->mgmt_group_cipher = rsn_selector_to_bitfield(pos);
+ if (data->mgmt_group_cipher != WPA_CIPHER_AES_128_CMAC) {
+ wpa_printf(MSG_DEBUG, "%s: Unsupported management "
+ "group cipher 0x%x", __func__,
+ data->mgmt_group_cipher);
+ return -10;
+ }
+ pos += RSN_SELECTOR_LEN;
+ left -= RSN_SELECTOR_LEN;
+ }
+#endif /* CONFIG_IEEE80211W */
+
+ if (left > 0) {
+ wpa_printf(MSG_DEBUG, "%s: ie has %u trailing bytes - ignored",
+ __func__, left);
+ }
+
+ return 0;
+#else /* CONFIG_NO_WPA2 */
+ return -1;
+#endif /* CONFIG_NO_WPA2 */
+}
+
+
+static int wpa_selector_to_bitfield(const u8 *s)
+{
+ if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_NONE)
+ return WPA_CIPHER_NONE;
+ if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_WEP40)
+ return WPA_CIPHER_WEP40;
+ if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_TKIP)
+ return WPA_CIPHER_TKIP;
+ if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_CCMP)
+ return WPA_CIPHER_CCMP;
+ if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_WEP104)
+ return WPA_CIPHER_WEP104;
+ return 0;
+}
+
+
+static int wpa_key_mgmt_to_bitfield(const u8 *s)
+{
+ if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_UNSPEC_802_1X)
+ return WPA_KEY_MGMT_IEEE8021X;
+ if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X)
+ return WPA_KEY_MGMT_PSK;
+ if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_NONE)
+ return WPA_KEY_MGMT_WPA_NONE;
+ return 0;
+}
+
+
+int wpa_parse_wpa_ie_wpa(const u8 *wpa_ie, size_t wpa_ie_len,
+ struct wpa_ie_data *data)
+{
+ const struct wpa_ie_hdr *hdr;
+ const u8 *pos;
+ int left;
+ int i, count;
+
+ os_memset(data, 0, sizeof(*data));
+ data->proto = WPA_PROTO_WPA;
+ data->pairwise_cipher = WPA_CIPHER_TKIP;
+ data->group_cipher = WPA_CIPHER_TKIP;
+ data->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
+ data->capabilities = 0;
+ data->pmkid = NULL;
+ data->num_pmkid = 0;
+ data->mgmt_group_cipher = 0;
+
+ if (wpa_ie_len == 0) {
+ /* No WPA IE - fail silently */
+ return -1;
+ }
+
+ if (wpa_ie_len < sizeof(struct wpa_ie_hdr)) {
+ wpa_printf(MSG_DEBUG, "%s: ie len too short %lu",
+ __func__, (unsigned long) wpa_ie_len);
+ return -1;
+ }
+
+ hdr = (const struct wpa_ie_hdr *) wpa_ie;
+
+ if (hdr->elem_id != WLAN_EID_VENDOR_SPECIFIC ||
+ hdr->len != wpa_ie_len - 2 ||
+ RSN_SELECTOR_GET(hdr->oui) != WPA_OUI_TYPE ||
+ WPA_GET_LE16(hdr->version) != WPA_VERSION) {
+ wpa_printf(MSG_DEBUG, "%s: malformed ie or unknown version",
+ __func__);
+ return -2;
+ }
+
+ pos = (const u8 *) (hdr + 1);
+ left = wpa_ie_len - sizeof(*hdr);
+
+ if (left >= WPA_SELECTOR_LEN) {
+ data->group_cipher = wpa_selector_to_bitfield(pos);
+ pos += WPA_SELECTOR_LEN;
+ left -= WPA_SELECTOR_LEN;
+ } else if (left > 0) {
+ wpa_printf(MSG_DEBUG, "%s: ie length mismatch, %u too much",
+ __func__, left);
+ return -3;
+ }
+
+ if (left >= 2) {
+ data->pairwise_cipher = 0;
+ count = WPA_GET_LE16(pos);
+ pos += 2;
+ left -= 2;
+ if (count == 0 || left < count * WPA_SELECTOR_LEN) {
+ wpa_printf(MSG_DEBUG, "%s: ie count botch (pairwise), "
+ "count %u left %u", __func__, count, left);
+ return -4;
+ }
+ for (i = 0; i < count; i++) {
+ data->pairwise_cipher |= wpa_selector_to_bitfield(pos);
+ pos += WPA_SELECTOR_LEN;
+ left -= WPA_SELECTOR_LEN;
+ }
+ } else if (left == 1) {
+ wpa_printf(MSG_DEBUG, "%s: ie too short (for key mgmt)",
+ __func__);
+ return -5;
+ }
+
+ if (left >= 2) {
+ data->key_mgmt = 0;
+ count = WPA_GET_LE16(pos);
+ pos += 2;
+ left -= 2;
+ if (count == 0 || left < count * WPA_SELECTOR_LEN) {
+ wpa_printf(MSG_DEBUG, "%s: ie count botch (key mgmt), "
+ "count %u left %u", __func__, count, left);
+ return -6;
+ }
+ for (i = 0; i < count; i++) {
+ data->key_mgmt |= wpa_key_mgmt_to_bitfield(pos);
+ pos += WPA_SELECTOR_LEN;
+ left -= WPA_SELECTOR_LEN;
+ }
+ } else if (left == 1) {
+ wpa_printf(MSG_DEBUG, "%s: ie too short (for capabilities)",
+ __func__);
+ return -7;
+ }
+
+ if (left >= 2) {
+ data->capabilities = WPA_GET_LE16(pos);
+ pos += 2;
+ left -= 2;
+ }
+
+ if (left > 0) {
+ wpa_printf(MSG_DEBUG, "%s: ie has %u trailing bytes - ignored",
+ __func__, left);
+ }
+
+ return 0;
+}
+
+
+#ifdef CONFIG_IEEE80211R
+
+/**
+ * wpa_derive_pmk_r0 - Derive PMK-R0 and PMKR0Name
+ *
+ * IEEE Std 802.11r-2008 - 8.5.1.5.3
+ */
+void wpa_derive_pmk_r0(const u8 *xxkey, size_t xxkey_len,
+ const u8 *ssid, size_t ssid_len,
+ const u8 *mdid, const u8 *r0kh_id, size_t r0kh_id_len,
+ const u8 *s0kh_id, u8 *pmk_r0, u8 *pmk_r0_name)
+{
+ u8 buf[1 + WPA_MAX_SSID_LEN + MOBILITY_DOMAIN_ID_LEN + 1 +
+ FT_R0KH_ID_MAX_LEN + ETH_ALEN];
+ u8 *pos, r0_key_data[48], hash[32];
+ const u8 *addr[2];
+ size_t len[2];
+
+ /*
+ * R0-Key-Data = KDF-384(XXKey, "FT-R0",
+ * SSIDlength || SSID || MDID || R0KHlength ||
+ * R0KH-ID || S0KH-ID)
+ * XXKey is either the second 256 bits of MSK or PSK.
+ * PMK-R0 = L(R0-Key-Data, 0, 256)
+ * PMK-R0Name-Salt = L(R0-Key-Data, 256, 128)
+ */
+ if (ssid_len > WPA_MAX_SSID_LEN || r0kh_id_len > FT_R0KH_ID_MAX_LEN)
+ return;
+ pos = buf;
+ *pos++ = ssid_len;
+ os_memcpy(pos, ssid, ssid_len);
+ pos += ssid_len;
+ os_memcpy(pos, mdid, MOBILITY_DOMAIN_ID_LEN);
+ pos += MOBILITY_DOMAIN_ID_LEN;
+ *pos++ = r0kh_id_len;
+ os_memcpy(pos, r0kh_id, r0kh_id_len);
+ pos += r0kh_id_len;
+ os_memcpy(pos, s0kh_id, ETH_ALEN);
+ pos += ETH_ALEN;
+
+ sha256_prf(xxkey, xxkey_len, "FT-R0", buf, pos - buf,
+ r0_key_data, sizeof(r0_key_data));
+ os_memcpy(pmk_r0, r0_key_data, PMK_LEN);
+
+ /*
+ * PMKR0Name = Truncate-128(SHA-256("FT-R0N" || PMK-R0Name-Salt)
+ */
+ addr[0] = (const u8 *) "FT-R0N";
+ len[0] = 6;
+ addr[1] = r0_key_data + PMK_LEN;
+ len[1] = 16;
+
+ sha256_vector(2, addr, len, hash);
+ os_memcpy(pmk_r0_name, hash, WPA_PMK_NAME_LEN);
+}
+
+
+/**
+ * wpa_derive_pmk_r1_name - Derive PMKR1Name
+ *
+ * IEEE Std 802.11r-2008 - 8.5.1.5.4
+ */
+void wpa_derive_pmk_r1_name(const u8 *pmk_r0_name, const u8 *r1kh_id,
+ const u8 *s1kh_id, u8 *pmk_r1_name)
+{
+ u8 hash[32];
+ const u8 *addr[4];
+ size_t len[4];
+
+ /*
+ * PMKR1Name = Truncate-128(SHA-256("FT-R1N" || PMKR0Name ||
+ * R1KH-ID || S1KH-ID))
+ */
+ addr[0] = (const u8 *) "FT-R1N";
+ len[0] = 6;
+ addr[1] = pmk_r0_name;
+ len[1] = WPA_PMK_NAME_LEN;
+ addr[2] = r1kh_id;
+ len[2] = FT_R1KH_ID_LEN;
+ addr[3] = s1kh_id;
+ len[3] = ETH_ALEN;
+
+ sha256_vector(4, addr, len, hash);
+ os_memcpy(pmk_r1_name, hash, WPA_PMK_NAME_LEN);
+}
+
+
+/**
+ * wpa_derive_pmk_r1 - Derive PMK-R1 and PMKR1Name from PMK-R0
+ *
+ * IEEE Std 802.11r-2008 - 8.5.1.5.4
+ */
+void wpa_derive_pmk_r1(const u8 *pmk_r0, const u8 *pmk_r0_name,
+ const u8 *r1kh_id, const u8 *s1kh_id,
+ u8 *pmk_r1, u8 *pmk_r1_name)
+{
+ u8 buf[FT_R1KH_ID_LEN + ETH_ALEN];
+ u8 *pos;
+
+ /* PMK-R1 = KDF-256(PMK-R0, "FT-R1", R1KH-ID || S1KH-ID) */
+ pos = buf;
+ os_memcpy(pos, r1kh_id, FT_R1KH_ID_LEN);
+ pos += FT_R1KH_ID_LEN;
+ os_memcpy(pos, s1kh_id, ETH_ALEN);
+ pos += ETH_ALEN;
+
+ sha256_prf(pmk_r0, PMK_LEN, "FT-R1", buf, pos - buf, pmk_r1, PMK_LEN);
+
+ wpa_derive_pmk_r1_name(pmk_r0_name, r1kh_id, s1kh_id, pmk_r1_name);
+}
+
+
+/**
+ * wpa_pmk_r1_to_ptk - Derive PTK and PTKName from PMK-R1
+ *
+ * IEEE Std 802.11r-2008 - 8.5.1.5.5
+ */
+void wpa_pmk_r1_to_ptk(const u8 *pmk_r1, const u8 *snonce, const u8 *anonce,
+ const u8 *sta_addr, const u8 *bssid,
+ const u8 *pmk_r1_name,
+ u8 *ptk, size_t ptk_len, u8 *ptk_name)
+{
+ u8 buf[2 * WPA_NONCE_LEN + 2 * ETH_ALEN];
+ u8 *pos, hash[32];
+ const u8 *addr[6];
+ size_t len[6];
+
+ /*
+ * PTK = KDF-PTKLen(PMK-R1, "FT-PTK", SNonce || ANonce ||
+ * BSSID || STA-ADDR)
+ */
+ pos = buf;
+ os_memcpy(pos, snonce, WPA_NONCE_LEN);
+ pos += WPA_NONCE_LEN;
+ os_memcpy(pos, anonce, WPA_NONCE_LEN);
+ pos += WPA_NONCE_LEN;
+ os_memcpy(pos, bssid, ETH_ALEN);
+ pos += ETH_ALEN;
+ os_memcpy(pos, sta_addr, ETH_ALEN);
+ pos += ETH_ALEN;
+
+ sha256_prf(pmk_r1, PMK_LEN, "FT-PTK", buf, pos - buf, ptk, ptk_len);
+
+ /*
+ * PTKName = Truncate-128(SHA-256(PMKR1Name || "FT-PTKN" || SNonce ||
+ * ANonce || BSSID || STA-ADDR))
+ */
+ addr[0] = pmk_r1_name;
+ len[0] = WPA_PMK_NAME_LEN;
+ addr[1] = (const u8 *) "FT-PTKN";
+ len[1] = 7;
+ addr[2] = snonce;
+ len[2] = WPA_NONCE_LEN;
+ addr[3] = anonce;
+ len[3] = WPA_NONCE_LEN;
+ addr[4] = bssid;
+ len[4] = ETH_ALEN;
+ addr[5] = sta_addr;
+ len[5] = ETH_ALEN;
+
+ sha256_vector(6, addr, len, hash);
+ os_memcpy(ptk_name, hash, WPA_PMK_NAME_LEN);
+}
+
+#endif /* CONFIG_IEEE80211R */
+
+
+/**
+ * rsn_pmkid - Calculate PMK identifier
+ * @pmk: Pairwise master key
+ * @pmk_len: Length of pmk in bytes
+ * @aa: Authenticator address
+ * @spa: Supplicant address
+ * @pmkid: Buffer for PMKID
+ * @use_sha256: Whether to use SHA256-based KDF
+ *
+ * IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy
+ * PMKID = HMAC-SHA1-128(PMK, "PMK Name" || AA || SPA)
+ */
+void rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa, const u8 *spa,
+ u8 *pmkid, int use_sha256)
+{
+ char *title = "PMK Name";
+ const u8 *addr[3];
+ const size_t len[3] = { 8, ETH_ALEN, ETH_ALEN };
+ unsigned char hash[SHA256_MAC_LEN];
+
+ addr[0] = (u8 *) title;
+ addr[1] = aa;
+ addr[2] = spa;
+
+#ifdef CONFIG_IEEE80211W
+ if (use_sha256)
+ hmac_sha256_vector(pmk, pmk_len, 3, addr, len, hash);
+ else
+#endif /* CONFIG_IEEE80211W */
+ hmac_sha1_vector(pmk, pmk_len, 3, addr, len, hash);
+ os_memcpy(pmkid, hash, PMKID_LEN);
+}
+
+
+/**
+ * wpa_cipher_txt - Convert cipher suite to a text string
+ * @cipher: Cipher suite (WPA_CIPHER_* enum)
+ * Returns: Pointer to a text string of the cipher suite name
+ */
+const char * wpa_cipher_txt(int cipher)
+{
+ switch (cipher) {
+ case WPA_CIPHER_NONE:
+ return "NONE";
+ case WPA_CIPHER_WEP40:
+ return "WEP-40";
+ case WPA_CIPHER_WEP104:
+ return "WEP-104";
+ case WPA_CIPHER_TKIP:
+ return "TKIP";
+ case WPA_CIPHER_CCMP:
+ return "CCMP";
+ case WPA_CIPHER_CCMP | WPA_CIPHER_TKIP:
+ return "CCMP+TKIP";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+
+/**
+ * wpa_key_mgmt_txt - Convert key management suite to a text string
+ * @key_mgmt: Key management suite (WPA_KEY_MGMT_* enum)
+ * @proto: WPA/WPA2 version (WPA_PROTO_*)
+ * Returns: Pointer to a text string of the key management suite name
+ */
+const char * wpa_key_mgmt_txt(int key_mgmt, int proto)
+{
+ switch (key_mgmt) {
+ case WPA_KEY_MGMT_IEEE8021X:
+ if (proto == (WPA_PROTO_RSN | WPA_PROTO_WPA))
+ return "WPA2+WPA/IEEE 802.1X/EAP";
+ return proto == WPA_PROTO_RSN ?
+ "WPA2/IEEE 802.1X/EAP" : "WPA/IEEE 802.1X/EAP";
+ case WPA_KEY_MGMT_PSK:
+ if (proto == (WPA_PROTO_RSN | WPA_PROTO_WPA))
+ return "WPA2-PSK+WPA-PSK";
+ return proto == WPA_PROTO_RSN ?
+ "WPA2-PSK" : "WPA-PSK";
+ case WPA_KEY_MGMT_NONE:
+ return "NONE";
+ case WPA_KEY_MGMT_IEEE8021X_NO_WPA:
+ return "IEEE 802.1X (no WPA)";
+#ifdef CONFIG_IEEE80211R
+ case WPA_KEY_MGMT_FT_IEEE8021X:
+ return "FT-EAP";
+ case WPA_KEY_MGMT_FT_PSK:
+ return "FT-PSK";
+#endif /* CONFIG_IEEE80211R */
+#ifdef CONFIG_IEEE80211W
+ case WPA_KEY_MGMT_IEEE8021X_SHA256:
+ return "WPA2-EAP-SHA256";
+ case WPA_KEY_MGMT_PSK_SHA256:
+ return "WPA2-PSK-SHA256";
+#endif /* CONFIG_IEEE80211W */
+ default:
+ return "UNKNOWN";
+ }
+}
+
+
+int wpa_compare_rsn_ie(int ft_initial_assoc,
+ const u8 *ie1, size_t ie1len,
+ const u8 *ie2, size_t ie2len)
+{
+ if (ie1 == NULL || ie2 == NULL)
+ return -1;
+
+ if (ie1len == ie2len && os_memcmp(ie1, ie2, ie1len) == 0)
+ return 0; /* identical IEs */
+
+#ifdef CONFIG_IEEE80211R
+ if (ft_initial_assoc) {
+ struct wpa_ie_data ie1d, ie2d;
+ /*
+ * The PMKID-List in RSN IE is different between Beacon/Probe
+ * Response/(Re)Association Request frames and EAPOL-Key
+ * messages in FT initial mobility domain association. Allow
+ * for this, but verify that other parts of the RSN IEs are
+ * identical.
+ */
+ if (wpa_parse_wpa_ie_rsn(ie1, ie1len, &ie1d) < 0 ||
+ wpa_parse_wpa_ie_rsn(ie2, ie2len, &ie2d) < 0)
+ return -1;
+ if (ie1d.proto == ie2d.proto &&
+ ie1d.pairwise_cipher == ie2d.pairwise_cipher &&
+ ie1d.group_cipher == ie2d.group_cipher &&
+ ie1d.key_mgmt == ie2d.key_mgmt &&
+ ie1d.capabilities == ie2d.capabilities &&
+ ie1d.mgmt_group_cipher == ie2d.mgmt_group_cipher)
+ return 0;
+ }
+#endif /* CONFIG_IEEE80211R */
+
+ return -1;
+}
+
+
+#ifdef CONFIG_IEEE80211R
+int wpa_insert_pmkid(u8 *ies, size_t ies_len, const u8 *pmkid)
+{
+ u8 *start, *end, *rpos, *rend;
+ int added = 0;
+
+ start = ies;
+ end = ies + ies_len;
+
+ while (start < end) {
+ if (*start == WLAN_EID_RSN)
+ break;
+ start += 2 + start[1];
+ }
+ if (start >= end) {
+ wpa_printf(MSG_ERROR, "FT: Could not find RSN IE in "
+ "IEs data");
+ return -1;
+ }
+ wpa_hexdump(MSG_DEBUG, "FT: RSN IE before modification",
+ start, 2 + start[1]);
+
+ /* Find start of PMKID-Count */
+ rpos = start + 2;
+ rend = rpos + start[1];
+
+ /* Skip Version and Group Data Cipher Suite */
+ rpos += 2 + 4;
+ /* Skip Pairwise Cipher Suite Count and List */
+ rpos += 2 + WPA_GET_LE16(rpos) * RSN_SELECTOR_LEN;
+ /* Skip AKM Suite Count and List */
+ rpos += 2 + WPA_GET_LE16(rpos) * RSN_SELECTOR_LEN;
+
+ if (rpos == rend) {
+ /* Add RSN Capabilities */
+ os_memmove(rpos + 2, rpos, end - rpos);
+ *rpos++ = 0;
+ *rpos++ = 0;
+ } else {
+ /* Skip RSN Capabilities */
+ rpos += 2;
+ if (rpos > rend) {
+ wpa_printf(MSG_ERROR, "FT: Could not parse RSN IE in "
+ "IEs data");
+ return -1;
+ }
+ }
+
+ if (rpos == rend) {
+ /* No PMKID-Count field included; add it */
+ os_memmove(rpos + 2 + PMKID_LEN, rpos, end - rpos);
+ WPA_PUT_LE16(rpos, 1);
+ rpos += 2;
+ os_memcpy(rpos, pmkid, PMKID_LEN);
+ added += 2 + PMKID_LEN;
+ start[1] += 2 + PMKID_LEN;
+ } else {
+ /* PMKID-Count was included; use it */
+ if (WPA_GET_LE16(rpos) != 0) {
+ wpa_printf(MSG_ERROR, "FT: Unexpected PMKID "
+ "in RSN IE in EAPOL-Key data");
+ return -1;
+ }
+ WPA_PUT_LE16(rpos, 1);
+ rpos += 2;
+ os_memmove(rpos + PMKID_LEN, rpos, end - rpos);
+ os_memcpy(rpos, pmkid, PMKID_LEN);
+ added += PMKID_LEN;
+ start[1] += PMKID_LEN;
+ }
+
+ wpa_hexdump(MSG_DEBUG, "FT: RSN IE after modification "
+ "(PMKID inserted)", start, 2 + start[1]);
+
+ return added;
+}
+#endif /* CONFIG_IEEE80211R */
diff --git a/src/common/wpa_common.h b/src/common/wpa_common.h
new file mode 100644
index 0000000..fe79cee
--- /dev/null
+++ b/src/common/wpa_common.h
@@ -0,0 +1,361 @@
+/*
+ * WPA definitions shared between hostapd and wpa_supplicant
+ * Copyright (c) 2002-2008, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#ifndef WPA_COMMON_H
+#define WPA_COMMON_H
+
+#define WPA_MAX_SSID_LEN 32
+
+/* IEEE 802.11i */
+#define PMKID_LEN 16
+#define PMK_LEN 32
+#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 WPA_SELECTOR_LEN 4
+#define WPA_VERSION 1
+#define RSN_SELECTOR_LEN 4
+#define RSN_VERSION 1
+
+#define RSN_SELECTOR(a, b, c, d) \
+ ((((u32) (a)) << 24) | (((u32) (b)) << 16) | (((u32) (c)) << 8) | \
+ (u32) (d))
+
+#define WPA_AUTH_KEY_MGMT_NONE RSN_SELECTOR(0x00, 0x50, 0xf2, 0)
+#define WPA_AUTH_KEY_MGMT_UNSPEC_802_1X RSN_SELECTOR(0x00, 0x50, 0xf2, 1)
+#define WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X RSN_SELECTOR(0x00, 0x50, 0xf2, 2)
+#define WPA_CIPHER_SUITE_NONE RSN_SELECTOR(0x00, 0x50, 0xf2, 0)
+#define WPA_CIPHER_SUITE_WEP40 RSN_SELECTOR(0x00, 0x50, 0xf2, 1)
+#define WPA_CIPHER_SUITE_TKIP RSN_SELECTOR(0x00, 0x50, 0xf2, 2)
+#if 0
+#define WPA_CIPHER_SUITE_WRAP RSN_SELECTOR(0x00, 0x50, 0xf2, 3)
+#endif
+#define WPA_CIPHER_SUITE_CCMP RSN_SELECTOR(0x00, 0x50, 0xf2, 4)
+#define WPA_CIPHER_SUITE_WEP104 RSN_SELECTOR(0x00, 0x50, 0xf2, 5)
+
+
+#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)
+
+#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)
+#ifdef CONFIG_IEEE80211W
+#define RSN_CIPHER_SUITE_AES_128_CMAC RSN_SELECTOR(0x00, 0x0f, 0xac, 6)
+#endif /* CONFIG_IEEE80211W */
+#define RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED RSN_SELECTOR(0x00, 0x0f, 0xac, 7)
+
+/* EAPOL-Key Key Data Encapsulation
+ * GroupKey and PeerKey require encryption, otherwise, encryption is optional.
+ */
+#define RSN_KEY_DATA_GROUPKEY RSN_SELECTOR(0x00, 0x0f, 0xac, 1)
+#if 0
+#define RSN_KEY_DATA_STAKEY RSN_SELECTOR(0x00, 0x0f, 0xac, 2)
+#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 WPA_OUI_TYPE RSN_SELECTOR(0x00, 0x50, 0xf2, 1)
+
+#define RSN_SELECTOR_PUT(a, val) WPA_PUT_BE32((u8 *) (a), (val))
+#define RSN_SELECTOR_GET(a) WPA_GET_BE32((const u8 *) (a))
+
+#define RSN_NUM_REPLAY_COUNTERS_1 0
+#define RSN_NUM_REPLAY_COUNTERS_2 1
+#define RSN_NUM_REPLAY_COUNTERS_4 2
+#define RSN_NUM_REPLAY_COUNTERS_16 3
+
+
+#ifdef _MSC_VER
+#pragma pack(push, 1)
+#endif /* _MSC_VER */
+
+#ifdef CONFIG_IEEE80211W
+#define WPA_IGTK_LEN 16
+#endif /* CONFIG_IEEE80211W */
+
+
+/* IEEE 802.11, 7.3.2.25.3 RSN Capabilities */
+#define WPA_CAPABILITY_PREAUTH BIT(0)
+#define WPA_CAPABILITY_NO_PAIRWISE BIT(1)
+/* B2-B3: PTKSA Replay Counter */
+/* B4-B5: GTKSA Replay Counter */
+#define WPA_CAPABILITY_MFPR BIT(6)
+#define WPA_CAPABILITY_MFPC BIT(7)
+/* B8: Reserved */
+#define WPA_CAPABILITY_PEERKEY_ENABLED BIT(9)
+#define WPA_CAPABILITY_SPP_A_MSDU_CAPABLE BIT(10)
+#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 */
+
+
+/* IEEE 802.11r */
+#define MOBILITY_DOMAIN_ID_LEN 2
+#define FT_R0KH_ID_MAX_LEN 48
+#define FT_R1KH_ID_LEN 6
+#define WPA_PMK_NAME_LEN 16
+
+
+/* IEEE 802.11, 8.5.2 EAPOL-Key frames */
+#define WPA_KEY_INFO_TYPE_MASK ((u16) (BIT(0) | BIT(1) | BIT(2)))
+#define WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 BIT(0)
+#define WPA_KEY_INFO_TYPE_HMAC_SHA1_AES BIT(1)
+#define WPA_KEY_INFO_TYPE_AES_128_CMAC 3
+#define WPA_KEY_INFO_KEY_TYPE BIT(3) /* 1 = Pairwise, 0 = Group key */
+/* bit4..5 is used in WPA, but is reserved in IEEE 802.11i/RSN */
+#define WPA_KEY_INFO_KEY_INDEX_MASK (BIT(4) | BIT(5))
+#define WPA_KEY_INFO_KEY_INDEX_SHIFT 4
+#define WPA_KEY_INFO_INSTALL BIT(6) /* pairwise */
+#define WPA_KEY_INFO_TXRX BIT(6) /* group */
+#define WPA_KEY_INFO_ACK BIT(7)
+#define WPA_KEY_INFO_MIC BIT(8)
+#define WPA_KEY_INFO_SECURE BIT(9)
+#define WPA_KEY_INFO_ERROR BIT(10)
+#define WPA_KEY_INFO_REQUEST BIT(11)
+#define WPA_KEY_INFO_ENCR_KEY_DATA BIT(12) /* IEEE 802.11i/RSN only */
+#define WPA_KEY_INFO_SMK_MESSAGE BIT(13)
+
+
+struct wpa_eapol_key {
+ 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[16];
+ u8 key_data_length[2]; /* big endian */
+ /* followed by key_data_length bytes of key_data */
+} STRUCT_PACKED;
+
+/**
+ * struct wpa_ptk - WPA Pairwise Transient Key
+ * IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy
+ */
+struct wpa_ptk {
+ u8 kck[16]; /* EAPOL-Key Key Confirmation Key (KCK) */
+ u8 kek[16]; /* EAPOL-Key Key Encryption Key (KEK) */
+ u8 tk1[16]; /* Temporal Key 1 (TK1) */
+ union {
+ u8 tk2[16]; /* Temporal Key 2 (TK2) */
+ struct {
+ u8 tx_mic_key[8];
+ u8 rx_mic_key[8];
+ } auth;
+ } u;
+} STRUCT_PACKED;
+
+
+/* WPA IE version 1
+ * 00-50-f2:1 (OUI:OUI type)
+ * 0x01 0x00 (version; little endian)
+ * (all following fields are optional:)
+ * Group Suite Selector (4 octets) (default: TKIP)
+ * Pairwise Suite Count (2 octets, little endian) (default: 1)
+ * Pairwise Suite List (4 * n octets) (default: TKIP)
+ * Authenticated Key Management Suite Count (2 octets, little endian)
+ * (default: 1)
+ * Authenticated Key Management Suite List (4 * n octets)
+ * (default: unspec 802.1X)
+ * WPA Capabilities (2 octets, little endian) (default: 0)
+ */
+
+struct wpa_ie_hdr {
+ u8 elem_id;
+ u8 len;
+ u8 oui[4]; /* 24-bit OUI followed by 8-bit OUI type */
+ u8 version[2]; /* little endian */
+} STRUCT_PACKED;
+
+
+/* 1/4: PMKID
+ * 2/4: RSN IE
+ * 3/4: one or two RSN IEs + GTK IE (encrypted)
+ * 4/4: empty
+ * 1/2: GTK IE (encrypted)
+ * 2/2: empty
+ */
+
+/* RSN IE version 1
+ * 0x01 0x00 (version; little endian)
+ * (all following fields are optional:)
+ * Group Suite Selector (4 octets) (default: CCMP)
+ * Pairwise Suite Count (2 octets, little endian) (default: 1)
+ * Pairwise Suite List (4 * n octets) (default: CCMP)
+ * Authenticated Key Management Suite Count (2 octets, little endian)
+ * (default: 1)
+ * Authenticated Key Management Suite List (4 * n octets)
+ * (default: unspec 802.1X)
+ * RSN Capabilities (2 octets, little endian) (default: 0)
+ * PMKID Count (2 octets) (default: 0)
+ * PMKID List (16 * n octets)
+ * Management Group Cipher Suite (4 octets) (default: AES-128-CMAC)
+ */
+
+struct rsn_ie_hdr {
+ u8 elem_id; /* WLAN_EID_RSN */
+ u8 len;
+ u8 version[2]; /* little endian */
+} 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;
+} STRUCT_PACKED;
+
+#ifdef CONFIG_IEEE80211W
+struct wpa_igtk_kde {
+ u8 keyid[2];
+ u8 pn[6];
+ u8 igtk[WPA_IGTK_LEN];
+} STRUCT_PACKED;
+#endif /* CONFIG_IEEE80211W */
+
+#ifdef CONFIG_IEEE80211R
+struct rsn_mdie {
+ u8 mobility_domain[MOBILITY_DOMAIN_ID_LEN];
+ u8 ft_capab;
+} STRUCT_PACKED;
+
+#define RSN_FT_CAPAB_FT_OVER_DS BIT(0)
+#define RSN_FT_CAPAB_FT_RESOURCE_REQ_SUPP BIT(1)
+
+struct rsn_ftie {
+ u8 mic_control[2];
+ u8 mic[16];
+ 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
+
+struct rsn_rdie {
+ u8 id;
+ u8 descr_count;
+ le16 status_code;
+} STRUCT_PACKED;
+
+#endif /* CONFIG_IEEE80211R */
+
+#ifdef _MSC_VER
+#pragma pack(pop)
+#endif /* _MSC_VER */
+
+
+int wpa_eapol_key_mic(const u8 *key, int ver, const u8 *buf, size_t len,
+ u8 *mic);
+void 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,
+ u8 *ptk, size_t ptk_len, int use_sha256);
+
+#ifdef CONFIG_IEEE80211R
+int wpa_ft_mic(const u8 *kck, const u8 *sta_addr, const u8 *ap_addr,
+ u8 transaction_seqnum, const u8 *mdie, size_t mdie_len,
+ 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);
+void wpa_pmk_r1_to_ptk(const u8 *pmk_r1, const u8 *snonce, const u8 *anonce,
+ const u8 *sta_addr, const u8 *bssid,
+ const u8 *pmk_r1_name,
+ u8 *ptk, size_t ptk_len, u8 *ptk_name);
+#endif /* CONFIG_IEEE80211R */
+
+struct wpa_ie_data {
+ int proto;
+ int pairwise_cipher;
+ int group_cipher;
+ int key_mgmt;
+ int capabilities;
+ size_t num_pmkid;
+ const u8 *pmkid;
+ int mgmt_group_cipher;
+};
+
+
+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);
+
+void rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa, const u8 *spa,
+ u8 *pmkid, int use_sha256);
+
+const char * wpa_cipher_txt(int cipher);
+const char * wpa_key_mgmt_txt(int key_mgmt, int proto);
+int wpa_compare_rsn_ie(int ft_initial_assoc,
+ const u8 *ie1, size_t ie1len,
+ const u8 *ie2, size_t ie2len);
+int wpa_insert_pmkid(u8 *ies, size_t ies_len, const u8 *pmkid);
+
+#endif /* WPA_COMMON_H */
diff --git a/src/common/wpa_ctrl.c b/src/common/wpa_ctrl.c
new file mode 100644
index 0000000..88d3a02
--- /dev/null
+++ b/src/common/wpa_ctrl.c
@@ -0,0 +1,500 @@
+/*
+ * wpa_supplicant/hostapd control interface library
+ * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#include "includes.h"
+
+#ifdef CONFIG_CTRL_IFACE
+
+#ifdef CONFIG_CTRL_IFACE_UNIX
+#include <sys/un.h>
+#endif /* CONFIG_CTRL_IFACE_UNIX */
+
+#ifdef ANDROID
+#include <cutils/sockets.h>
+#include "private/android_filesystem_config.h"
+#endif /* ANDROID */
+
+#include "wpa_ctrl.h"
+#include "common.h"
+
+
+#if defined(CONFIG_CTRL_IFACE_UNIX) || defined(CONFIG_CTRL_IFACE_UDP)
+#define CTRL_IFACE_SOCKET
+#endif /* CONFIG_CTRL_IFACE_UNIX || CONFIG_CTRL_IFACE_UDP */
+
+
+/**
+ * struct wpa_ctrl - Internal structure for control interface library
+ *
+ * This structure is used by the wpa_supplicant/hostapd control interface
+ * library to store internal data. Programs using the library should not touch
+ * this data directly. They can only use the pointer to the data structure as
+ * an identifier for the control interface connection and use this as one of
+ * the arguments for most of the control interface library functions.
+ */
+struct wpa_ctrl {
+#ifdef CONFIG_CTRL_IFACE_UDP
+ int s;
+ struct sockaddr_in local;
+ struct sockaddr_in dest;
+ char *cookie;
+#endif /* CONFIG_CTRL_IFACE_UDP */
+#ifdef CONFIG_CTRL_IFACE_UNIX
+ int s;
+ struct sockaddr_un local;
+ struct sockaddr_un dest;
+#endif /* CONFIG_CTRL_IFACE_UNIX */
+#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
+ HANDLE pipe;
+#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
+};
+
+
+#ifdef CONFIG_CTRL_IFACE_UNIX
+
+#ifndef CONFIG_CTRL_IFACE_CLIENT_DIR
+#define CONFIG_CTRL_IFACE_CLIENT_DIR "/tmp"
+#endif /* CONFIG_CTRL_IFACE_CLIENT_DIR */
+#ifndef CONFIG_CTRL_IFACE_CLIENT_PREFIX
+#define CONFIG_CTRL_IFACE_CLIENT_PREFIX "wpa_ctrl_"
+#endif /* CONFIG_CTRL_IFACE_CLIENT_PREFIX */
+
+
+struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
+{
+ struct wpa_ctrl *ctrl;
+ static int counter = 0;
+ int ret;
+ size_t res;
+ int tries = 0;
+
+ ctrl = os_malloc(sizeof(*ctrl));
+ if (ctrl == NULL)
+ return NULL;
+ os_memset(ctrl, 0, sizeof(*ctrl));
+
+ ctrl->s = socket(PF_UNIX, SOCK_DGRAM, 0);
+ if (ctrl->s < 0) {
+ os_free(ctrl);
+ return NULL;
+ }
+
+ ctrl->local.sun_family = AF_UNIX;
+ counter++;
+try_again:
+ ret = os_snprintf(ctrl->local.sun_path, sizeof(ctrl->local.sun_path),
+ CONFIG_CTRL_IFACE_CLIENT_DIR "/"
+ CONFIG_CTRL_IFACE_CLIENT_PREFIX "%d-%d",
+ (int) getpid(), counter);
+ if (ret < 0 || (size_t) ret >= sizeof(ctrl->local.sun_path)) {
+ close(ctrl->s);
+ os_free(ctrl);
+ return NULL;
+ }
+ tries++;
+ if (bind(ctrl->s, (struct sockaddr *) &ctrl->local,
+ sizeof(ctrl->local)) < 0) {
+ if (errno == EADDRINUSE && tries < 2) {
+ /*
+ * getpid() returns unique identifier for this instance
+ * of wpa_ctrl, so the existing socket file must have
+ * been left by unclean termination of an earlier run.
+ * Remove the file and try again.
+ */
+ unlink(ctrl->local.sun_path);
+ goto try_again;
+ }
+ close(ctrl->s);
+ os_free(ctrl);
+ return NULL;
+ }
+
+#ifdef ANDROID
+ chmod(ctrl->local.sun_path, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
+ chown(ctrl->local.sun_path, AID_SYSTEM, AID_WIFI);
+ /*
+ * If the ctrl_path isn't an absolute pathname, assume that
+ * it's the name of a socket in the Android reserved namespace.
+ * Otherwise, it's a normal UNIX domain socket appearing in the
+ * filesystem.
+ */
+ if (ctrl_path != NULL && *ctrl_path != '/') {
+ char buf[21];
+ os_snprintf(buf, sizeof(buf), "wpa_%s", ctrl_path);
+ if (socket_local_client_connect(
+ ctrl->s, buf,
+ ANDROID_SOCKET_NAMESPACE_RESERVED,
+ SOCK_DGRAM) < 0) {
+ close(ctrl->s);
+ unlink(ctrl->local.sun_path);
+ os_free(ctrl);
+ return NULL;
+ }
+ return ctrl;
+ }
+#endif /* ANDROID */
+
+ ctrl->dest.sun_family = AF_UNIX;
+ res = os_strlcpy(ctrl->dest.sun_path, ctrl_path,
+ sizeof(ctrl->dest.sun_path));
+ if (res >= sizeof(ctrl->dest.sun_path)) {
+ close(ctrl->s);
+ os_free(ctrl);
+ return NULL;
+ }
+ if (connect(ctrl->s, (struct sockaddr *) &ctrl->dest,
+ sizeof(ctrl->dest)) < 0) {
+ close(ctrl->s);
+ unlink(ctrl->local.sun_path);
+ os_free(ctrl);
+ return NULL;
+ }
+
+ return ctrl;
+}
+
+
+void wpa_ctrl_close(struct wpa_ctrl *ctrl)
+{
+ if (ctrl == NULL)
+ return;
+ unlink(ctrl->local.sun_path);
+ if (ctrl->s >= 0)
+ close(ctrl->s);
+ os_free(ctrl);
+}
+
+#endif /* CONFIG_CTRL_IFACE_UNIX */
+
+
+#ifdef CONFIG_CTRL_IFACE_UDP
+
+struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
+{
+ struct wpa_ctrl *ctrl;
+ char buf[128];
+ size_t len;
+
+ ctrl = os_malloc(sizeof(*ctrl));
+ if (ctrl == NULL)
+ return NULL;
+ os_memset(ctrl, 0, sizeof(*ctrl));
+
+ ctrl->s = socket(PF_INET, SOCK_DGRAM, 0);
+ if (ctrl->s < 0) {
+ perror("socket");
+ os_free(ctrl);
+ return NULL;
+ }
+
+ ctrl->local.sin_family = AF_INET;
+ ctrl->local.sin_addr.s_addr = htonl((127 << 24) | 1);
+ if (bind(ctrl->s, (struct sockaddr *) &ctrl->local,
+ sizeof(ctrl->local)) < 0) {
+ close(ctrl->s);
+ os_free(ctrl);
+ return NULL;
+ }
+
+ ctrl->dest.sin_family = AF_INET;
+ ctrl->dest.sin_addr.s_addr = htonl((127 << 24) | 1);
+ ctrl->dest.sin_port = htons(WPA_CTRL_IFACE_PORT);
+ if (connect(ctrl->s, (struct sockaddr *) &ctrl->dest,
+ sizeof(ctrl->dest)) < 0) {
+ perror("connect");
+ close(ctrl->s);
+ os_free(ctrl);
+ return NULL;
+ }
+
+ len = sizeof(buf) - 1;
+ if (wpa_ctrl_request(ctrl, "GET_COOKIE", 10, buf, &len, NULL) == 0) {
+ buf[len] = '\0';
+ ctrl->cookie = os_strdup(buf);
+ }
+
+ return ctrl;
+}
+
+
+void wpa_ctrl_close(struct wpa_ctrl *ctrl)
+{
+ close(ctrl->s);
+ os_free(ctrl->cookie);
+ os_free(ctrl);
+}
+
+#endif /* CONFIG_CTRL_IFACE_UDP */
+
+
+#ifdef CTRL_IFACE_SOCKET
+int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len,
+ char *reply, size_t *reply_len,
+ void (*msg_cb)(char *msg, size_t len))
+{
+ struct timeval tv;
+ int res;
+ fd_set rfds;
+ const char *_cmd;
+ char *cmd_buf = NULL;
+ size_t _cmd_len;
+
+#ifdef CONFIG_CTRL_IFACE_UDP
+ if (ctrl->cookie) {
+ char *pos;
+ _cmd_len = os_strlen(ctrl->cookie) + 1 + cmd_len;
+ cmd_buf = os_malloc(_cmd_len);
+ if (cmd_buf == NULL)
+ return -1;
+ _cmd = cmd_buf;
+ pos = cmd_buf;
+ os_strlcpy(pos, ctrl->cookie, _cmd_len);
+ pos += os_strlen(ctrl->cookie);
+ *pos++ = ' ';
+ os_memcpy(pos, cmd, cmd_len);
+ } else
+#endif /* CONFIG_CTRL_IFACE_UDP */
+ {
+ _cmd = cmd;
+ _cmd_len = cmd_len;
+ }
+
+ if (send(ctrl->s, _cmd, _cmd_len, 0) < 0) {
+ os_free(cmd_buf);
+ return -1;
+ }
+ os_free(cmd_buf);
+
+ for (;;) {
+ tv.tv_sec = 10;
+ tv.tv_usec = 0;
+ FD_ZERO(&rfds);
+ FD_SET(ctrl->s, &rfds);
+ res = select(ctrl->s + 1, &rfds, NULL, NULL, &tv);
+ if (res < 0)
+ return res;
+ if (FD_ISSET(ctrl->s, &rfds)) {
+ res = recv(ctrl->s, reply, *reply_len, 0);
+ if (res < 0)
+ return res;
+ if (res > 0 && reply[0] == '<') {
+ /* This is an unsolicited message from
+ * wpa_supplicant, not the reply to the
+ * request. Use msg_cb to report this to the
+ * caller. */
+ if (msg_cb) {
+ /* Make sure the message is nul
+ * terminated. */
+ if ((size_t) res == *reply_len)
+ res = (*reply_len) - 1;
+ reply[res] = '\0';
+ msg_cb(reply, res);
+ }
+ continue;
+ }
+ *reply_len = res;
+ break;
+ } else {
+ return -2;
+ }
+ }
+ return 0;
+}
+#endif /* CTRL_IFACE_SOCKET */
+
+
+static int wpa_ctrl_attach_helper(struct wpa_ctrl *ctrl, int attach)
+{
+ char buf[10];
+ int ret;
+ size_t len = 10;
+
+ ret = wpa_ctrl_request(ctrl, attach ? "ATTACH" : "DETACH", 6,
+ buf, &len, NULL);
+ if (ret < 0)
+ return ret;
+ if (len == 3 && os_memcmp(buf, "OK\n", 3) == 0)
+ return 0;
+ return -1;
+}
+
+
+int wpa_ctrl_attach(struct wpa_ctrl *ctrl)
+{
+ return wpa_ctrl_attach_helper(ctrl, 1);
+}
+
+
+int wpa_ctrl_detach(struct wpa_ctrl *ctrl)
+{
+ return wpa_ctrl_attach_helper(ctrl, 0);
+}
+
+
+#ifdef CTRL_IFACE_SOCKET
+
+int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len)
+{
+ int res;
+
+ res = recv(ctrl->s, reply, *reply_len, 0);
+ if (res < 0)
+ return res;
+ *reply_len = res;
+ return 0;
+}
+
+
+int wpa_ctrl_pending(struct wpa_ctrl *ctrl)
+{
+ struct timeval tv;
+ fd_set rfds;
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+ FD_ZERO(&rfds);
+ FD_SET(ctrl->s, &rfds);
+ select(ctrl->s + 1, &rfds, NULL, NULL, &tv);
+ return FD_ISSET(ctrl->s, &rfds);
+}
+
+
+int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl)
+{
+ return ctrl->s;
+}
+
+#endif /* CTRL_IFACE_SOCKET */
+
+
+#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
+
+#ifndef WPA_SUPPLICANT_NAMED_PIPE
+#define WPA_SUPPLICANT_NAMED_PIPE "WpaSupplicant"
+#endif
+#define NAMED_PIPE_PREFIX TEXT("\\\\.\\pipe\\") TEXT(WPA_SUPPLICANT_NAMED_PIPE)
+
+struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
+{
+ struct wpa_ctrl *ctrl;
+ DWORD mode;
+ TCHAR name[256];
+ int i, ret;
+
+ ctrl = os_malloc(sizeof(*ctrl));
+ if (ctrl == NULL)
+ return NULL;
+ os_memset(ctrl, 0, sizeof(*ctrl));
+
+#ifdef UNICODE
+ if (ctrl_path == NULL)
+ ret = _snwprintf(name, 256, NAMED_PIPE_PREFIX);
+ else
+ ret = _snwprintf(name, 256, NAMED_PIPE_PREFIX TEXT("-%S"),
+ ctrl_path);
+#else /* UNICODE */
+ if (ctrl_path == NULL)
+ ret = os_snprintf(name, 256, NAMED_PIPE_PREFIX);
+ else
+ ret = os_snprintf(name, 256, NAMED_PIPE_PREFIX "-%s",
+ ctrl_path);
+#endif /* UNICODE */
+ if (ret < 0 || ret >= 256) {
+ os_free(ctrl);
+ return NULL;
+ }
+
+ for (i = 0; i < 10; i++) {
+ ctrl->pipe = CreateFile(name, GENERIC_READ | GENERIC_WRITE, 0,
+ NULL, OPEN_EXISTING, 0, NULL);
+ /*
+ * Current named pipe server side in wpa_supplicant is
+ * re-opening the pipe for new clients only after the previous
+ * one is taken into use. This leaves a small window for race
+ * conditions when two connections are being opened at almost
+ * the same time. Retry if that was the case.
+ */
+ if (ctrl->pipe != INVALID_HANDLE_VALUE ||
+ GetLastError() != ERROR_PIPE_BUSY)
+ break;
+ WaitNamedPipe(name, 1000);
+ }
+ if (ctrl->pipe == INVALID_HANDLE_VALUE) {
+ os_free(ctrl);
+ return NULL;
+ }
+
+ mode = PIPE_READMODE_MESSAGE;
+ if (!SetNamedPipeHandleState(ctrl->pipe, &mode, NULL, NULL)) {
+ CloseHandle(ctrl->pipe);
+ os_free(ctrl);
+ return NULL;
+ }
+
+ return ctrl;
+}
+
+
+void wpa_ctrl_close(struct wpa_ctrl *ctrl)
+{
+ CloseHandle(ctrl->pipe);
+ os_free(ctrl);
+}
+
+
+int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len,
+ char *reply, size_t *reply_len,
+ void (*msg_cb)(char *msg, size_t len))
+{
+ DWORD written;
+ DWORD readlen = *reply_len;
+
+ if (!WriteFile(ctrl->pipe, cmd, cmd_len, &written, NULL))
+ return -1;
+
+ if (!ReadFile(ctrl->pipe, reply, *reply_len, &readlen, NULL))
+ return -1;
+ *reply_len = readlen;
+
+ return 0;
+}
+
+
+int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len)
+{
+ DWORD len = *reply_len;
+ if (!ReadFile(ctrl->pipe, reply, *reply_len, &len, NULL))
+ return -1;
+ *reply_len = len;
+ return 0;
+}
+
+
+int wpa_ctrl_pending(struct wpa_ctrl *ctrl)
+{
+ DWORD left;
+
+ if (!PeekNamedPipe(ctrl->pipe, NULL, 0, NULL, &left, NULL))
+ return -1;
+ return left ? 1 : 0;
+}
+
+
+int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl)
+{
+ return -1;
+}
+
+#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
+
+#endif /* CONFIG_CTRL_IFACE */
diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h
new file mode 100644
index 0000000..528cc16
--- /dev/null
+++ b/src/common/wpa_ctrl.h
@@ -0,0 +1,274 @@
+/*
+ * wpa_supplicant/hostapd control interface library
+ * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#ifndef WPA_CTRL_H
+#define WPA_CTRL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* wpa_supplicant control interface - fixed message prefixes */
+
+/** Interactive request for identity/password/pin */
+#define WPA_CTRL_REQ "CTRL-REQ-"
+
+/** Response to identity/password/pin request */
+#define WPA_CTRL_RSP "CTRL-RSP-"
+
+/* Event messages with fixed prefix */
+/** Authentication completed successfully and data connection enabled */
+#define WPA_EVENT_CONNECTED "CTRL-EVENT-CONNECTED "
+/** Disconnected, data connection is not available */
+#define WPA_EVENT_DISCONNECTED "CTRL-EVENT-DISCONNECTED "
+/** Association rejected during connection attempt */
+#define WPA_EVENT_ASSOC_REJECT "CTRL-EVENT-ASSOC-REJECT "
+/** wpa_supplicant is exiting */
+#define WPA_EVENT_TERMINATING "CTRL-EVENT-TERMINATING "
+/** Password change was completed successfully */
+#define WPA_EVENT_PASSWORD_CHANGED "CTRL-EVENT-PASSWORD-CHANGED "
+/** EAP-Request/Notification received */
+#define WPA_EVENT_EAP_NOTIFICATION "CTRL-EVENT-EAP-NOTIFICATION "
+/** EAP authentication started (EAP-Request/Identity received) */
+#define WPA_EVENT_EAP_STARTED "CTRL-EVENT-EAP-STARTED "
+/** EAP method proposed by the server */
+#define WPA_EVENT_EAP_PROPOSED_METHOD "CTRL-EVENT-EAP-PROPOSED-METHOD "
+/** EAP method selected */
+#define WPA_EVENT_EAP_METHOD "CTRL-EVENT-EAP-METHOD "
+/** EAP peer certificate from TLS */
+#define WPA_EVENT_EAP_PEER_CERT "CTRL-EVENT-EAP-PEER-CERT "
+/** EAP TLS certificate chain validation error */
+#define WPA_EVENT_EAP_TLS_CERT_ERROR "CTRL-EVENT-EAP-TLS-CERT-ERROR "
+/** EAP authentication completed successfully */
+#define WPA_EVENT_EAP_SUCCESS "CTRL-EVENT-EAP-SUCCESS "
+/** EAP authentication failed (EAP-Failure received) */
+#define WPA_EVENT_EAP_FAILURE "CTRL-EVENT-EAP-FAILURE "
+/** New scan results available */
+#define WPA_EVENT_SCAN_RESULTS "CTRL-EVENT-SCAN-RESULTS "
+/** wpa_supplicant state change */
+#define WPA_EVENT_STATE_CHANGE "CTRL-EVENT-STATE-CHANGE "
+/** A new BSS entry was added (followed by BSS entry id and BSSID) */
+#define WPA_EVENT_BSS_ADDED "CTRL-EVENT-BSS-ADDED "
+/** A BSS entry was removed (followed by BSS entry id and BSSID) */
+#define WPA_EVENT_BSS_REMOVED "CTRL-EVENT-BSS-REMOVED "
+
+/** WPS overlap detected in PBC mode */
+#define WPS_EVENT_OVERLAP "WPS-OVERLAP-DETECTED "
+/** Available WPS AP with active PBC found in scan results */
+#define WPS_EVENT_AP_AVAILABLE_PBC "WPS-AP-AVAILABLE-PBC "
+/** Available WPS AP with our address as authorized in scan results */
+#define WPS_EVENT_AP_AVAILABLE_AUTH "WPS-AP-AVAILABLE-AUTH "
+/** Available WPS AP with recently selected PIN registrar found in scan results
+ */
+#define WPS_EVENT_AP_AVAILABLE_PIN "WPS-AP-AVAILABLE-PIN "
+/** Available WPS AP found in scan results */
+#define WPS_EVENT_AP_AVAILABLE "WPS-AP-AVAILABLE "
+/** A new credential received */
+#define WPS_EVENT_CRED_RECEIVED "WPS-CRED-RECEIVED "
+/** M2D received */
+#define WPS_EVENT_M2D "WPS-M2D "
+/** WPS registration failed after M2/M2D */
+#define WPS_EVENT_FAIL "WPS-FAIL "
+/** WPS registration completed successfully */
+#define WPS_EVENT_SUCCESS "WPS-SUCCESS "
+/** WPS enrollment attempt timed out and was terminated */
+#define WPS_EVENT_TIMEOUT "WPS-TIMEOUT "
+
+#define WPS_EVENT_ENROLLEE_SEEN "WPS-ENROLLEE-SEEN "
+
+#define WPS_EVENT_OPEN_NETWORK "WPS-OPEN-NETWORK "
+
+/* WPS ER events */
+#define WPS_EVENT_ER_AP_ADD "WPS-ER-AP-ADD "
+#define WPS_EVENT_ER_AP_REMOVE "WPS-ER-AP-REMOVE "
+#define WPS_EVENT_ER_ENROLLEE_ADD "WPS-ER-ENROLLEE-ADD "
+#define WPS_EVENT_ER_ENROLLEE_REMOVE "WPS-ER-ENROLLEE-REMOVE "
+#define WPS_EVENT_ER_AP_SETTINGS "WPS-ER-AP-SETTINGS "
+#define WPS_EVENT_ER_SET_SEL_REG "WPS-ER-AP-SET-SEL-REG "
+
+/** P2P device found */
+#define P2P_EVENT_DEVICE_FOUND "P2P-DEVICE-FOUND "
+/** A P2P device requested GO negotiation, but we were not ready to start the
+ * negotiation */
+#define P2P_EVENT_GO_NEG_REQUEST "P2P-GO-NEG-REQUEST "
+#define P2P_EVENT_GO_NEG_SUCCESS "P2P-GO-NEG-SUCCESS "
+#define P2P_EVENT_GO_NEG_FAILURE "P2P-GO-NEG-FAILURE "
+#define P2P_EVENT_GROUP_FORMATION_SUCCESS "P2P-GROUP-FORMATION-SUCCESS "
+#define P2P_EVENT_GROUP_FORMATION_FAILURE "P2P-GROUP-FORMATION-FAILURE "
+#define P2P_EVENT_GROUP_STARTED "P2P-GROUP-STARTED "
+#define P2P_EVENT_GROUP_REMOVED "P2P-GROUP-REMOVED "
+#define P2P_EVENT_CROSS_CONNECT_ENABLE "P2P-CROSS-CONNECT-ENABLE "
+#define P2P_EVENT_CROSS_CONNECT_DISABLE "P2P-CROSS-CONNECT-DISABLE "
+/* parameters: <peer address> <PIN> */
+#define P2P_EVENT_PROV_DISC_SHOW_PIN "P2P-PROV-DISC-SHOW-PIN "
+/* parameters: <peer address> */
+#define P2P_EVENT_PROV_DISC_ENTER_PIN "P2P-PROV-DISC-ENTER-PIN "
+/* parameters: <peer address> */
+#define P2P_EVENT_PROV_DISC_PBC_REQ "P2P-PROV-DISC-PBC-REQ "
+/* parameters: <peer address> */
+#define P2P_EVENT_PROV_DISC_PBC_RESP "P2P-PROV-DISC-PBC-RESP "
+/* parameters: <freq> <src addr> <dialog token> <update indicator> <TLVs> */
+#define P2P_EVENT_SERV_DISC_REQ "P2P-SERV-DISC-REQ "
+/* parameters: <src addr> <update indicator> <TLVs> */
+#define P2P_EVENT_SERV_DISC_RESP "P2P-SERV-DISC-RESP "
+#define P2P_EVENT_INVITATION_RECEIVED "P2P-INVITATION-RECEIVED "
+#define P2P_EVENT_INVITATION_RESULT "P2P-INVITATION-RESULT "
+
+/* hostapd control interface - fixed message prefixes */
+#define WPS_EVENT_PIN_NEEDED "WPS-PIN-NEEDED "
+#define WPS_EVENT_NEW_AP_SETTINGS "WPS-NEW-AP-SETTINGS "
+#define WPS_EVENT_REG_SUCCESS "WPS-REG-SUCCESS "
+#define WPS_EVENT_AP_SETUP_LOCKED "WPS-AP-SETUP-LOCKED "
+#define WPS_EVENT_AP_SETUP_UNLOCKED "WPS-AP-SETUP-UNLOCKED "
+#define WPS_EVENT_AP_PIN_ENABLED "WPS-AP-PIN-ENABLED "
+#define WPS_EVENT_AP_PIN_DISABLED "WPS-AP-PIN-DISABLED "
+#define AP_STA_CONNECTED "AP-STA-CONNECTED "
+#define AP_STA_DISCONNECTED "AP-STA-DISCONNECTED "
+
+
+/* wpa_supplicant/hostapd control interface access */
+
+/**
+ * wpa_ctrl_open - Open a control interface to wpa_supplicant/hostapd
+ * @ctrl_path: Path for UNIX domain sockets; ignored if UDP sockets are used.
+ * Returns: Pointer to abstract control interface data or %NULL on failure
+ *
+ * This function is used to open a control interface to wpa_supplicant/hostapd.
+ * ctrl_path is usually /var/run/wpa_supplicant or /var/run/hostapd. This path
+ * is configured in wpa_supplicant/hostapd and other programs using the control
+ * interface need to use matching path configuration.
+ */
+struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path);
+
+
+/**
+ * wpa_ctrl_close - Close a control interface to wpa_supplicant/hostapd
+ * @ctrl: Control interface data from wpa_ctrl_open()
+ *
+ * This function is used to close a control interface.
+ */
+void wpa_ctrl_close(struct wpa_ctrl *ctrl);
+
+
+/**
+ * wpa_ctrl_request - Send a command to wpa_supplicant/hostapd
+ * @ctrl: Control interface data from wpa_ctrl_open()
+ * @cmd: Command; usually, ASCII text, e.g., "PING"
+ * @cmd_len: Length of the cmd in bytes
+ * @reply: Buffer for the response
+ * @reply_len: Reply buffer length
+ * @msg_cb: Callback function for unsolicited messages or %NULL if not used
+ * Returns: 0 on success, -1 on error (send or receive failed), -2 on timeout
+ *
+ * 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
+ * for the reply. If unsolicited messages are received, the blocking time may
+ * be longer.
+ *
+ * msg_cb can be used to register a callback function that will be called for
+ * unsolicited messages received while waiting for the command response. These
+ * messages may be received if wpa_ctrl_request() is called at the same time as
+ * wpa_supplicant/hostapd is sending such a message. This can happen only if
+ * the program has used wpa_ctrl_attach() to register itself as a monitor for
+ * event messages. Alternatively to msg_cb, programs can register two control
+ * interface connections and use one of them for commands and the other one for
+ * receiving event messages, in other words, call wpa_ctrl_attach() only for
+ * the control interface connection that will be used for event messages.
+ */
+int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len,
+ char *reply, size_t *reply_len,
+ void (*msg_cb)(char *msg, size_t len));
+
+
+/**
+ * wpa_ctrl_attach - Register as an event monitor for the control interface
+ * @ctrl: Control interface data from wpa_ctrl_open()
+ * Returns: 0 on success, -1 on failure, -2 on timeout
+ *
+ * This function registers the control interface connection as a monitor for
+ * wpa_supplicant/hostapd events. After a success wpa_ctrl_attach() call, the
+ * control interface connection starts receiving event messages that can be
+ * read with wpa_ctrl_recv().
+ */
+int wpa_ctrl_attach(struct wpa_ctrl *ctrl);
+
+
+/**
+ * wpa_ctrl_detach - Unregister event monitor from the control interface
+ * @ctrl: Control interface data from wpa_ctrl_open()
+ * Returns: 0 on success, -1 on failure, -2 on timeout
+ *
+ * This function unregisters the control interface connection as a monitor for
+ * wpa_supplicant/hostapd events, i.e., cancels the registration done with
+ * wpa_ctrl_attach().
+ */
+int wpa_ctrl_detach(struct wpa_ctrl *ctrl);
+
+
+/**
+ * wpa_ctrl_recv - Receive a pending control interface message
+ * @ctrl: Control interface data from wpa_ctrl_open()
+ * @reply: Buffer for the message data
+ * @reply_len: Length of the reply buffer
+ * Returns: 0 on success, -1 on failure
+ *
+ * This function will receive a pending control interface message. This
+ * function will block if no messages are available. The received response will
+ * be written to reply and reply_len is set to the actual length of the reply.
+ * wpa_ctrl_recv() is only used for event messages, i.e., wpa_ctrl_attach()
+ * must have been used to register the control interface as an event monitor.
+ */
+int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len);
+
+
+/**
+ * wpa_ctrl_pending - Check whether there are pending event messages
+ * @ctrl: Control interface data from wpa_ctrl_open()
+ * Returns: 1 if there are pending messages, 0 if no, or -1 on error
+ *
+ * This function will check whether there are any pending control interface
+ * message available to be received with wpa_ctrl_recv(). wpa_ctrl_pending() is
+ * only used for event messages, i.e., wpa_ctrl_attach() must have been used to
+ * register the control interface as an event monitor.
+ */
+int wpa_ctrl_pending(struct wpa_ctrl *ctrl);
+
+
+/**
+ * wpa_ctrl_get_fd - Get file descriptor used by the control interface
+ * @ctrl: Control interface data from wpa_ctrl_open()
+ * Returns: File descriptor used for the connection
+ *
+ * This function can be used to get the file descriptor that is used for the
+ * control interface connection. The returned value can be used, e.g., with
+ * select() while waiting for multiple events.
+ *
+ * The returned file descriptor must not be used directly for sending or
+ * receiving packets; instead, the library functions wpa_ctrl_request() and
+ * wpa_ctrl_recv() must be used for this.
+ */
+int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl);
+
+#ifdef CONFIG_CTRL_IFACE_UDP
+#define WPA_CTRL_IFACE_PORT 9877
+#define WPA_GLOBAL_CTRL_IFACE_PORT 9878
+#endif /* CONFIG_CTRL_IFACE_UDP */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* WPA_CTRL_H */