aboutsummaryrefslogtreecommitdiffstats
path: root/src/common
diff options
context:
space:
mode:
Diffstat (limited to 'src/common')
-rw-r--r--src/common/defs.h33
-rw-r--r--src/common/ieee802_11_common.c302
-rw-r--r--src/common/ieee802_11_common.h11
-rw-r--r--src/common/ieee802_11_defs.h97
-rw-r--r--src/common/privsep_commands.h2
-rw-r--r--src/common/qca-vendor.h107
-rw-r--r--src/common/sae.c13
-rw-r--r--src/common/sae.h2
-rw-r--r--src/common/version.h2
-rw-r--r--src/common/wpa_common.c182
-rw-r--r--src/common/wpa_common.h14
-rw-r--r--src/common/wpa_ctrl.c10
-rw-r--r--src/common/wpa_ctrl.h27
13 files changed, 683 insertions, 119 deletions
diff --git a/src/common/defs.h b/src/common/defs.h
index d4091e31..e1bbd509 100644
--- a/src/common/defs.h
+++ b/src/common/defs.h
@@ -49,6 +49,7 @@ typedef enum { FALSE = 0, TRUE = 1 } Boolean;
#define WPA_KEY_MGMT_WAPI_CERT BIT(13)
#define WPA_KEY_MGMT_CCKM BIT(14)
#define WPA_KEY_MGMT_OSEN BIT(15)
+#define WPA_KEY_MGMT_IEEE8021X_SUITE_B BIT(16)
static inline int wpa_key_mgmt_wpa_ieee8021x(int akm)
{
@@ -56,7 +57,8 @@ static inline int wpa_key_mgmt_wpa_ieee8021x(int akm)
WPA_KEY_MGMT_FT_IEEE8021X |
WPA_KEY_MGMT_CCKM |
WPA_KEY_MGMT_OSEN |
- WPA_KEY_MGMT_IEEE8021X_SHA256));
+ WPA_KEY_MGMT_IEEE8021X_SHA256 |
+ WPA_KEY_MGMT_IEEE8021X_SUITE_B));
}
static inline int wpa_key_mgmt_wpa_psk(int akm)
@@ -85,7 +87,13 @@ static inline int wpa_key_mgmt_sha256(int akm)
{
return !!(akm & (WPA_KEY_MGMT_PSK_SHA256 |
WPA_KEY_MGMT_IEEE8021X_SHA256 |
- WPA_KEY_MGMT_OSEN));
+ WPA_KEY_MGMT_OSEN |
+ WPA_KEY_MGMT_IEEE8021X_SUITE_B));
+}
+
+static inline int wpa_key_mgmt_suite_b(int akm)
+{
+ return !!(akm & WPA_KEY_MGMT_IEEE8021X_SUITE_B);
}
static inline int wpa_key_mgmt_wpa(int akm)
@@ -300,4 +308,25 @@ enum wpa_ctrl_req_type {
/* Maximum number of EAP methods to store for EAP server user information */
#define EAP_MAX_METHODS 8
+/**
+ * enum ht_mode - channel width and offset
+ */
+enum ht_mode {
+ CHAN_UNDEFINED = 0,
+ CHAN_NO_HT,
+ CHAN_HT20,
+ CHAN_HT40PLUS,
+ CHAN_HT40MINUS,
+};
+
+enum mesh_plink_state {
+ PLINK_LISTEN = 1,
+ PLINK_OPEN_SENT,
+ PLINK_OPEN_RCVD,
+ PLINK_CNF_RCVD,
+ PLINK_ESTAB,
+ PLINK_HOLDING,
+ PLINK_BLOCKED,
+};
+
#endif /* DEFS_H */
diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c
index 173a400d..e1d45cf9 100644
--- a/src/common/ieee802_11_common.c
+++ b/src/common/ieee802_11_common.c
@@ -249,6 +249,18 @@ ParseRes ieee802_11_parse_elems(const u8 *start, size_t len,
elems->ht_operation = pos;
elems->ht_operation_len = elen;
break;
+ case WLAN_EID_MESH_CONFIG:
+ elems->mesh_config = pos;
+ elems->mesh_config_len = elen;
+ break;
+ case WLAN_EID_MESH_ID:
+ elems->mesh_id = pos;
+ elems->mesh_id_len = elen;
+ break;
+ case WLAN_EID_PEER_MGMT:
+ elems->peer_mgmt = pos;
+ elems->peer_mgmt_len = elen;
+ break;
case WLAN_EID_VHT_CAP:
elems->vht_capabilities = pos;
elems->vht_capabilities_len = elen;
@@ -290,6 +302,16 @@ ParseRes ieee802_11_parse_elems(const u8 *start, size_t len,
elems->ssid_list = pos;
elems->ssid_list_len = elen;
break;
+ case WLAN_EID_AMPE:
+ elems->ampe = pos;
+ elems->ampe_len = elen;
+ break;
+ case WLAN_EID_MIC:
+ elems->mic = pos;
+ elems->mic_len = elen;
+ /* after mic everything is encrypted, so stop. */
+ left = elen;
+ break;
default:
unknown++;
if (!show_errors)
@@ -515,6 +537,286 @@ enum hostapd_hw_mode ieee80211_freq_to_chan(int freq, u8 *channel)
}
+static const char *us_op_class_cc[] = {
+ "US", "CA", NULL
+};
+
+static const char *eu_op_class_cc[] = {
+ "AL", "AM", "AT", "AZ", "BA", "BE", "BG", "BY", "CH", "CY", "CZ", "DE",
+ "DK", "EE", "EL", "ES", "FI", "FR", "GE", "HR", "HU", "IE", "IS", "IT",
+ "LI", "LT", "LU", "LV", "MD", "ME", "MK", "MT", "NL", "NO", "PL", "PT",
+ "RO", "RS", "RU", "SE", "SI", "SK", "TR", "UA", "UK", NULL
+};
+
+static const char *jp_op_class_cc[] = {
+ "JP", NULL
+};
+
+static const char *cn_op_class_cc[] = {
+ "CN", "CA", NULL
+};
+
+
+static int country_match(const char *cc[], const char *country)
+{
+ int i;
+
+ if (country == NULL)
+ return 0;
+ for (i = 0; cc[i]; i++) {
+ if (cc[i][0] == country[0] && cc[i][1] == country[1])
+ return 1;
+ }
+
+ return 0;
+}
+
+
+static int ieee80211_chan_to_freq_us(u8 op_class, u8 chan)
+{
+ switch (op_class) {
+ case 12: /* channels 1..11 */
+ case 32: /* channels 1..7; 40 MHz */
+ case 33: /* channels 5..11; 40 MHz */
+ if (chan < 1 || chan > 11)
+ return -1;
+ return 2407 + 5 * chan;
+ case 1: /* channels 36,40,44,48 */
+ case 2: /* channels 52,56,60,64; dfs */
+ case 22: /* channels 36,44; 40 MHz */
+ case 23: /* channels 52,60; 40 MHz */
+ case 27: /* channels 40,48; 40 MHz */
+ case 28: /* channels 56,64; 40 MHz */
+ if (chan < 36 || chan > 64)
+ return -1;
+ return 5000 + 5 * chan;
+ case 4: /* channels 100-144 */
+ case 24: /* channels 100-140; 40 MHz */
+ if (chan < 100 || chan > 144)
+ return -1;
+ return 5000 + 5 * chan;
+ case 3: /* channels 149,153,157,161 */
+ case 25: /* channels 149,157; 40 MHz */
+ case 26: /* channels 149,157; 40 MHz */
+ case 30: /* channels 153,161; 40 MHz */
+ case 31: /* channels 153,161; 40 MHz */
+ if (chan < 149 || chan > 161)
+ return -1;
+ return 5000 + 5 * chan;
+ case 34: /* 60 GHz band, channels 1..3 */
+ if (chan < 1 || chan > 3)
+ return -1;
+ return 56160 + 2160 * chan;
+ }
+ return -1;
+}
+
+
+static int ieee80211_chan_to_freq_eu(u8 op_class, u8 chan)
+{
+ switch (op_class) {
+ case 4: /* channels 1..13 */
+ case 11: /* channels 1..9; 40 MHz */
+ case 12: /* channels 5..13; 40 MHz */
+ if (chan < 1 || chan > 13)
+ return -1;
+ return 2407 + 5 * chan;
+ case 1: /* channels 36,40,44,48 */
+ case 2: /* channels 52,56,60,64; dfs */
+ case 5: /* channels 36,44; 40 MHz */
+ case 6: /* channels 52,60; 40 MHz */
+ case 8: /* channels 40,48; 40 MHz */
+ case 9: /* channels 56,64; 40 MHz */
+ if (chan < 36 || chan > 64)
+ return -1;
+ return 5000 + 5 * chan;
+ case 3: /* channels 100-140 */
+ case 7: /* channels 100-132; 40 MHz */
+ case 10: /* channels 104-136; 40 MHz */
+ case 16: /* channels 100-140 */
+ if (chan < 100 || chan > 140)
+ return -1;
+ return 5000 + 5 * chan;
+ case 17: /* channels 149,153,157,161,165,169 */
+ if (chan < 149 || chan > 169)
+ return -1;
+ return 5000 + 5 * chan;
+ case 18: /* 60 GHz band, channels 1..4 */
+ if (chan < 1 || chan > 4)
+ return -1;
+ return 56160 + 2160 * chan;
+ }
+ return -1;
+}
+
+
+static int ieee80211_chan_to_freq_jp(u8 op_class, u8 chan)
+{
+ switch (op_class) {
+ case 30: /* channels 1..13 */
+ case 56: /* channels 1..9; 40 MHz */
+ case 57: /* channels 5..13; 40 MHz */
+ if (chan < 1 || chan > 13)
+ return -1;
+ return 2407 + 5 * chan;
+ case 31: /* channel 14 */
+ if (chan != 14)
+ return -1;
+ return 2414 + 5 * chan;
+ case 1: /* channels 34,38,42,46(old) or 36,40,44,48 */
+ case 32: /* channels 52,56,60,64 */
+ case 33: /* channels 52,56,60,64 */
+ case 36: /* channels 36,44; 40 MHz */
+ case 37: /* channels 52,60; 40 MHz */
+ case 38: /* channels 52,60; 40 MHz */
+ case 41: /* channels 40,48; 40 MHz */
+ case 42: /* channels 56,64; 40 MHz */
+ case 43: /* channels 56,64; 40 MHz */
+ if (chan < 34 || chan > 64)
+ return -1;
+ return 5000 + 5 * chan;
+ case 34: /* channels 100-140 */
+ case 35: /* channels 100-140 */
+ case 39: /* channels 100-132; 40 MHz */
+ case 40: /* channels 100-132; 40 MHz */
+ case 44: /* channels 104-136; 40 MHz */
+ case 45: /* channels 104-136; 40 MHz */
+ case 58: /* channels 100-140 */
+ if (chan < 100 || chan > 140)
+ return -1;
+ return 5000 + 5 * chan;
+ case 59: /* 60 GHz band, channels 1..4 */
+ if (chan < 1 || chan > 3)
+ return -1;
+ return 56160 + 2160 * chan;
+ }
+ return -1;
+}
+
+
+static int ieee80211_chan_to_freq_cn(u8 op_class, u8 chan)
+{
+ switch (op_class) {
+ case 7: /* channels 1..13 */
+ case 8: /* channels 1..9; 40 MHz */
+ case 9: /* channels 5..13; 40 MHz */
+ if (chan < 1 || chan > 13)
+ return -1;
+ return 2407 + 5 * chan;
+ case 1: /* channels 36,40,44,48 */
+ case 2: /* channels 52,56,60,64; dfs */
+ case 4: /* channels 36,44; 40 MHz */
+ case 5: /* channels 52,60; 40 MHz */
+ if (chan < 36 || chan > 64)
+ return -1;
+ return 5000 + 5 * chan;
+ case 3: /* channels 149,153,157,161,165 */
+ case 6: /* channels 149,157; 40 MHz */
+ if (chan < 149 || chan > 165)
+ return -1;
+ return 5000 + 5 * chan;
+ }
+ return -1;
+}
+
+
+static int ieee80211_chan_to_freq_global(u8 op_class, u8 chan)
+{
+ /* Table E-4 in IEEE Std 802.11-2012 - Global operating classes */
+ switch (op_class) {
+ case 81:
+ /* channels 1..13 */
+ if (chan < 1 || chan > 13)
+ return -1;
+ return 2407 + 5 * chan;
+ case 82:
+ /* channel 14 */
+ if (chan != 14)
+ return -1;
+ return 2414 + 5 * chan;
+ case 83: /* channels 1..9; 40 MHz */
+ case 84: /* channels 5..13; 40 MHz */
+ if (chan < 1 || chan > 13)
+ return -1;
+ return 2407 + 5 * chan;
+ case 115: /* channels 36,40,44,48; indoor only */
+ case 116: /* channels 36,44; 40 MHz; indoor only */
+ case 117: /* channels 40,48; 40 MHz; indoor only */
+ case 118: /* channels 52,56,60,64; dfs */
+ case 119: /* channels 52,60; 40 MHz; dfs */
+ case 120: /* channels 56,64; 40 MHz; dfs */
+ if (chan < 36 || chan > 64)
+ return -1;
+ return 5000 + 5 * chan;
+ case 121: /* channels 100-140 */
+ case 122: /* channels 100-142; 40 MHz */
+ case 123: /* channels 104-136; 40 MHz */
+ if (chan < 100 || chan > 140)
+ return -1;
+ return 5000 + 5 * chan;
+ case 124: /* channels 149,153,157,161 */
+ case 125: /* channels 149,153,157,161,165,169 */
+ case 126: /* channels 149,157; 40 MHz */
+ case 127: /* channels 153,161; 40 MHz */
+ if (chan < 149 || chan > 161)
+ return -1;
+ return 5000 + 5 * chan;
+ case 128: /* center freqs 42, 58, 106, 122, 138, 155; 80 MHz */
+ case 130: /* center freqs 42, 58, 106, 122, 138, 155; 80 MHz */
+ if (chan < 36 || chan > 161)
+ return -1;
+ return 5000 + 5 * chan;
+ case 129: /* center freqs 50, 114; 160 MHz */
+ if (chan < 50 || chan > 114)
+ return -1;
+ return 5000 + 5 * chan;
+ case 180: /* 60 GHz band, channels 1..4 */
+ if (chan < 1 || chan > 4)
+ return -1;
+ return 56160 + 2160 * chan;
+ }
+ return -1;
+}
+
+/**
+ * ieee80211_chan_to_freq - Convert channel info to frequency
+ * @country: Country code, if known; otherwise, global operating class is used
+ * @op_class: Operating class
+ * @chan: Channel number
+ * Returns: Frequency in MHz or -1 if the specified channel is unknown
+ */
+int ieee80211_chan_to_freq(const char *country, u8 op_class, u8 chan)
+{
+ int freq;
+
+ if (country_match(us_op_class_cc, country)) {
+ freq = ieee80211_chan_to_freq_us(op_class, chan);
+ if (freq > 0)
+ return freq;
+ }
+
+ if (country_match(eu_op_class_cc, country)) {
+ freq = ieee80211_chan_to_freq_eu(op_class, chan);
+ if (freq > 0)
+ return freq;
+ }
+
+ if (country_match(jp_op_class_cc, country)) {
+ freq = ieee80211_chan_to_freq_jp(op_class, chan);
+ if (freq > 0)
+ return freq;
+ }
+
+ if (country_match(cn_op_class_cc, country)) {
+ freq = ieee80211_chan_to_freq_cn(op_class, chan);
+ if (freq > 0)
+ return freq;
+ }
+
+ return ieee80211_chan_to_freq_global(op_class, chan);
+}
+
+
static int is_11b(u8 rate)
{
return rate == 0x02 || rate == 0x04 || rate == 0x0b || rate == 0x16;
diff --git a/src/common/ieee802_11_common.h b/src/common/ieee802_11_common.h
index cf83057b..2357afc5 100644
--- a/src/common/ieee802_11_common.h
+++ b/src/common/ieee802_11_common.h
@@ -28,6 +28,9 @@ struct ieee802_11_elems {
const u8 *timeout_int;
const u8 *ht_capabilities;
const u8 *ht_operation;
+ const u8 *mesh_config;
+ const u8 *mesh_id;
+ const u8 *peer_mgmt;
const u8 *vht_capabilities;
const u8 *vht_operation;
const u8 *vht_opmode_notif;
@@ -42,6 +45,8 @@ struct ieee802_11_elems {
const u8 *bss_max_idle_period;
const u8 *ssid_list;
const u8 *osen;
+ const u8 *ampe;
+ const u8 *mic;
u8 ssid_len;
u8 supp_rates_len;
@@ -60,6 +65,9 @@ struct ieee802_11_elems {
u8 timeout_int_len;
u8 ht_capabilities_len;
u8 ht_operation_len;
+ u8 mesh_config_len;
+ u8 mesh_id_len;
+ u8 peer_mgmt_len;
u8 vht_capabilities_len;
u8 vht_operation_len;
u8 vendor_ht_cap_len;
@@ -71,6 +79,8 @@ struct ieee802_11_elems {
u8 ext_capab_len;
u8 ssid_list_len;
u8 osen_len;
+ u8 ampe_len;
+ u8 mic_len;
};
typedef enum { ParseOK = 0, ParseUnknown = 1, ParseFailed = -1 } ParseRes;
@@ -95,6 +105,7 @@ struct hostapd_wmm_ac_params {
int hostapd_config_wmm_ac(struct hostapd_wmm_ac_params wmm_ac_params[],
const char *name, const char *val);
enum hostapd_hw_mode ieee80211_freq_to_chan(int freq, u8 *channel);
+int ieee80211_chan_to_freq(const char *country, u8 op_class, u8 chan);
int supp_rates_11b_only(struct ieee802_11_elems *elems);
diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
index 6de71e9e..dfe0fafd 100644
--- a/src/common/ieee802_11_defs.h
+++ b/src/common/ieee802_11_defs.h
@@ -25,6 +25,8 @@
#define WLAN_FC_GET_TYPE(fc) (((fc) & 0x000c) >> 2)
#define WLAN_FC_GET_STYPE(fc) (((fc) & 0x00f0) >> 4)
+#define WLAN_INVALID_MGMT_SEQ 0xFFFF
+
#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)
@@ -194,6 +196,16 @@
#define WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED 26
/* IEEE 802.11e */
#define WLAN_REASON_DISASSOC_LOW_ACK 34
+/* IEEE 802.11s */
+#define WLAN_REASON_MESH_PEERING_CANCELLED 52
+#define WLAN_REASON_MESH_MAX_PEERS 53
+#define WLAN_REASON_MESH_CONFIG_POLICY_VIOLATION 54
+#define WLAN_REASON_MESH_CLOSE_RCVD 55
+#define WLAN_REASON_MESH_MAX_RETRIES 56
+#define WLAN_REASON_MESH_CONFIRM_TIMEOUT 57
+#define WLAN_REASON_MESH_INVALID_GTK 58
+#define WLAN_REASON_MESH_INCONSISTENT_PARAMS 59
+#define WLAN_REASON_MESH_INVALID_SECURITY_CAP 60
/* Information Element IDs */
@@ -234,6 +246,7 @@
#define WLAN_EID_SECONDARY_CHANNEL_OFFSET 62
#define WLAN_EID_WAPI 68
#define WLAN_EID_TIME_ADVERTISEMENT 69
+#define WLAN_EID_RRM_ENABLED_CAPABILITIES 70
#define WLAN_EID_20_40_BSS_COEXISTENCE 72
#define WLAN_EID_20_40_BSS_INTOLERANT 73
#define WLAN_EID_OVERLAPPING_BSS_SCAN_PARAMS 74
@@ -249,7 +262,12 @@
#define WLAN_EID_ADV_PROTO 108
#define WLAN_EID_QOS_MAP_SET 110
#define WLAN_EID_ROAMING_CONSORTIUM 111
+#define WLAN_EID_MESH_CONFIG 113
+#define WLAN_EID_MESH_ID 114
+#define WLAN_EID_PEER_MGMT 117
#define WLAN_EID_EXT_CAPAB 127
+#define WLAN_EID_AMPE 139
+#define WLAN_EID_MIC 140
#define WLAN_EID_CCKM 156
#define WLAN_EID_VHT_CAP 191
#define WLAN_EID_VHT_OPERATION 192
@@ -277,6 +295,7 @@
#define WLAN_ACTION_WNM 10
#define WLAN_ACTION_UNPROTECTED_WNM 11
#define WLAN_ACTION_TDLS 12
+#define WLAN_ACTION_SELF_PROTECTED 15
#define WLAN_ACTION_WMM 17 /* WMM Specification 1.1 */
#define WLAN_ACTION_VENDOR_SPECIFIC 127
@@ -321,6 +340,19 @@
#define WLAN_TDLS_PEER_TRAFFIC_RESPONSE 9
#define WLAN_TDLS_DISCOVERY_REQUEST 10
+/* Radio Measurement Action codes */
+#define WLAN_RRM_RADIO_MEASUREMENT_REQUEST 0
+#define WLAN_RRM_RADIO_MEASUREMENT_REPORT 1
+#define WLAN_RRM_LINK_MEASUREMENT_REQUEST 2
+#define WLAN_RRM_LINK_MEASUREMENT_REPORT 3
+#define WLAN_RRM_NEIGHBOR_REPORT_REQUEST 4
+#define WLAN_RRM_NEIGHBOR_REPORT_RESPONSE 5
+
+/* Radio Measurement capabilities (from RRM Capabilities IE) */
+/* byte 1 (out of 5) */
+#define WLAN_RRM_CAPS_LINK_MEASUREMENT BIT(0)
+#define WLAN_RRM_CAPS_NEIGHBOR_REPORT BIT(1)
+
/* Timeout Interval Type */
#define WLAN_TIMEOUT_REASSOC_DEADLINE 1
#define WLAN_TIMEOUT_KEY_LIFETIME 2
@@ -577,6 +609,10 @@ struct ieee80211_mgmt {
* Entries (optional) */
u8 variable[0];
} STRUCT_PACKED bss_tm_query;
+ struct {
+ u8 action; /* 15 */
+ u8 variable[0];
+ } STRUCT_PACKED slf_prot_action;
} u;
} STRUCT_PACKED action;
} u;
@@ -638,6 +674,15 @@ struct ieee80211_vht_operation {
le16 vht_basic_mcs_set;
} STRUCT_PACKED;
+struct ieee80211_ampe_ie {
+ u8 selected_pairwise_suite[4];
+ u8 local_nonce[32];
+ u8 peer_nonce[32];
+ u8 mgtk[16];
+ u8 key_rsc[8];
+ u8 key_expiration[4];
+} STRUCT_PACKED;
+
#ifdef _MSC_VER
#pragma pack(pop)
#endif /* _MSC_VER */
@@ -754,6 +799,7 @@ struct ieee80211_vht_operation {
#define VHT_CAP_MAX_MPDU_LENGTH_7991 ((u32) BIT(0))
#define VHT_CAP_MAX_MPDU_LENGTH_11454 ((u32) BIT(1))
#define VHT_CAP_MAX_MPDU_LENGTH_MASK ((u32) BIT(0) | BIT(1))
+#define VHT_CAP_MAX_MPDU_LENGTH_MASK_SHIFT 0
#define VHT_CAP_SUPP_CHAN_WIDTH_160MHZ ((u32) BIT(2))
#define VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ ((u32) BIT(3))
#define VHT_CAP_SUPP_CHAN_WIDTH_MASK ((u32) BIT(2) | BIT(3))
@@ -767,13 +813,16 @@ struct ieee80211_vht_operation {
#define VHT_CAP_RXSTBC_4 ((u32) BIT(10))
#define VHT_CAP_RXSTBC_MASK ((u32) BIT(8) | BIT(9) | \
BIT(10))
+#define VHT_CAP_RXSTBC_MASK_SHIFT 8
#define VHT_CAP_SU_BEAMFORMER_CAPABLE ((u32) BIT(11))
#define VHT_CAP_SU_BEAMFORMEE_CAPABLE ((u32) BIT(12))
#define VHT_CAP_BEAMFORMEE_STS_MAX ((u32) BIT(13) | \
BIT(14) | BIT(15))
+#define VHT_CAP_BEAMFORMEE_STS_MAX_SHIFT 13
#define VHT_CAP_BEAMFORMEE_STS_OFFSET 13
#define VHT_CAP_SOUNDING_DIMENSION_MAX ((u32) BIT(16) | \
BIT(17) | BIT(18))
+#define VHT_CAP_SOUNDING_DIMENSION_MAX_SHIFT 16
#define VHT_CAP_SOUNDING_DIMENSION_OFFSET 16
#define VHT_CAP_MU_BEAMFORMER_CAPABLE ((u32) BIT(19))
#define VHT_CAP_MU_BEAMFORMEE_CAPABLE ((u32) BIT(20))
@@ -788,6 +837,7 @@ struct ieee80211_vht_operation {
#define VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_6 ((u32) BIT(24) | BIT(25))
#define VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX ((u32) BIT(23) | \
BIT(24) | BIT(25))
+#define VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT 23
#define VHT_CAP_VHT_LINK_ADAPTATION_VHT_UNSOL_MFB ((u32) BIT(27))
#define VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB ((u32) BIT(26) | BIT(27))
#define VHT_CAP_RX_ANTENNA_PATTERN ((u32) BIT(28))
@@ -855,6 +905,8 @@ struct wmm_information_element {
} STRUCT_PACKED;
+#define WMM_QOSINFO_AP_UAPSD 0x80
+
#define WMM_QOSINFO_STA_AC_MASK 0x0f
#define WMM_QOSINFO_STA_SP_MASK 0x03
#define WMM_QOSINFO_STA_SP_SHIFT 5
@@ -922,11 +974,12 @@ struct wmm_tspec_element {
/* Access Categories / ACI to AC coding */
-enum {
+enum wmm_ac {
WMM_AC_BE = 0 /* Best Effort */,
WMM_AC_BK = 1 /* Background */,
WMM_AC_VI = 2 /* Video */,
- WMM_AC_VO = 3 /* Voice */
+ WMM_AC_VO = 3 /* Voice */,
+ WMM_AC_NUM = 4
};
@@ -1087,6 +1140,19 @@ enum wifi_display_subelem {
WFD_SUBELEM_SESSION_INFO = 9
};
+/* 802.11s */
+#define MESH_SYNC_METHOD_NEIGHBOR_OFFSET 1
+#define MESH_SYNC_METHOD_VENDOR 255
+#define MESH_PATH_PROTOCOL_HWMP 1
+#define MESH_PATH_PROTOCOL_VENDOR 255
+#define MESH_PATH_METRIC_AIRTIME 1
+#define MESH_PATH_METRIC_VENDOR 255
+
+enum plink_action_field {
+ PLINK_OPEN = 1,
+ PLINK_CONFIRM,
+ PLINK_CLOSE
+};
#define OUI_BROADCOM 0x00904c /* Broadcom (Epigram) */
@@ -1122,6 +1188,7 @@ enum wifi_display_subelem {
#define WLAN_AKM_SUITE_FT_PSK 0x000FAC04
#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05
#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06
+#define WLAN_AKM_SUITE_8021X_SUITE_B 0x000FAC11
#define WLAN_AKM_SUITE_CCKM 0x00409600
#define WLAN_AKM_SUITE_OSEN 0x506f9a01
@@ -1247,4 +1314,30 @@ enum wnm_sleep_mode_subelement_id {
#define CHAN_SWITCH_MODE_ALLOW_TX 0
#define CHAN_SWITCH_MODE_BLOCK_TX 1
+struct tpc_report {
+ u8 eid;
+ u8 len;
+ u8 tx_power;
+ u8 link_margin;
+} STRUCT_PACKED;
+
+/* IEEE Std 802.11-2012, 8.5.7.4 - Link Measurement Request frame format */
+struct rrm_link_measurement_request {
+ u8 dialog_token;
+ s8 tx_power;
+ s8 max_tp;
+ u8 variable[0];
+} STRUCT_PACKED;
+
+/* IEEE Std 802.11-2012, 8.5.7.5 - Link Measurement Report frame format */
+struct rrm_link_measurement_report {
+ u8 dialog_token;
+ struct tpc_report tpc;
+ u8 rx_ant_id;
+ u8 tx_ant_id;
+ u8 rcpi;
+ u8 rsni;
+ u8 variable[0];
+} STRUCT_PACKED;
+
#endif /* IEEE802_11_DEFS_H */
diff --git a/src/common/privsep_commands.h b/src/common/privsep_commands.h
index 858b51d3..4dc34c4a 100644
--- a/src/common/privsep_commands.h
+++ b/src/common/privsep_commands.h
@@ -31,7 +31,9 @@ struct privsep_cmd_associate
u8 bssid[ETH_ALEN];
u8 ssid[32];
size_t ssid_len;
+ int hwmode;
int freq;
+ int channel;
int pairwise_suite;
int group_suite;
int key_mgmt_suite;
diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h
index ad3bdfd6..ec1be863 100644
--- a/src/common/qca-vendor.h
+++ b/src/common/qca-vendor.h
@@ -50,6 +50,25 @@ enum qca_radiotap_vendor_ids {
* @QCA_NL80211_VENDOR_SUBCMD_NAN: NAN command/event which is used to pass
* NAN Request/Response and NAN Indication messages. These messages are
* interpreted between the framework and the firmware component.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY: Set key operation that can be
+ * used to configure PMK to the driver even when not connected. This can
+ * be used to request offloading of key management operations. Only used
+ * if device supports QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH: An extended version of
+ * NL80211_CMD_ROAM event with optional attributes including information
+ * from offloaded key management operation. Uses
+ * enum qca_wlan_vendor_attr_roam_auth attributes. Only used
+ * if device supports QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_DO_ACS: ACS command/event which is used to
+ * invoke the ACS function in device and pass selected channels to
+ * hostapd.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES: Command to get the features
+ * supported by the driver. enum qca_wlan_vendor_features defines
+ * the possible features.
*/
enum qca_nl80211_vendor_subcmds {
QCA_NL80211_VENDOR_SUBCMD_UNSPEC = 0,
@@ -60,7 +79,42 @@ enum qca_nl80211_vendor_subcmds {
QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY = 11,
QCA_NL80211_VENDOR_SUBCMD_NAN = 12,
QCA_NL80211_VENDOR_SUBMCD_STATS_EXT = 13,
- /* 14..49 - reserved for QCA */
+ QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET = 14,
+ QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET = 15,
+ QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR = 16,
+ QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS = 17,
+ QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS = 18,
+ QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS = 19,
+ QCA_NL80211_VENDOR_SUBCMD_GSCAN_START = 20,
+ QCA_NL80211_VENDOR_SUBCMD_GSCAN_STOP = 21,
+ QCA_NL80211_VENDOR_SUBCMD_GSCAN_GET_VALID_CHANNELS = 22,
+ QCA_NL80211_VENDOR_SUBCMD_GSCAN_GET_CAPABILITIES = 23,
+ QCA_NL80211_VENDOR_SUBCMD_GSCAN_GET_CACHED_RESULTS = 24,
+ QCA_NL80211_VENDOR_SUBCMD_GSCAN_SCAN_RESULTS_AVAILABLE = 25,
+ QCA_NL80211_VENDOR_SUBCMD_GSCAN_FULL_SCAN_RESULT = 26,
+ QCA_NL80211_VENDOR_SUBCMD_GSCAN_SCAN_EVENT = 27,
+ QCA_NL80211_VENDOR_SUBCMD_GSCAN_HOTLIST_AP_FOUND = 28,
+ QCA_NL80211_VENDOR_SUBCMD_GSCAN_SET_BSSID_HOTLIST = 29,
+ QCA_NL80211_VENDOR_SUBCMD_GSCAN_RESET_BSSID_HOTLIST = 30,
+ QCA_NL80211_VENDOR_SUBCMD_GSCAN_SIGNIFICANT_CHANGE = 31,
+ QCA_NL80211_VENDOR_SUBCMD_GSCAN_SET_SIGNIFICANT_CHANGE = 32,
+ QCA_NL80211_VENDOR_SUBCMD_GSCAN_RESET_SIGNIFICANT_CHANGE = 33,
+ QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE = 34,
+ QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE = 35,
+ QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS = 36,
+ QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE = 37,
+ QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES = 38,
+ QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI = 39,
+ QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG = 40,
+ QCA_NL80211_VENDOR_SUBCMD_GSCAN_HOTLIST_AP_LOST = 41,
+ QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX = 42,
+ /* 43..49 - reserved for QCA */
+ QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY = 50,
+ QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH = 51,
+ QCA_NL80211_VENDOR_SUBCMD_APFIND = 52,
+ /* 53 - reserved for QCA */
+ QCA_NL80211_VENDOR_SUBCMD_DO_ACS = 54,
+ QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES = 55,
};
@@ -78,6 +132,8 @@ enum qca_wlan_vendor_attr {
* by enum qca_roaming_policy. */
QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY = 5,
QCA_WLAN_VENDOR_ATTR_MAC_ADDR = 6,
+ /* used by QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES */
+ QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS = 7,
/* keep last */
QCA_WLAN_VENDOR_ATTR_AFTER_LAST,
QCA_WLAN_VENDOR_ATTR_MAX = QCA_WLAN_VENDOR_ATTR_AFTER_LAST - 1,
@@ -89,4 +145,53 @@ enum qca_roaming_policy {
QCA_ROAMING_ALLOWED_WITHIN_ESS,
};
+enum qca_wlan_vendor_attr_roam_auth {
+ QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
+ QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
+ QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
+ QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
+ QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
+ QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
+ QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_MAX =
+ QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AFTER_LAST - 1
+};
+
+enum qca_wlan_vendor_attr_acs_offload {
+ QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL,
+ QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL,
+ QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
+ QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED,
+ QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED,
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_ACS_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_ACS_MAX =
+ QCA_WLAN_VENDOR_ATTR_ACS_AFTER_LAST - 1
+};
+
+enum qca_wlan_vendor_acs_hw_mode {
+ QCA_ACS_MODE_IEEE80211B,
+ QCA_ACS_MODE_IEEE80211G,
+ QCA_ACS_MODE_IEEE80211A,
+ QCA_ACS_MODE_IEEE80211AD,
+};
+
+/**
+ * enum qca_wlan_vendor_features - Vendor device/driver feature flags
+ *
+ * @QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD: Device supports key
+ * management offload, a mechanism where the station's firmware
+ * does the exchange with the AP to establish the temporal keys
+ * after roaming, rather than having the user space wpa_supplicant do it.
+ * @NUM_QCA_WLAN_VENDOR_FEATURES: Number of assigned feature bits
+ */
+enum qca_wlan_vendor_features {
+ QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD = 0,
+ NUM_QCA_WLAN_VENDOR_FEATURES /* keep last */
+};
+
#endif /* QCA_VENDOR_H */
diff --git a/src/common/sae.c b/src/common/sae.c
index b67623f8..58889580 100644
--- a/src/common/sae.c
+++ b/src/common/sae.c
@@ -87,7 +87,8 @@ void sae_clear_temp_data(struct sae_data *sae)
crypto_ec_point_deinit(tmp->pwe_ecc, 1);
crypto_ec_point_deinit(tmp->own_commit_element_ecc, 0);
crypto_ec_point_deinit(tmp->peer_commit_element_ecc, 0);
- os_free(sae->tmp);
+ wpabuf_free(tmp->anti_clogging_token);
+ bin_clear_free(tmp, sizeof(*tmp));
sae->tmp = NULL;
}
@@ -623,8 +624,10 @@ static int sae_derive_keys(struct sae_data *sae, const u8 *k)
wpa_hexdump(MSG_DEBUG, "SAE: PMKID", val, SAE_PMKID_LEN);
sha256_prf(keyseed, sizeof(keyseed), "SAE KCK and PMK",
val, sae->tmp->prime_len, keys, sizeof(keys));
+ os_memset(keyseed, 0, sizeof(keyseed));
os_memcpy(sae->tmp->kck, keys, SAE_KCK_LEN);
os_memcpy(sae->pmk, keys + SAE_KCK_LEN, SAE_PMK_LEN);
+ os_memset(keys, 0, sizeof(keys));
wpa_hexdump_key(MSG_DEBUG, "SAE: KCK", sae->tmp->kck, SAE_KCK_LEN);
wpa_hexdump_key(MSG_DEBUG, "SAE: PMK", sae->pmk, SAE_PMK_LEN);
@@ -656,8 +659,11 @@ void sae_write_commit(struct sae_data *sae, struct wpabuf *buf,
return;
wpabuf_put_le16(buf, sae->group); /* Finite Cyclic Group */
- if (token)
+ if (token) {
wpabuf_put_buf(buf, token);
+ wpa_hexdump(MSG_DEBUG, "SAE: Anti-clogging token",
+ wpabuf_head(token), wpabuf_len(token));
+ }
pos = wpabuf_put(buf, sae->tmp->prime_len);
crypto_bignum_to_bin(sae->tmp->own_commit_scalar, pos,
sae->tmp->prime_len, sae->tmp->prime_len);
@@ -682,8 +688,7 @@ void sae_write_commit(struct sae_data *sae, struct wpabuf *buf,
}
-static u16 sae_group_allowed(struct sae_data *sae, int *allowed_groups,
- u16 group)
+u16 sae_group_allowed(struct sae_data *sae, int *allowed_groups, u16 group)
{
if (allowed_groups) {
int i;
diff --git a/src/common/sae.h b/src/common/sae.h
index d82a98e8..89d74ab1 100644
--- a/src/common/sae.h
+++ b/src/common/sae.h
@@ -35,6 +35,7 @@ struct sae_temporary_data {
const struct crypto_bignum *order;
struct crypto_bignum *prime_buf;
struct crypto_bignum *order_buf;
+ struct wpabuf *anti_clogging_token;
};
struct sae_data {
@@ -60,5 +61,6 @@ u16 sae_parse_commit(struct sae_data *sae, const u8 *data, size_t len,
const u8 **token, size_t *token_len, int *allowed_groups);
void sae_write_confirm(struct sae_data *sae, struct wpabuf *buf);
int sae_check_confirm(struct sae_data *sae, const u8 *data, size_t len);
+u16 sae_group_allowed(struct sae_data *sae, int *allowed_groups, u16 group);
#endif /* SAE_H */
diff --git a/src/common/version.h b/src/common/version.h
index 726289d9..c662270e 100644
--- a/src/common/version.h
+++ b/src/common/version.h
@@ -5,6 +5,6 @@
#define VERSION_STR_POSTFIX ""
#endif /* VERSION_STR_POSTFIX */
-#define VERSION_STR "2.3" VERSION_STR_POSTFIX
+#define VERSION_STR "2.4-devel" VERSION_STR_POSTFIX
#endif /* VERSION_H */
diff --git a/src/common/wpa_common.c b/src/common/wpa_common.c
index 998a51a8..a573e11e 100644
--- a/src/common/wpa_common.c
+++ b/src/common/wpa_common.c
@@ -14,7 +14,6 @@
#include "crypto/sha256.h"
#include "crypto/aes_wrap.h"
#include "crypto/crypto.h"
-#include "drivers/driver.h"
#include "ieee802_11_defs.h"
#include "defs.h"
#include "wpa_common.h"
@@ -23,6 +22,7 @@
/**
* wpa_eapol_key_mic - Calculate EAPOL-Key MIC
* @key: EAPOL-Key Key Confirmation Key (KCK)
+ * @akmp: WPA_KEY_MGMT_* used in key derivation
* @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)
@@ -38,10 +38,10 @@
* 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)
+int wpa_eapol_key_mic(const u8 *key, int akmp, int ver, const u8 *buf,
+ size_t len, u8 *mic)
{
- u8 hash[SHA1_MAC_LEN];
+ u8 hash[SHA256_MAC_LEN];
switch (ver) {
#ifndef CONFIG_FIPS
@@ -57,11 +57,23 @@ int wpa_eapol_key_mic(const u8 *key, int ver, const u8 *buf, size_t len,
case WPA_KEY_INFO_TYPE_AES_128_CMAC:
return omac1_aes_128(key, buf, len, mic);
#endif /* CONFIG_IEEE80211R || CONFIG_IEEE80211W */
-#ifdef CONFIG_HS20
case WPA_KEY_INFO_TYPE_AKM_DEFINED:
- /* FIX: This should be based on negotiated AKM */
- return omac1_aes_128(key, buf, len, mic);
+ switch (akmp) {
+#ifdef CONFIG_HS20
+ case WPA_KEY_MGMT_OSEN:
+ return omac1_aes_128(key, buf, len, mic);
#endif /* CONFIG_HS20 */
+#ifdef CONFIG_SUITEB
+ case WPA_KEY_MGMT_IEEE8021X_SUITE_B:
+ if (hmac_sha256(key, 16, buf, len, hash))
+ return -1;
+ os_memcpy(mic, hash, MD5_MAC_LEN);
+ break;
+#endif /* CONFIG_SUITEB */
+ default:
+ return -1;
+ }
+ break;
default:
return -1;
}
@@ -399,6 +411,8 @@ static int rsn_key_mgmt_to_bitfield(const u8 *s)
if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_SAE)
return WPA_KEY_MGMT_FT_SAE;
#endif /* CONFIG_SAE */
+ if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_802_1X_SUITE_B)
+ return WPA_KEY_MGMT_IEEE8021X_SUITE_B;
return 0;
}
@@ -496,7 +510,7 @@ int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
count = WPA_GET_LE16(pos);
pos += 2;
left -= 2;
- if (count == 0 || left < count * RSN_SELECTOR_LEN) {
+ if (count == 0 || count > left / RSN_SELECTOR_LEN) {
wpa_printf(MSG_DEBUG, "%s: ie count botch (pairwise), "
"count %u left %u", __func__, count, left);
return -4;
@@ -524,7 +538,7 @@ int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
count = WPA_GET_LE16(pos);
pos += 2;
left -= 2;
- if (count == 0 || left < count * RSN_SELECTOR_LEN) {
+ if (count == 0 || count > left / RSN_SELECTOR_LEN) {
wpa_printf(MSG_DEBUG, "%s: ie count botch (key mgmt), "
"count %u left %u", __func__, count, left);
return -6;
@@ -547,17 +561,17 @@ int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
}
if (left >= 2) {
- data->num_pmkid = WPA_GET_LE16(pos);
+ u16 num_pmkid = WPA_GET_LE16(pos);
pos += 2;
left -= 2;
- if (left < (int) data->num_pmkid * PMKID_LEN) {
+ if (num_pmkid > (unsigned int) left / PMKID_LEN) {
wpa_printf(MSG_DEBUG, "%s: PMKID underflow "
- "(num_pmkid=%lu left=%d)",
- __func__, (unsigned long) data->num_pmkid,
- left);
+ "(num_pmkid=%u left=%d)",
+ __func__, num_pmkid, left);
data->num_pmkid = 0;
return -9;
} else {
+ data->num_pmkid = num_pmkid;
data->pmkid = pos;
pos += data->num_pmkid * PMKID_LEN;
left -= data->num_pmkid * PMKID_LEN;
@@ -674,7 +688,7 @@ int wpa_parse_wpa_ie_wpa(const u8 *wpa_ie, size_t wpa_ie_len,
count = WPA_GET_LE16(pos);
pos += 2;
left -= 2;
- if (count == 0 || left < count * WPA_SELECTOR_LEN) {
+ if (count == 0 || count > left / WPA_SELECTOR_LEN) {
wpa_printf(MSG_DEBUG, "%s: ie count botch (pairwise), "
"count %u left %u", __func__, count, left);
return -4;
@@ -695,7 +709,7 @@ int wpa_parse_wpa_ie_wpa(const u8 *wpa_ie, size_t wpa_ie_len,
count = WPA_GET_LE16(pos);
pos += 2;
left -= 2;
- if (count == 0 || left < count * WPA_SELECTOR_LEN) {
+ if (count == 0 || count > left / WPA_SELECTOR_LEN) {
wpa_printf(MSG_DEBUG, "%s: ie count botch (key mgmt), "
"count %u left %u", __func__, count, left);
return -6;
@@ -928,6 +942,39 @@ void rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa, const u8 *spa,
}
+#ifdef CONFIG_SUITEB
+/**
+ * rsn_pmkid_suite_b - Calculate PMK identifier for Suite B AKM
+ * @kck: Key confirmation key
+ * @kck_len: Length of kck in bytes
+ * @aa: Authenticator address
+ * @spa: Supplicant address
+ * @pmkid: Buffer for PMKID
+ * Returns: 0 on success, -1 on failure
+ *
+ * IEEE Std 802.11ac-2013 - 11.6.1.3 Pairwise key hierarchy
+ * PMKID = Truncate(HMAC-SHA-256(KCK, "PMK Name" || AA || SPA))
+ */
+int rsn_pmkid_suite_b(const u8 *kck, size_t kck_len, const u8 *aa,
+ const u8 *spa, u8 *pmkid)
+{
+ 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;
+
+ if (hmac_sha256_vector(kck, kck_len, 3, addr, len, hash) < 0)
+ return -1;
+ os_memcpy(pmkid, hash, PMKID_LEN);
+ return 0;
+}
+#endif /* CONFIG_SUITEB */
+
+
/**
* wpa_cipher_txt - Convert cipher suite to a text string
* @cipher: Cipher suite (WPA_CIPHER_* enum)
@@ -997,6 +1044,16 @@ const char * wpa_key_mgmt_txt(int key_mgmt, int proto)
case WPA_KEY_MGMT_PSK_SHA256:
return "WPA2-PSK-SHA256";
#endif /* CONFIG_IEEE80211W */
+ case WPA_KEY_MGMT_WPS:
+ return "WPS";
+ case WPA_KEY_MGMT_SAE:
+ return "SAE";
+ case WPA_KEY_MGMT_FT_SAE:
+ return "FT-SAE";
+ case WPA_KEY_MGMT_OSEN:
+ return "OSEN";
+ case WPA_KEY_MGMT_IEEE8021X_SUITE_B:
+ return "WPA2-EAP-SUITE-B";
default:
return "UNKNOWN";
}
@@ -1023,6 +1080,8 @@ u32 wpa_akm_to_suite(int akm)
return WLAN_AKM_SUITE_CCKM;
if (akm & WPA_KEY_MGMT_OSEN)
return WLAN_AKM_SUITE_OSEN;
+ if (akm & WPA_KEY_MGMT_IEEE8021X_SUITE_B)
+ return WLAN_AKM_SUITE_8021X_SUITE_B;
return 0;
}
@@ -1417,56 +1476,56 @@ int wpa_write_ciphers(char *start, char *end, int ciphers, const char *delim)
if (ciphers & WPA_CIPHER_CCMP_256) {
ret = os_snprintf(pos, end - pos, "%sCCMP-256",
pos == start ? "" : delim);
- if (ret < 0 || ret >= end - pos)
+ if (os_snprintf_error(end - pos, ret))
return -1;
pos += ret;
}
if (ciphers & WPA_CIPHER_GCMP_256) {
ret = os_snprintf(pos, end - pos, "%sGCMP-256",
pos == start ? "" : delim);
- if (ret < 0 || ret >= end - pos)
+ if (os_snprintf_error(end - pos, ret))
return -1;
pos += ret;
}
if (ciphers & WPA_CIPHER_CCMP) {
ret = os_snprintf(pos, end - pos, "%sCCMP",
pos == start ? "" : delim);
- if (ret < 0 || ret >= end - pos)
+ if (os_snprintf_error(end - pos, ret))
return -1;
pos += ret;
}
if (ciphers & WPA_CIPHER_GCMP) {
ret = os_snprintf(pos, end - pos, "%sGCMP",
pos == start ? "" : delim);
- if (ret < 0 || ret >= end - pos)
+ if (os_snprintf_error(end - pos, ret))
return -1;
pos += ret;
}
if (ciphers & WPA_CIPHER_TKIP) {
ret = os_snprintf(pos, end - pos, "%sTKIP",
pos == start ? "" : delim);
- if (ret < 0 || ret >= end - pos)
+ if (os_snprintf_error(end - pos, ret))
return -1;
pos += ret;
}
if (ciphers & WPA_CIPHER_WEP104) {
ret = os_snprintf(pos, end - pos, "%sWEP104",
pos == start ? "" : delim);
- if (ret < 0 || ret >= end - pos)
+ if (os_snprintf_error(end - pos, ret))
return -1;
pos += ret;
}
if (ciphers & WPA_CIPHER_WEP40) {
ret = os_snprintf(pos, end - pos, "%sWEP40",
pos == start ? "" : delim);
- if (ret < 0 || ret >= end - pos)
+ if (os_snprintf_error(end - pos, ret))
return -1;
pos += ret;
}
if (ciphers & WPA_CIPHER_NONE) {
ret = os_snprintf(pos, end - pos, "%sNONE",
pos == start ? "" : delim);
- if (ret < 0 || ret >= end - pos)
+ if (os_snprintf_error(end - pos, ret))
return -1;
pos += ret;
}
@@ -1497,78 +1556,3 @@ int wpa_select_ap_group_cipher(int wpa, int wpa_pairwise, int rsn_pairwise)
return WPA_CIPHER_CCMP_256;
return WPA_CIPHER_CCMP;
}
-
-
-static int wpa_check_wowlan_trigger(const char *start, const char *trigger,
- int capa_trigger, u8 *param_trigger)
-{
- if (os_strcmp(start, trigger) != 0)
- return 0;
- if (!capa_trigger)
- return 0;
-
- *param_trigger = 1;
- return 1;
-}
-
-
-struct wowlan_triggers *wpa_get_wowlan_triggers(const char *wowlan_triggers,
- struct wpa_driver_capa *capa)
-{
- struct wowlan_triggers *triggers;
- char *start, *end, *buf;
- int last;
-
- if (!wowlan_triggers)
- return NULL;
-
- buf = os_strdup(wowlan_triggers);
- if (buf == NULL)
- return NULL;
-
- triggers = os_zalloc(sizeof(*triggers));
- if (triggers == NULL)
- goto out;
-
-#define CHECK_TRIGGER(trigger) \
- wpa_check_wowlan_trigger(start, #trigger, \
- capa->wowlan_triggers.trigger, \
- &triggers->trigger)
-
- start = buf;
- while (*start != '\0') {
- while (isblank(*start))
- start++;
- if (*start == '\0')
- break;
- end = start;
- while (!isblank(*end) && *end != '\0')
- end++;
- last = *end == '\0';
- *end = '\0';
-
- if (!CHECK_TRIGGER(any) &&
- !CHECK_TRIGGER(disconnect) &&
- !CHECK_TRIGGER(magic_pkt) &&
- !CHECK_TRIGGER(gtk_rekey_failure) &&
- !CHECK_TRIGGER(eap_identity_req) &&
- !CHECK_TRIGGER(four_way_handshake) &&
- !CHECK_TRIGGER(rfkill_release)) {
- wpa_printf(MSG_DEBUG,
- "Unknown/unsupported wowlan trigger '%s'",
- start);
- os_free(triggers);
- triggers = NULL;
- goto out;
- }
-
- if (last)
- break;
- start = end + 1;
- }
-#undef CHECK_TRIGGER
-
-out:
- os_free(buf);
- return triggers;
-}
diff --git a/src/common/wpa_common.h b/src/common/wpa_common.h
index 0ef5a9d1..17bed34a 100644
--- a/src/common/wpa_common.h
+++ b/src/common/wpa_common.h
@@ -327,8 +327,8 @@ struct rsn_rdie {
#endif /* _MSC_VER */
-int wpa_eapol_key_mic(const u8 *key, int ver, const u8 *buf, size_t len,
- u8 *mic);
+int wpa_eapol_key_mic(const u8 *key, int akmp, 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,
@@ -374,6 +374,16 @@ int wpa_parse_wpa_ie_wpa(const u8 *wpa_ie, size_t wpa_ie_len,
void rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa, const u8 *spa,
u8 *pmkid, int use_sha256);
+#ifdef CONFIG_SUITEB
+int rsn_pmkid_suite_b(const u8 *kck, size_t kck_len, const u8 *aa,
+ const u8 *spa, u8 *pmkid);
+#else /* CONFIG_SUITEB */
+static inline int rsn_pmkid_suite_b(const u8 *kck, size_t kck_len, const u8 *aa,
+ const u8 *spa, u8 *pmkid)
+{
+ return -1;
+}
+#endif /* CONFIG_SUITEB */
const char * wpa_cipher_txt(int cipher);
const char * wpa_key_mgmt_txt(int key_mgmt, int proto);
diff --git a/src/common/wpa_ctrl.c b/src/common/wpa_ctrl.c
index 5820a136..ccaaf1b0 100644
--- a/src/common/wpa_ctrl.c
+++ b/src/common/wpa_ctrl.c
@@ -94,10 +94,9 @@ struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
if (ctrl_path == NULL)
return NULL;
- ctrl = os_malloc(sizeof(*ctrl));
+ ctrl = os_zalloc(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) {
@@ -112,7 +111,7 @@ try_again:
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)) {
+ if (os_snprintf_error(sizeof(ctrl->local.sun_path), ret)) {
close(ctrl->s);
os_free(ctrl);
return NULL;
@@ -283,10 +282,9 @@ struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
struct hostent *h;
#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
- ctrl = os_malloc(sizeof(*ctrl));
+ ctrl = os_zalloc(sizeof(*ctrl));
if (ctrl == NULL)
return NULL;
- os_memset(ctrl, 0, sizeof(*ctrl));
#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
ctrl->s = socket(PF_INET6, SOCK_DGRAM, 0);
@@ -643,7 +641,7 @@ struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
ret = os_snprintf(name, 256, NAMED_PIPE_PREFIX "-%s",
ctrl_path);
#endif /* UNICODE */
- if (ret < 0 || ret >= 256) {
+ if (os_snprintf_error(256, ret)) {
os_free(ctrl);
return NULL;
}
diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h
index 4812f8df..1f747eb1 100644
--- a/src/common/wpa_ctrl.h
+++ b/src/common/wpa_ctrl.h
@@ -58,6 +58,8 @@ extern "C" {
#define WPA_EVENT_SCAN_STARTED "CTRL-EVENT-SCAN-STARTED "
/** New scan results available */
#define WPA_EVENT_SCAN_RESULTS "CTRL-EVENT-SCAN-RESULTS "
+/** Scan command failed */
+#define WPA_EVENT_SCAN_FAILED "CTRL-EVENT-SCAN-FAILED "
/** 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) */
@@ -118,6 +120,17 @@ extern "C" {
#define WPS_EVENT_ER_AP_SETTINGS "WPS-ER-AP-SETTINGS "
#define WPS_EVENT_ER_SET_SEL_REG "WPS-ER-AP-SET-SEL-REG "
+/* MESH events */
+#define MESH_GROUP_STARTED "MESH-GROUP-STARTED "
+#define MESH_GROUP_REMOVED "MESH-GROUP-REMOVED "
+#define MESH_PEER_CONNECTED "MESH-PEER-CONNECTED "
+#define MESH_PEER_DISCONNECTED "MESH-PEER-DISCONNECTED "
+
+/* WMM AC events */
+#define WMM_AC_EVENT_TSPEC_ADDED "TSPEC-ADDED "
+#define WMM_AC_EVENT_TSPEC_REMOVED "TSPEC-REMOVED "
+#define WMM_AC_EVENT_TSPEC_REQ_FAILED "TSPEC-REQ-FAILED "
+
/** P2P device found */
#define P2P_EVENT_DEVICE_FOUND "P2P-DEVICE-FOUND "
@@ -187,6 +200,9 @@ extern "C" {
#define EXT_RADIO_WORK_START "EXT-RADIO-WORK-START "
#define EXT_RADIO_WORK_TIMEOUT "EXT-RADIO-WORK-TIMEOUT "
+#define RRM_EVENT_NEIGHBOR_REP_RXED "RRM-NEIGHBOR-REP-RECEIVED "
+#define RRM_EVENT_NEIGHBOR_REP_FAILED "RRM-NEIGHBOR-REP-REQUEST-FAILED "
+
/* hostapd control interface - fixed message prefixes */
#define WPS_EVENT_PIN_NEEDED "WPS-PIN-NEEDED "
#define WPS_EVENT_NEW_AP_SETTINGS "WPS-NEW-AP-SETTINGS "
@@ -204,6 +220,9 @@ extern "C" {
#define AP_EVENT_ENABLED "AP-ENABLED "
#define AP_EVENT_DISABLED "AP-DISABLED "
+#define INTERFACE_ENABLED "INTERFACE-ENABLED "
+#define INTERFACE_DISABLED "INTERFACE-DISABLED "
+
#define ACS_EVENT_STARTED "ACS-STARTED "
#define ACS_EVENT_COMPLETED "ACS-COMPLETED "
#define ACS_EVENT_FAILED "ACS-FAILED "
@@ -216,6 +235,9 @@ extern "C" {
#define AP_CSA_FINISHED "AP-CSA-FINISHED "
+/* BSS Transition Management Response frame received */
+#define BSS_TM_RESP "BSS-TM-RESP "
+
/* BSS command information masks */
#define WPA_BSS_MASK_ALL 0xFFFDFFFF
@@ -237,6 +259,7 @@ extern "C" {
#define WPA_BSS_MASK_INTERNETW BIT(15)
#define WPA_BSS_MASK_WIFI_DISPLAY BIT(16)
#define WPA_BSS_MASK_DELIM BIT(17)
+#define WPA_BSS_MASK_MESH_SCAN BIT(18)
/* VENDOR_ELEM_* frame id values */
@@ -383,8 +406,6 @@ int wpa_ctrl_pending(struct wpa_ctrl *ctrl);
*/
int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl);
-char * wpa_ctrl_get_remote_ifname(struct wpa_ctrl *ctrl);
-
#ifdef ANDROID
/**
* wpa_ctrl_cleanup() - Delete any local UNIX domain socket files that
@@ -402,6 +423,8 @@ void wpa_ctrl_cleanup(void);
#define WPA_CTRL_IFACE_PORT_LIMIT 50 /* decremented from start */
#define WPA_GLOBAL_CTRL_IFACE_PORT 9878
#define WPA_GLOBAL_CTRL_IFACE_PORT_LIMIT 20 /* incremented from start */
+
+char * wpa_ctrl_get_remote_ifname(struct wpa_ctrl *ctrl);
#endif /* CONFIG_CTRL_IFACE_UDP */